From d01286d6be2415f1ba18bc1171c0e81ba0405a1b Mon Sep 17 00:00:00 2001 From: raihan <54474184+ryihan@users.noreply.github.com> Date: Tue, 26 Oct 2021 03:52:50 +0600 Subject: [PATCH] Update --- .../Helloworld/GreeterClient/Program.cs | 38 + .../Helloworld/GreeterServer/Program.cs | 51 + .../Greeter/Properties/AssemblyInfo.cs | 40 + .../GreeterClient/Program.cs | 38 + .../GreeterClient/Properties/AssemblyInfo.cs | 40 + .../GreeterServer/Program.cs | 51 + .../GreeterServer/Properties/AssemblyInfo.cs | 40 + .../Assets/Scripts/HelloWorldScript.cs | 38 + .../Assets/Scripts/HelloWorldTest.cs | 81 + .../Assets/Scripts/Helloworld.cs | 286 + .../Assets/Scripts/HelloworldGrpc.cs | 150 + .../Properties/AssemblyInfo.cs | 46 + .../Resources/Resource.designer.cs | 14016 ++++++++++++++++ .../HelloworldXamarin.iOS/AppDelegate.cs | 47 + .../HelloworldXamarin.iOS/Main.cs | 36 + .../Properties/AssemblyInfo.cs | 52 + .../HelloworldXamarin/App.xaml.cs | 44 + .../HelloworldXamarin/AssemblyInfo.cs | 19 + .../HelloworldXamarin/Helloworld.cs | 286 + .../HelloworldXamarin/HelloworldGrpc.cs | 150 + .../HelloworldXamarin/MainPage.xaml.cs | 79 + .../RouteGuide/RouteGuide/RouteGuideUtil.cs | 139 + .../RouteGuide/RouteGuideClient/Program.cs | 241 + .../RouteGuide/RouteGuideServer/Program.cs | 46 + .../RouteGuideServer/RouteGuideImpl.cs | 153 + examples/csharp/Xds/GreeterClient/Program.cs | 51 + examples/csharp/Xds/GreeterServer/Program.cs | 93 + .../Grpc.Auth/GoogleAuthInterceptors.cs | 111 + src/csharp/Grpc.Auth/GoogleGrpcCredentials.cs | 81 + .../Grpc.Auth/Properties/AssemblyInfo.cs | 29 + .../Grpc.Core.Api/AsyncAuthInterceptor.cs | 69 + src/csharp/Grpc.Core.Api/AsyncCallState.cs | 98 + .../Grpc.Core.Api/AsyncClientStreamingCall.cs | 155 + .../Grpc.Core.Api/AsyncDuplexStreamingCall.cs | 145 + .../Grpc.Core.Api/AsyncServerStreamingCall.cs | 126 + .../AsyncStreamReaderExtensions.cs | 50 + src/csharp/Grpc.Core.Api/AsyncUnaryCall.cs | 136 + src/csharp/Grpc.Core.Api/AuthContext.cs | 112 + src/csharp/Grpc.Core.Api/AuthProperty.cs | 109 + .../BindServiceMethodAttribute.cs | 59 + src/csharp/Grpc.Core.Api/CallCredentials.cs | 90 + .../CallCredentialsConfiguratorBase.cs | 39 + src/csharp/Grpc.Core.Api/CallFlags.cs | 45 + src/csharp/Grpc.Core.Api/CallInvoker.cs | 67 + src/csharp/Grpc.Core.Api/CallOptions.cs | 230 + src/csharp/Grpc.Core.Api/ChannelBase.cs | 82 + .../Grpc.Core.Api/ChannelCredentials.cs | 134 + .../ChannelCredentialsConfiguratorBase.cs | 44 + src/csharp/Grpc.Core.Api/ClientBase.cs | 231 + .../ContextPropagationOptions.cs | 59 + .../Grpc.Core.Api/ContextPropagationToken.cs | 35 + .../Grpc.Core.Api/DeserializationContext.cs | 66 + .../Grpc.Core.Api/IAsyncStreamReader.cs | 66 + .../Grpc.Core.Api/IAsyncStreamWriter.cs | 47 + .../Grpc.Core.Api/IClientStreamWriter.cs | 38 + .../Grpc.Core.Api/IServerStreamWriter.cs | 34 + .../Interceptors/CallInvokerExtensions.cs | 143 + .../Interceptors/ChannelExtensions.cs | 87 + .../Interceptors/ClientInterceptorContext.cs | 64 + .../Interceptors/InterceptingCallInvoker.cs | 96 + .../Grpc.Core.Api/Interceptors/Interceptor.cs | 405 + .../Internal/CodeAnalysisAttributes.cs | 151 + .../Internal/UnimplementedCallInvoker.cs | 60 + .../Grpc.Core.Api/KeyCertificatePair.cs | 68 + src/csharp/Grpc.Core.Api/Marshaller.cs | 138 + src/csharp/Grpc.Core.Api/Metadata.cs | 497 + src/csharp/Grpc.Core.Api/Method.cs | 176 + .../Grpc.Core.Api/Properties/AssemblyInfo.cs | 55 + src/csharp/Grpc.Core.Api/RpcException.cs | 109 + .../Grpc.Core.Api/SerializationContext.cs | 69 + src/csharp/Grpc.Core.Api/ServerCallContext.cs | 163 + src/csharp/Grpc.Core.Api/ServerMethods.cs | 58 + .../Grpc.Core.Api/ServerServiceDefinition.cs | 161 + src/csharp/Grpc.Core.Api/ServiceBinderBase.cs | 98 + src/csharp/Grpc.Core.Api/SslCredentials.cs | 122 + src/csharp/Grpc.Core.Api/Status.cs | 95 + src/csharp/Grpc.Core.Api/StatusCode.cs | 125 + .../Grpc.Core.Api/Utils/EncodingExtensions.cs | 54 + .../Grpc.Core.Api/Utils/GrpcPreconditions.cs | 105 + src/csharp/Grpc.Core.Api/VerifyPeerContext.cs | 48 + src/csharp/Grpc.Core.Api/Version.cs | 23 + src/csharp/Grpc.Core.Api/VersionInfo.cs | 43 + src/csharp/Grpc.Core.Api/WriteOptions.cs | 74 + .../Properties/AssemblyInfo.cs | 29 + src/csharp/Grpc.Core.Testing/TestCalls.cs | 76 + .../TestServerCallContext.cs | 107 + .../Grpc.Core.Tests/AppDomainUnloadTest.cs | 77 + src/csharp/Grpc.Core.Tests/AuthContextTest.cs | 71 + .../Grpc.Core.Tests/AuthPropertyTest.cs | 67 + .../Grpc.Core.Tests/CallCancellationTest.cs | 193 + .../Grpc.Core.Tests/CallCredentialsTest.cs | 50 + src/csharp/Grpc.Core.Tests/CallOptionsTest.cs | 98 + .../ChannelConnectivityTest.cs | 90 + .../Grpc.Core.Tests/ChannelCredentialsTest.cs | 67 + .../Grpc.Core.Tests/ChannelOptionsTest.cs | 90 + src/csharp/Grpc.Core.Tests/ChannelTest.cs | 127 + .../Grpc.Core.Tests/ClientServerTest.cs | 397 + src/csharp/Grpc.Core.Tests/CompressionTest.cs | 153 + .../Grpc.Core.Tests/ContextPropagationTest.cs | 181 + .../ContextualMarshallerTest.cs | 121 + src/csharp/Grpc.Core.Tests/FakeCredentials.cs | 50 + .../Grpc.Core.Tests/GrpcEnvironmentTest.cs | 94 + src/csharp/Grpc.Core.Tests/HalfcloseTest.cs | 82 + .../Interceptors/ClientInterceptorTest.cs | 228 + .../Interceptors/ServerInterceptorTest.cs | 173 + .../Internal/AsyncCallServerTest.cs | 194 + .../Internal/AsyncCallStateTest.cs | 82 + .../Grpc.Core.Tests/Internal/AsyncCallTest.cs | 766 + .../Internal/ChannelArgsSafeHandleTest.cs | 60 + .../Internal/CompletionQueueEventTest.cs | 40 + .../Internal/CompletionQueueSafeHandleTest.cs | 52 + .../DefaultDeserializationContextTest.cs | 230 + .../Internal/DefaultObjectPoolTest.cs | 95 + .../DefaultSerializationContextTest.cs | 207 + .../Internal/FakeBufferReaderManager.cs | 118 + .../Internal/FakeBufferReaderManagerTest.cs | 121 + .../Internal/FakeNativeCall.cs | 192 + .../Internal/MetadataArraySafeHandleTest.cs | 69 + .../Internal/ReusableSliceBufferTest.cs | 140 + .../Internal/SliceBufferSafeHandleTest.cs | 163 + .../Grpc.Core.Tests/Internal/SliceTest.cs | 66 + .../Grpc.Core.Tests/Internal/TimespecTest.cs | 176 + .../Internal/UserAgentStringProviderTest.cs | 63 + .../Internal/WellKnownStringsTest.cs | 62 + src/csharp/Grpc.Core.Tests/MarshallerTest.cs | 102 + .../Grpc.Core.Tests/MarshallingErrorsTest.cs | 169 + src/csharp/Grpc.Core.Tests/MetadataTest.cs | 374 + .../Grpc.Core.Tests/MockServiceHelper.cs | 234 + src/csharp/Grpc.Core.Tests/NUnitMain.cs | 40 + src/csharp/Grpc.Core.Tests/PInvokeTest.cs | 121 + src/csharp/Grpc.Core.Tests/PerformanceTest.cs | 84 + .../Properties/AssemblyInfo.cs | 29 + .../Grpc.Core.Tests/ResponseHeadersTest.cs | 192 + src/csharp/Grpc.Core.Tests/SanityTest.cs | 116 + .../Grpc.Core.Tests/ServerBindFailedTest.cs | 90 + src/csharp/Grpc.Core.Tests/ServerTest.cs | 113 + .../Grpc.Core.Tests/ShutdownHookClientTest.cs | 42 + .../ShutdownHookPendingCallTest.cs | 54 + .../Grpc.Core.Tests/ShutdownHookServerTest.cs | 43 + src/csharp/Grpc.Core.Tests/ShutdownTest.cs | 65 + .../Grpc.Core.Tests/ThreadingModelTest.cs | 99 + src/csharp/Grpc.Core.Tests/TimeoutsTest.cs | 135 + .../Grpc.Core.Tests/UserAgentStringTest.cs | 88 + src/csharp/Grpc.Core.Xamarin/Internal.cs | 24 + src/csharp/Grpc.Core/CallInvocationDetails.cs | 158 + src/csharp/Grpc.Core/Calls.cs | 143 + src/csharp/Grpc.Core/Channel.cs | 340 + src/csharp/Grpc.Core/ChannelOptions.cs | 258 + src/csharp/Grpc.Core/ChannelState.cs | 54 + src/csharp/Grpc.Core/CompressionLevel.cs | 48 + src/csharp/Grpc.Core/DefaultCallInvoker.cs | 98 + src/csharp/Grpc.Core/ForwardedTypes.cs | 78 + src/csharp/Grpc.Core/GrpcEnvironment.cs | 490 + .../ServerServiceDefinitionExtensions.cs | 129 + src/csharp/Grpc.Core/Internal/AsyncCall.cs | 681 + .../Grpc.Core/Internal/AsyncCallBase.cs | 401 + .../Grpc.Core/Internal/AsyncCallServer.cs | 266 + .../Grpc.Core/Internal/AtomicCounter.cs | 71 + .../Internal/AuthContextSafeHandle.cs | 107 + .../Internal/BatchContextSafeHandle.cs | 191 + .../Grpc.Core/Internal/CStringSafeHandle.cs | 44 + .../Internal/CallCredentialsSafeHandle.cs | 45 + src/csharp/Grpc.Core/Internal/CallError.cs | 79 + .../Internal/CallOptionsExtensions.cs | 57 + .../Grpc.Core/Internal/CallSafeHandle.cs | 263 + .../Internal/ChannelArgsSafeHandle.cs | 59 + .../Internal/ChannelCredentialsSafeHandle.cs | 64 + .../Grpc.Core/Internal/ChannelSafeHandle.cs | 88 + .../Grpc.Core/Internal/ClientRequestStream.cs | 65 + .../Internal/ClientResponseStream.cs | 71 + .../Grpc.Core/Internal/ClientSideStatus.cs | 55 + src/csharp/Grpc.Core/Internal/ClockType.cs | 38 + .../Internal/CommonPlatformDetection.cs | 129 + .../Internal/CompletionQueueEvent.cs | 59 + .../Internal/CompletionQueueSafeHandle.cs | 137 + .../Grpc.Core/Internal/CompletionRegistry.cs | 129 + .../Internal/ContextPropagationFlags.cs | 34 + .../Internal/ContextPropagationTokenImpl.cs | 119 + .../Internal/CoreErrorDetailException.cs | 35 + src/csharp/Grpc.Core/Internal/DebugStats.cs | 45 + .../DefaultCallCredentialsConfigurator.cs | 85 + .../DefaultChannelCredentialsConfigurator.cs | 163 + .../Internal/DefaultDeserializationContext.cs | 76 + .../Grpc.Core/Internal/DefaultObjectPool.cs | 205 + .../Internal/DefaultSerializationContext.cs | 115 + .../Internal/DefaultServerCallContext.cs | 108 + .../Internal/DefaultSslRootsOverride.cs | 57 + .../Grpc.Core/Internal/GrpcThreadPool.cs | 244 + src/csharp/Grpc.Core/Internal/INativeCall.cs | 94 + src/csharp/Grpc.Core/Internal/IObjectPool.cs | 35 + .../Grpc.Core/Internal/IPooledObject.cs | 34 + .../Internal/IServerResponseStream.cs | 38 + src/csharp/Grpc.Core/Internal/MarshalUtils.cs | 73 + .../Internal/MetadataArraySafeHandle.cs | 93 + .../Internal/MonoPInvokeCallbackAttribute.cs | 40 + .../Internal/NativeCallbackDispatcher.cs | 91 + .../Grpc.Core/Internal/NativeExtension.cs | 330 + .../Grpc.Core/Internal/NativeLogRedirector.cs | 90 + .../NativeMetadataCredentialsPlugin.cs | 100 + .../Internal/NativeMethods.Generated.cs | 3359 ++++ .../Grpc.Core/Internal/NativeMethods.cs | 68 + src/csharp/Grpc.Core/Internal/PlatformApis.cs | 253 + .../Internal/RequestCallContextSafeHandle.cs | 124 + .../Grpc.Core/Internal/ReusableSliceBuffer.cs | 106 + .../Internal/SafeHandleZeroIsInvalid.cs | 41 + .../Grpc.Core/Internal/ServerCallHandler.cs | 328 + src/csharp/Grpc.Core/Internal/ServerCalls.cs | 56 + .../Internal/ServerCredentialsSafeHandle.cs | 50 + .../Grpc.Core/Internal/ServerRequestStream.cs | 65 + .../Internal/ServerResponseStream.cs | 67 + src/csharp/Grpc.Core/Internal/ServerRpcNew.cs | 94 + .../Grpc.Core/Internal/ServerSafeHandle.cs | 96 + .../ServerServiceDefinitionExtensions.cs | 78 + src/csharp/Grpc.Core/Internal/Slice.cs | 59 + .../Internal/SliceBufferSafeHandle.cs | 166 + .../Grpc.Core/Internal/SliceMemoryManager.cs | 65 + src/csharp/Grpc.Core/Internal/Timespec.cs | 287 + .../Internal/UnimplementedCallInvoker.cs | 60 + .../Grpc.Core/Internal/UnmanagedLibrary.cs | 265 + .../Internal/UserAgentStringProvider.cs | 108 + .../Grpc.Core/Internal/WellKnownStrings.cs | 92 + src/csharp/Grpc.Core/Logging/ConsoleLogger.cs | 50 + src/csharp/Grpc.Core/Logging/ILogger.cs | 60 + src/csharp/Grpc.Core/Logging/LogLevel.cs | 48 + .../Grpc.Core/Logging/LogLevelFilterLogger.cs | 188 + src/csharp/Grpc.Core/Logging/NullLogger.cs | 107 + .../Grpc.Core/Logging/TextWriterLogger.cs | 161 + src/csharp/Grpc.Core/Profiling/IProfiler.cs | 34 + .../Grpc.Core/Profiling/ProfilerEntry.cs | 73 + .../Grpc.Core/Profiling/ProfilerScope.cs | 45 + src/csharp/Grpc.Core/Profiling/Profilers.cs | 119 + .../Grpc.Core/Properties/AssemblyInfo.cs | 50 + src/csharp/Grpc.Core/Server.cs | 487 + src/csharp/Grpc.Core/ServerCredentials.cs | 221 + src/csharp/Grpc.Core/ServerPort.cs | 105 + .../Grpc.Core/Utils/AsyncStreamExtensions.cs | 85 + src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs | 57 + src/csharp/Grpc.Core/Utils/TaskUtils.cs | 44 + .../Grpc.Examples.MathClient/MathClient.cs | 42 + .../Properties/AssemblyInfo.cs | 29 + .../Grpc.Examples.MathServer/MathServer.cs | 45 + .../Properties/AssemblyInfo.cs | 29 + .../MathClientMockableTest.cs | 101 + .../MathClientServerTests.cs | 177 + .../MathServiceImplTestabilityTest.cs | 47 + src/csharp/Grpc.Examples.Tests/NUnitMain.cs | 40 + .../Properties/AssemblyInfo.cs | 29 + src/csharp/Grpc.Examples/Math.cs | 1073 ++ src/csharp/Grpc.Examples/MathExamples.cs | 137 + src/csharp/Grpc.Examples/MathGrpc.cs | 367 + src/csharp/Grpc.Examples/MathServiceImpl.cs | 95 + .../Grpc.Examples/Properties/AssemblyInfo.cs | 29 + .../HealthClientServerTest.cs | 83 + .../HealthServiceImplTest.cs | 260 + .../Grpc.HealthCheck.Tests/NUnitMain.cs | 40 + .../Properties/AssemblyInfo.cs | 29 + .../TestResponseStreamWriter.cs | 72 + .../TestServerCallContext.cs | 57 + src/csharp/Grpc.HealthCheck/Health.cs | 450 + src/csharp/Grpc.HealthCheck/HealthGrpc.cs | 301 + .../Grpc.HealthCheck/HealthServiceImpl.cs | 277 + .../Properties/AssemblyInfo.cs | 35 + .../Grpc.IntegrationTesting.Client/Program.cs | 31 + .../Properties/AssemblyInfo.cs | 29 + .../Program.cs | 31 + .../Properties/AssemblyInfo.cs | 29 + .../Grpc.IntegrationTesting.Server/Program.cs | 30 + .../Properties/AssemblyInfo.cs | 29 + .../Program.cs | 30 + .../Properties/AssemblyInfo.cs | 29 + .../Program.cs | 31 + .../Properties/AssemblyInfo.cs | 29 + .../BenchmarkService.cs | 48 + .../BenchmarkServiceGrpc.cs | 407 + .../BenchmarkServiceImpl.cs | 58 + .../Grpc.IntegrationTesting/ClientRunners.cs | 364 + src/csharp/Grpc.IntegrationTesting/Control.cs | 6647 ++++++++ .../ControlExtensions.cs | 43 + .../CoreStats/Stats.cs | 941 ++ .../CustomErrorDetailsTest.cs | 129 + .../Grpc.IntegrationTesting/EchoMessages.cs | 2134 +++ src/csharp/Grpc.IntegrationTesting/Empty.cs | 204 + .../Grpc.IntegrationTesting/EmptyService.cs | 38 + .../EmptyServiceGrpc.cs | 101 + .../ExternalDnsClientServerTest.cs | 74 + .../ExternalDnsWithTracingClientServerTest.cs | 176 + .../GeneratedClientTest.cs | 67 + .../GeneratedServiceBaseTest.cs | 101 + .../Grpc.IntegrationTesting/GenericService.cs | 56 + .../Grpc.IntegrationTesting/Histogram.cs | 165 + .../Grpc.IntegrationTesting/HistogramTest.cs | 113 + .../Grpc.IntegrationTesting/IClientRunner.cs | 52 + .../Grpc.IntegrationTesting/IServerRunner.cs | 57 + .../InterarrivalTimers.cs | 133 + .../Grpc.IntegrationTesting/InteropClient.cs | 744 + .../InteropClientServerTest.cs | 146 + .../Grpc.IntegrationTesting/InteropServer.cs | 90 + .../Grpc.IntegrationTesting/Messages.cs | 5546 ++++++ .../MetadataCredentialsTest.cs | 269 + src/csharp/Grpc.IntegrationTesting/Metrics.cs | 735 + .../Grpc.IntegrationTesting/MetricsGrpc.cs | 262 + .../Grpc.IntegrationTesting/NUnitMain.cs | 40 + .../Grpc.IntegrationTesting/Payloads.cs | 999 ++ .../Properties/AssemblyInfo.cs | 29 + .../Grpc.IntegrationTesting/QpsWorker.cs | 87 + .../ReportQpsScenarioService.cs | 41 + .../ReportQpsScenarioServiceGrpc.cs | 206 + .../RunnerClientServerTest.cs | 95 + .../Grpc.IntegrationTesting/ServerRunners.cs | 163 + .../SslCredentialsTest.cs | 289 + src/csharp/Grpc.IntegrationTesting/Stats.cs | 1766 ++ .../StressTestClient.cs | 289 + src/csharp/Grpc.IntegrationTesting/Test.cs | 72 + .../TestCredentials.cs | 82 + .../Grpc.IntegrationTesting/TestGrpc.cs | 1625 ++ .../TestServiceImpl.cs | 122 + .../Grpc.IntegrationTesting/TimeStats.cs | 90 + .../UnobservedTaskExceptionTest.cs | 100 + .../Grpc.IntegrationTesting/WorkerService.cs | 45 + .../WorkerServiceGrpc.cs | 406 + .../WorkerServiceImpl.cs | 99 + .../XdsInteropClient.cs | 438 + .../XdsInteropClientTest.cs | 174 + .../AtomicCounterBenchmark.cs | 52 + .../CommonThreadedBase.cs | 129 + .../CompletionRegistryBenchmark.cs | 55 + .../PInvokeByteArrayBenchmark.cs | 54 + .../Grpc.Microbenchmarks/PingBenchmark.cs | 102 + src/csharp/Grpc.Microbenchmarks/Program.cs | 33 + .../ScalabityExampleBenchmark.cs | 56 + .../SendMessageBenchmark.cs | 91 + .../UnaryCallOverheadBenchmark.cs | 104 + src/csharp/Grpc.Microbenchmarks/Utf8Decode.cs | 70 + src/csharp/Grpc.Microbenchmarks/Utf8Encode.cs | 126 + src/csharp/Grpc.Reflection.Tests/NUnitMain.cs | 40 + .../Properties/AssemblyInfo.cs | 29 + .../ReflectionClientServerTest.cs | 140 + .../SymbolRegistryTest.cs | 48 + .../Properties/AssemblyInfo.cs | 29 + src/csharp/Grpc.Reflection/Reflection.cs | 2290 +++ src/csharp/Grpc.Reflection/ReflectionGrpc.cs | 184 + .../Grpc.Reflection/ReflectionServiceImpl.cs | 161 + src/csharp/Grpc.Reflection/SymbolRegistry.cs | 145 + .../Grpc.Tools.Tests/CSharpGeneratorTest.cs | 98 + .../Grpc.Tools.Tests/CppGeneratorTest.cs | 88 + .../Grpc.Tools.Tests/DepFileUtilTest.cs | 174 + src/csharp/Grpc.Tools.Tests/GeneratorTest.cs | 55 + .../Grpc.Tools.Tests/MsBuildAssemblyHelper.cs | 71 + src/csharp/Grpc.Tools.Tests/NUnitMain.cs | 32 + .../Grpc.Tools.Tests/ProtoCompileBasicTest.cs | 84 + .../ProtoCompileCommandLineGeneratorTest.cs | 269 + .../ProtoCompileCommandLinePrinterTest.cs | 51 + .../ProtoToolsPlatformTaskTest.cs | 158 + src/csharp/Grpc.Tools.Tests/Utils.cs | 46 + src/csharp/Grpc.Tools/Common.cs | 73 + src/csharp/Grpc.Tools/DepFileUtil.cs | 305 + src/csharp/Grpc.Tools/GeneratorServices.cs | 239 + .../Grpc.Tools/Properties/AssemblyInfo.cs | 27 + src/csharp/Grpc.Tools/ProtoCompile.cs | 588 + src/csharp/Grpc.Tools/ProtoCompilerOutputs.cs | 100 + .../Grpc.Tools/ProtoReadDependencies.cs | 78 + src/csharp/Grpc.Tools/ProtoToolsPlatform.cs | 72 + test/distrib/csharp/DistribTest/Program.cs | 74 + .../DistribTest/Properties/AssemblyInfo.cs | 54 + 364 files changed, 82949 insertions(+) create mode 100644 examples/csharp/Helloworld/GreeterClient/Program.cs create mode 100644 examples/csharp/Helloworld/GreeterServer/Program.cs create mode 100644 examples/csharp/HelloworldLegacyCsproj/Greeter/Properties/AssemblyInfo.cs create mode 100644 examples/csharp/HelloworldLegacyCsproj/GreeterClient/Program.cs create mode 100644 examples/csharp/HelloworldLegacyCsproj/GreeterClient/Properties/AssemblyInfo.cs create mode 100644 examples/csharp/HelloworldLegacyCsproj/GreeterServer/Program.cs create mode 100644 examples/csharp/HelloworldLegacyCsproj/GreeterServer/Properties/AssemblyInfo.cs create mode 100644 examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs create mode 100644 examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs create mode 100644 examples/csharp/HelloworldUnity/Assets/Scripts/Helloworld.cs create mode 100644 examples/csharp/HelloworldUnity/Assets/Scripts/HelloworldGrpc.cs create mode 100644 examples/csharp/HelloworldXamarin/HelloworldXamarin.Android/Properties/AssemblyInfo.cs create mode 100644 examples/csharp/HelloworldXamarin/HelloworldXamarin.Android/Resources/Resource.designer.cs create mode 100644 examples/csharp/HelloworldXamarin/HelloworldXamarin.iOS/AppDelegate.cs create mode 100644 examples/csharp/HelloworldXamarin/HelloworldXamarin.iOS/Main.cs create mode 100644 examples/csharp/HelloworldXamarin/HelloworldXamarin.iOS/Properties/AssemblyInfo.cs create mode 100644 examples/csharp/HelloworldXamarin/HelloworldXamarin/App.xaml.cs create mode 100644 examples/csharp/HelloworldXamarin/HelloworldXamarin/AssemblyInfo.cs create mode 100644 examples/csharp/HelloworldXamarin/HelloworldXamarin/Helloworld.cs create mode 100644 examples/csharp/HelloworldXamarin/HelloworldXamarin/HelloworldGrpc.cs create mode 100644 examples/csharp/HelloworldXamarin/HelloworldXamarin/MainPage.xaml.cs create mode 100644 examples/csharp/RouteGuide/RouteGuide/RouteGuideUtil.cs create mode 100644 examples/csharp/RouteGuide/RouteGuideClient/Program.cs create mode 100644 examples/csharp/RouteGuide/RouteGuideServer/Program.cs create mode 100644 examples/csharp/RouteGuide/RouteGuideServer/RouteGuideImpl.cs create mode 100644 examples/csharp/Xds/GreeterClient/Program.cs create mode 100644 examples/csharp/Xds/GreeterServer/Program.cs create mode 100644 src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs create mode 100644 src/csharp/Grpc.Auth/GoogleGrpcCredentials.cs create mode 100644 src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.Core.Api/AsyncAuthInterceptor.cs create mode 100644 src/csharp/Grpc.Core.Api/AsyncCallState.cs create mode 100644 src/csharp/Grpc.Core.Api/AsyncClientStreamingCall.cs create mode 100644 src/csharp/Grpc.Core.Api/AsyncDuplexStreamingCall.cs create mode 100644 src/csharp/Grpc.Core.Api/AsyncServerStreamingCall.cs create mode 100644 src/csharp/Grpc.Core.Api/AsyncStreamReaderExtensions.cs create mode 100644 src/csharp/Grpc.Core.Api/AsyncUnaryCall.cs create mode 100644 src/csharp/Grpc.Core.Api/AuthContext.cs create mode 100644 src/csharp/Grpc.Core.Api/AuthProperty.cs create mode 100644 src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs create mode 100644 src/csharp/Grpc.Core.Api/CallCredentials.cs create mode 100644 src/csharp/Grpc.Core.Api/CallCredentialsConfiguratorBase.cs create mode 100644 src/csharp/Grpc.Core.Api/CallFlags.cs create mode 100644 src/csharp/Grpc.Core.Api/CallInvoker.cs create mode 100644 src/csharp/Grpc.Core.Api/CallOptions.cs create mode 100644 src/csharp/Grpc.Core.Api/ChannelBase.cs create mode 100644 src/csharp/Grpc.Core.Api/ChannelCredentials.cs create mode 100644 src/csharp/Grpc.Core.Api/ChannelCredentialsConfiguratorBase.cs create mode 100644 src/csharp/Grpc.Core.Api/ClientBase.cs create mode 100644 src/csharp/Grpc.Core.Api/ContextPropagationOptions.cs create mode 100644 src/csharp/Grpc.Core.Api/ContextPropagationToken.cs create mode 100644 src/csharp/Grpc.Core.Api/DeserializationContext.cs create mode 100644 src/csharp/Grpc.Core.Api/IAsyncStreamReader.cs create mode 100644 src/csharp/Grpc.Core.Api/IAsyncStreamWriter.cs create mode 100644 src/csharp/Grpc.Core.Api/IClientStreamWriter.cs create mode 100644 src/csharp/Grpc.Core.Api/IServerStreamWriter.cs create mode 100644 src/csharp/Grpc.Core.Api/Interceptors/CallInvokerExtensions.cs create mode 100644 src/csharp/Grpc.Core.Api/Interceptors/ChannelExtensions.cs create mode 100644 src/csharp/Grpc.Core.Api/Interceptors/ClientInterceptorContext.cs create mode 100644 src/csharp/Grpc.Core.Api/Interceptors/InterceptingCallInvoker.cs create mode 100644 src/csharp/Grpc.Core.Api/Interceptors/Interceptor.cs create mode 100644 src/csharp/Grpc.Core.Api/Internal/CodeAnalysisAttributes.cs create mode 100644 src/csharp/Grpc.Core.Api/Internal/UnimplementedCallInvoker.cs create mode 100644 src/csharp/Grpc.Core.Api/KeyCertificatePair.cs create mode 100644 src/csharp/Grpc.Core.Api/Marshaller.cs create mode 100644 src/csharp/Grpc.Core.Api/Metadata.cs create mode 100644 src/csharp/Grpc.Core.Api/Method.cs create mode 100644 src/csharp/Grpc.Core.Api/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.Core.Api/RpcException.cs create mode 100644 src/csharp/Grpc.Core.Api/SerializationContext.cs create mode 100644 src/csharp/Grpc.Core.Api/ServerCallContext.cs create mode 100644 src/csharp/Grpc.Core.Api/ServerMethods.cs create mode 100644 src/csharp/Grpc.Core.Api/ServerServiceDefinition.cs create mode 100644 src/csharp/Grpc.Core.Api/ServiceBinderBase.cs create mode 100644 src/csharp/Grpc.Core.Api/SslCredentials.cs create mode 100644 src/csharp/Grpc.Core.Api/Status.cs create mode 100644 src/csharp/Grpc.Core.Api/StatusCode.cs create mode 100644 src/csharp/Grpc.Core.Api/Utils/EncodingExtensions.cs create mode 100644 src/csharp/Grpc.Core.Api/Utils/GrpcPreconditions.cs create mode 100644 src/csharp/Grpc.Core.Api/VerifyPeerContext.cs create mode 100644 src/csharp/Grpc.Core.Api/Version.cs create mode 100644 src/csharp/Grpc.Core.Api/VersionInfo.cs create mode 100644 src/csharp/Grpc.Core.Api/WriteOptions.cs create mode 100644 src/csharp/Grpc.Core.Testing/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.Core.Testing/TestCalls.cs create mode 100644 src/csharp/Grpc.Core.Testing/TestServerCallContext.cs create mode 100644 src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/AuthContextTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/AuthPropertyTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/CallCancellationTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/CallCredentialsTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/CallOptionsTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/ChannelConnectivityTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/ChannelCredentialsTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/ChannelOptionsTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/ChannelTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/ClientServerTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/CompressionTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/ContextualMarshallerTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/FakeCredentials.cs create mode 100644 src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/HalfcloseTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Interceptors/ClientInterceptorTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Interceptors/ServerInterceptorTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/AsyncCallStateTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/ChannelArgsSafeHandleTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/CompletionQueueEventTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/CompletionQueueSafeHandleTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/DefaultDeserializationContextTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/DefaultObjectPoolTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/DefaultSerializationContextTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/FakeBufferReaderManager.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/FakeBufferReaderManagerTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/ReusableSliceBufferTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/SliceBufferSafeHandleTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/SliceTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/UserAgentStringProviderTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Internal/WellKnownStringsTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/MarshallerTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/MetadataTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/MockServiceHelper.cs create mode 100644 src/csharp/Grpc.Core.Tests/NUnitMain.cs create mode 100644 src/csharp/Grpc.Core.Tests/PInvokeTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/PerformanceTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.Core.Tests/ResponseHeadersTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/SanityTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/ServerBindFailedTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/ServerTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/ShutdownHookClientTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/ShutdownHookPendingCallTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/ShutdownHookServerTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/ShutdownTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/ThreadingModelTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/TimeoutsTest.cs create mode 100644 src/csharp/Grpc.Core.Tests/UserAgentStringTest.cs create mode 100644 src/csharp/Grpc.Core.Xamarin/Internal.cs create mode 100644 src/csharp/Grpc.Core/CallInvocationDetails.cs create mode 100644 src/csharp/Grpc.Core/Calls.cs create mode 100644 src/csharp/Grpc.Core/Channel.cs create mode 100644 src/csharp/Grpc.Core/ChannelOptions.cs create mode 100644 src/csharp/Grpc.Core/ChannelState.cs create mode 100644 src/csharp/Grpc.Core/CompressionLevel.cs create mode 100644 src/csharp/Grpc.Core/DefaultCallInvoker.cs create mode 100644 src/csharp/Grpc.Core/ForwardedTypes.cs create mode 100644 src/csharp/Grpc.Core/GrpcEnvironment.cs create mode 100644 src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs create mode 100644 src/csharp/Grpc.Core/Internal/AsyncCall.cs create mode 100644 src/csharp/Grpc.Core/Internal/AsyncCallBase.cs create mode 100644 src/csharp/Grpc.Core/Internal/AsyncCallServer.cs create mode 100644 src/csharp/Grpc.Core/Internal/AtomicCounter.cs create mode 100644 src/csharp/Grpc.Core/Internal/AuthContextSafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Internal/CStringSafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Internal/CallError.cs create mode 100644 src/csharp/Grpc.Core/Internal/CallOptionsExtensions.cs create mode 100644 src/csharp/Grpc.Core/Internal/CallSafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Internal/ClientRequestStream.cs create mode 100644 src/csharp/Grpc.Core/Internal/ClientResponseStream.cs create mode 100644 src/csharp/Grpc.Core/Internal/ClientSideStatus.cs create mode 100644 src/csharp/Grpc.Core/Internal/ClockType.cs create mode 100644 src/csharp/Grpc.Core/Internal/CommonPlatformDetection.cs create mode 100644 src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs create mode 100644 src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Internal/CompletionRegistry.cs create mode 100644 src/csharp/Grpc.Core/Internal/ContextPropagationFlags.cs create mode 100644 src/csharp/Grpc.Core/Internal/ContextPropagationTokenImpl.cs create mode 100644 src/csharp/Grpc.Core/Internal/CoreErrorDetailException.cs create mode 100644 src/csharp/Grpc.Core/Internal/DebugStats.cs create mode 100644 src/csharp/Grpc.Core/Internal/DefaultCallCredentialsConfigurator.cs create mode 100644 src/csharp/Grpc.Core/Internal/DefaultChannelCredentialsConfigurator.cs create mode 100644 src/csharp/Grpc.Core/Internal/DefaultDeserializationContext.cs create mode 100644 src/csharp/Grpc.Core/Internal/DefaultObjectPool.cs create mode 100644 src/csharp/Grpc.Core/Internal/DefaultSerializationContext.cs create mode 100644 src/csharp/Grpc.Core/Internal/DefaultServerCallContext.cs create mode 100644 src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs create mode 100644 src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs create mode 100644 src/csharp/Grpc.Core/Internal/INativeCall.cs create mode 100644 src/csharp/Grpc.Core/Internal/IObjectPool.cs create mode 100644 src/csharp/Grpc.Core/Internal/IPooledObject.cs create mode 100644 src/csharp/Grpc.Core/Internal/IServerResponseStream.cs create mode 100644 src/csharp/Grpc.Core/Internal/MarshalUtils.cs create mode 100644 src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Internal/MonoPInvokeCallbackAttribute.cs create mode 100644 src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs create mode 100644 src/csharp/Grpc.Core/Internal/NativeExtension.cs create mode 100644 src/csharp/Grpc.Core/Internal/NativeLogRedirector.cs create mode 100644 src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs create mode 100644 src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs create mode 100644 src/csharp/Grpc.Core/Internal/NativeMethods.cs create mode 100644 src/csharp/Grpc.Core/Internal/PlatformApis.cs create mode 100644 src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Internal/ReusableSliceBuffer.cs create mode 100644 src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs create mode 100644 src/csharp/Grpc.Core/Internal/ServerCallHandler.cs create mode 100644 src/csharp/Grpc.Core/Internal/ServerCalls.cs create mode 100644 src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Internal/ServerRequestStream.cs create mode 100644 src/csharp/Grpc.Core/Internal/ServerResponseStream.cs create mode 100644 src/csharp/Grpc.Core/Internal/ServerRpcNew.cs create mode 100644 src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs create mode 100644 src/csharp/Grpc.Core/Internal/Slice.cs create mode 100644 src/csharp/Grpc.Core/Internal/SliceBufferSafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Internal/SliceMemoryManager.cs create mode 100644 src/csharp/Grpc.Core/Internal/Timespec.cs create mode 100644 src/csharp/Grpc.Core/Internal/UnimplementedCallInvoker.cs create mode 100644 src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs create mode 100644 src/csharp/Grpc.Core/Internal/UserAgentStringProvider.cs create mode 100644 src/csharp/Grpc.Core/Internal/WellKnownStrings.cs create mode 100644 src/csharp/Grpc.Core/Logging/ConsoleLogger.cs create mode 100644 src/csharp/Grpc.Core/Logging/ILogger.cs create mode 100644 src/csharp/Grpc.Core/Logging/LogLevel.cs create mode 100644 src/csharp/Grpc.Core/Logging/LogLevelFilterLogger.cs create mode 100644 src/csharp/Grpc.Core/Logging/NullLogger.cs create mode 100644 src/csharp/Grpc.Core/Logging/TextWriterLogger.cs create mode 100644 src/csharp/Grpc.Core/Profiling/IProfiler.cs create mode 100644 src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs create mode 100644 src/csharp/Grpc.Core/Profiling/ProfilerScope.cs create mode 100644 src/csharp/Grpc.Core/Profiling/Profilers.cs create mode 100644 src/csharp/Grpc.Core/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.Core/Server.cs create mode 100644 src/csharp/Grpc.Core/ServerCredentials.cs create mode 100644 src/csharp/Grpc.Core/ServerPort.cs create mode 100644 src/csharp/Grpc.Core/Utils/AsyncStreamExtensions.cs create mode 100644 src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs create mode 100644 src/csharp/Grpc.Core/Utils/TaskUtils.cs create mode 100644 src/csharp/Grpc.Examples.MathClient/MathClient.cs create mode 100644 src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.Examples.MathServer/MathServer.cs create mode 100644 src/csharp/Grpc.Examples.MathServer/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.Examples.Tests/MathClientMockableTest.cs create mode 100644 src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs create mode 100644 src/csharp/Grpc.Examples.Tests/MathServiceImplTestabilityTest.cs create mode 100644 src/csharp/Grpc.Examples.Tests/NUnitMain.cs create mode 100644 src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.Examples/Math.cs create mode 100644 src/csharp/Grpc.Examples/MathExamples.cs create mode 100644 src/csharp/Grpc.Examples/MathGrpc.cs create mode 100644 src/csharp/Grpc.Examples/MathServiceImpl.cs create mode 100644 src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs create mode 100644 src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs create mode 100644 src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs create mode 100644 src/csharp/Grpc.HealthCheck.Tests/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.HealthCheck.Tests/TestResponseStreamWriter.cs create mode 100644 src/csharp/Grpc.HealthCheck.Tests/TestServerCallContext.cs create mode 100644 src/csharp/Grpc.HealthCheck/Health.cs create mode 100644 src/csharp/Grpc.HealthCheck/HealthGrpc.cs create mode 100644 src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs create mode 100644 src/csharp/Grpc.HealthCheck/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.IntegrationTesting.Client/Program.cs create mode 100644 src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.IntegrationTesting.QpsWorker/Program.cs create mode 100644 src/csharp/Grpc.IntegrationTesting.QpsWorker/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.IntegrationTesting.Server/Program.cs create mode 100644 src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.IntegrationTesting.StressClient/Program.cs create mode 100644 src/csharp/Grpc.IntegrationTesting.StressClient/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.IntegrationTesting.XdsClient/Program.cs create mode 100644 src/csharp/Grpc.IntegrationTesting.XdsClient/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/BenchmarkService.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/ClientRunners.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/Control.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/ControlExtensions.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/CoreStats/Stats.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/CustomErrorDetailsTest.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/EchoMessages.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/Empty.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/EmptyService.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/ExternalDnsClientServerTest.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/ExternalDnsWithTracingClientServerTest.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/GeneratedServiceBaseTest.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/GenericService.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/Histogram.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/HistogramTest.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/IClientRunner.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/IServerRunner.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/InterarrivalTimers.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/InteropClient.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/InteropServer.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/Messages.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/Metrics.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/NUnitMain.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/Payloads.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/QpsWorker.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioService.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/ServerRunners.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/Stats.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/StressTestClient.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/Test.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/TestCredentials.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/TestGrpc.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/TimeStats.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/UnobservedTaskExceptionTest.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/WorkerService.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/XdsInteropClient.cs create mode 100644 src/csharp/Grpc.IntegrationTesting/XdsInteropClientTest.cs create mode 100644 src/csharp/Grpc.Microbenchmarks/AtomicCounterBenchmark.cs create mode 100644 src/csharp/Grpc.Microbenchmarks/CommonThreadedBase.cs create mode 100644 src/csharp/Grpc.Microbenchmarks/CompletionRegistryBenchmark.cs create mode 100644 src/csharp/Grpc.Microbenchmarks/PInvokeByteArrayBenchmark.cs create mode 100644 src/csharp/Grpc.Microbenchmarks/PingBenchmark.cs create mode 100644 src/csharp/Grpc.Microbenchmarks/Program.cs create mode 100644 src/csharp/Grpc.Microbenchmarks/ScalabityExampleBenchmark.cs create mode 100644 src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs create mode 100644 src/csharp/Grpc.Microbenchmarks/UnaryCallOverheadBenchmark.cs create mode 100644 src/csharp/Grpc.Microbenchmarks/Utf8Decode.cs create mode 100644 src/csharp/Grpc.Microbenchmarks/Utf8Encode.cs create mode 100644 src/csharp/Grpc.Reflection.Tests/NUnitMain.cs create mode 100644 src/csharp/Grpc.Reflection.Tests/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.Reflection.Tests/ReflectionClientServerTest.cs create mode 100644 src/csharp/Grpc.Reflection.Tests/SymbolRegistryTest.cs create mode 100644 src/csharp/Grpc.Reflection/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.Reflection/Reflection.cs create mode 100644 src/csharp/Grpc.Reflection/ReflectionGrpc.cs create mode 100644 src/csharp/Grpc.Reflection/ReflectionServiceImpl.cs create mode 100644 src/csharp/Grpc.Reflection/SymbolRegistry.cs create mode 100644 src/csharp/Grpc.Tools.Tests/CSharpGeneratorTest.cs create mode 100644 src/csharp/Grpc.Tools.Tests/CppGeneratorTest.cs create mode 100644 src/csharp/Grpc.Tools.Tests/DepFileUtilTest.cs create mode 100644 src/csharp/Grpc.Tools.Tests/GeneratorTest.cs create mode 100644 src/csharp/Grpc.Tools.Tests/MsBuildAssemblyHelper.cs create mode 100644 src/csharp/Grpc.Tools.Tests/NUnitMain.cs create mode 100644 src/csharp/Grpc.Tools.Tests/ProtoCompileBasicTest.cs create mode 100644 src/csharp/Grpc.Tools.Tests/ProtoCompileCommandLineGeneratorTest.cs create mode 100644 src/csharp/Grpc.Tools.Tests/ProtoCompileCommandLinePrinterTest.cs create mode 100644 src/csharp/Grpc.Tools.Tests/ProtoToolsPlatformTaskTest.cs create mode 100644 src/csharp/Grpc.Tools.Tests/Utils.cs create mode 100644 src/csharp/Grpc.Tools/Common.cs create mode 100644 src/csharp/Grpc.Tools/DepFileUtil.cs create mode 100644 src/csharp/Grpc.Tools/GeneratorServices.cs create mode 100644 src/csharp/Grpc.Tools/Properties/AssemblyInfo.cs create mode 100644 src/csharp/Grpc.Tools/ProtoCompile.cs create mode 100644 src/csharp/Grpc.Tools/ProtoCompilerOutputs.cs create mode 100644 src/csharp/Grpc.Tools/ProtoReadDependencies.cs create mode 100644 src/csharp/Grpc.Tools/ProtoToolsPlatform.cs create mode 100644 test/distrib/csharp/DistribTest/Program.cs create mode 100644 test/distrib/csharp/DistribTest/Properties/AssemblyInfo.cs diff --git a/examples/csharp/Helloworld/GreeterClient/Program.cs b/examples/csharp/Helloworld/GreeterClient/Program.cs new file mode 100644 index 00000000..c72ab634 --- /dev/null +++ b/examples/csharp/Helloworld/GreeterClient/Program.cs @@ -0,0 +1,38 @@ +// Copyright 2015 gRPC authors. +// +// 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. + +using System; +using Grpc.Core; +using Helloworld; + +namespace GreeterClient +{ + class Program + { + public static void Main(string[] args) + { + Channel channel = new Channel("127.0.0.1:30051", ChannelCredentials.Insecure); + + var client = new Greeter.GreeterClient(channel); + String user = "you"; + + var reply = client.SayHello(new HelloRequest { Name = user }); + Console.WriteLine("Greeting: " + reply.Message); + + channel.ShutdownAsync().Wait(); + Console.WriteLine("Press any key to exit..."); + Console.ReadKey(); + } + } +} diff --git a/examples/csharp/Helloworld/GreeterServer/Program.cs b/examples/csharp/Helloworld/GreeterServer/Program.cs new file mode 100644 index 00000000..c528a8ff --- /dev/null +++ b/examples/csharp/Helloworld/GreeterServer/Program.cs @@ -0,0 +1,51 @@ +// Copyright 2015 gRPC authors. +// +// 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. + +using System; +using System.Threading.Tasks; +using Grpc.Core; +using Helloworld; + +namespace GreeterServer +{ + class GreeterImpl : Greeter.GreeterBase + { + // Server side handler of the SayHello RPC + public override Task SayHello(HelloRequest request, ServerCallContext context) + { + return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); + } + } + + class Program + { + const int Port = 30051; + + public static void Main(string[] args) + { + Server server = new Server + { + Services = { Greeter.BindService(new GreeterImpl()) }, + Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } + }; + server.Start(); + + Console.WriteLine("Greeter server listening on port " + Port); + Console.WriteLine("Press any key to stop the server..."); + Console.ReadKey(); + + server.ShutdownAsync().Wait(); + } + } +} diff --git a/examples/csharp/HelloworldLegacyCsproj/Greeter/Properties/AssemblyInfo.cs b/examples/csharp/HelloworldLegacyCsproj/Greeter/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..bdf394f8 --- /dev/null +++ b/examples/csharp/HelloworldLegacyCsproj/Greeter/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. +[assembly: AssemblyTitle("Greeter")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("jtattermusch")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. +[assembly: AssemblyVersion("1.0.*")] +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/examples/csharp/HelloworldLegacyCsproj/GreeterClient/Program.cs b/examples/csharp/HelloworldLegacyCsproj/GreeterClient/Program.cs new file mode 100644 index 00000000..c72ab634 --- /dev/null +++ b/examples/csharp/HelloworldLegacyCsproj/GreeterClient/Program.cs @@ -0,0 +1,38 @@ +// Copyright 2015 gRPC authors. +// +// 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. + +using System; +using Grpc.Core; +using Helloworld; + +namespace GreeterClient +{ + class Program + { + public static void Main(string[] args) + { + Channel channel = new Channel("127.0.0.1:30051", ChannelCredentials.Insecure); + + var client = new Greeter.GreeterClient(channel); + String user = "you"; + + var reply = client.SayHello(new HelloRequest { Name = user }); + Console.WriteLine("Greeting: " + reply.Message); + + channel.ShutdownAsync().Wait(); + Console.WriteLine("Press any key to exit..."); + Console.ReadKey(); + } + } +} diff --git a/examples/csharp/HelloworldLegacyCsproj/GreeterClient/Properties/AssemblyInfo.cs b/examples/csharp/HelloworldLegacyCsproj/GreeterClient/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..c88280b4 --- /dev/null +++ b/examples/csharp/HelloworldLegacyCsproj/GreeterClient/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. +[assembly: AssemblyTitle("GreeterClient")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("jtattermusch")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. +[assembly: AssemblyVersion("1.0.*")] +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/examples/csharp/HelloworldLegacyCsproj/GreeterServer/Program.cs b/examples/csharp/HelloworldLegacyCsproj/GreeterServer/Program.cs new file mode 100644 index 00000000..c528a8ff --- /dev/null +++ b/examples/csharp/HelloworldLegacyCsproj/GreeterServer/Program.cs @@ -0,0 +1,51 @@ +// Copyright 2015 gRPC authors. +// +// 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. + +using System; +using System.Threading.Tasks; +using Grpc.Core; +using Helloworld; + +namespace GreeterServer +{ + class GreeterImpl : Greeter.GreeterBase + { + // Server side handler of the SayHello RPC + public override Task SayHello(HelloRequest request, ServerCallContext context) + { + return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); + } + } + + class Program + { + const int Port = 30051; + + public static void Main(string[] args) + { + Server server = new Server + { + Services = { Greeter.BindService(new GreeterImpl()) }, + Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } + }; + server.Start(); + + Console.WriteLine("Greeter server listening on port " + Port); + Console.WriteLine("Press any key to stop the server..."); + Console.ReadKey(); + + server.ShutdownAsync().Wait(); + } + } +} diff --git a/examples/csharp/HelloworldLegacyCsproj/GreeterServer/Properties/AssemblyInfo.cs b/examples/csharp/HelloworldLegacyCsproj/GreeterServer/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..c0f2961c --- /dev/null +++ b/examples/csharp/HelloworldLegacyCsproj/GreeterServer/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. +[assembly: AssemblyTitle("GreeterServer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("jtattermusch")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. +[assembly: AssemblyVersion("1.0.*")] +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs new file mode 100644 index 00000000..0dad0f6a --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldScript.cs @@ -0,0 +1,38 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using UnityEngine; +using UnityEngine.UI; + +public class HelloWorldScript : MonoBehaviour { + int counter = 1; + + // Use this for initialization + void Start () {} + + // Update is called once per frame + void Update() {} + + // Ran when button is clicked + public void RunHelloWorld(Text text) + { + var reply = HelloWorldTest.Greet("Unity " + counter); + text.text = "Greeting: " + reply.Message; + counter++; + } +} diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs new file mode 100644 index 00000000..53bc5fb4 --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloWorldTest.cs @@ -0,0 +1,81 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using UnityEngine; +using System.Threading.Tasks; +using System; +using Grpc.Core; +using Helloworld; + +class HelloWorldTest +{ + // Can be run from commandline. + // Example command: + // "/Applications/Unity/Unity.app/Contents/MacOS/Unity -quit -batchmode -nographics -executeMethod HelloWorldTest.RunHelloWorld -logfile" + public static void RunHelloWorld() + { + Application.SetStackTraceLogType(LogType.Log, StackTraceLogType.None); + + Debug.Log("=============================================================="); + Debug.Log("Starting tests"); + Debug.Log("=============================================================="); + + Debug.Log("Application.platform: " + Application.platform); + Debug.Log("Environment.OSVersion: " + Environment.OSVersion); + + var reply = Greet("Unity"); + Debug.Log("Greeting: " + reply.Message); + + Debug.Log("=============================================================="); + Debug.Log("Tests finished successfully."); + Debug.Log("=============================================================="); + } + + public static HelloReply Greet(string greeting) + { + const int Port = 30051; + + Server server = new Server + { + Services = { Greeter.BindService(new GreeterImpl()) }, + Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } + }; + server.Start(); + + Channel channel = new Channel("127.0.0.1:30051", ChannelCredentials.Insecure); + + var client = new Greeter.GreeterClient(channel); + + var reply = client.SayHello(new HelloRequest { Name = greeting }); + + channel.ShutdownAsync().Wait(); + + server.ShutdownAsync().Wait(); + + return reply; + } + + class GreeterImpl : Greeter.GreeterBase + { + // Server side handler of the SayHello RPC + public override Task SayHello(HelloRequest request, ServerCallContext context) + { + return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); + } + } +} diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/Helloworld.cs b/examples/csharp/HelloworldUnity/Assets/Scripts/Helloworld.cs new file mode 100644 index 00000000..ecfc8e13 --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/Helloworld.cs @@ -0,0 +1,286 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: helloworld.proto +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Helloworld { + + /// Holder for reflection information generated from helloworld.proto + public static partial class HelloworldReflection { + + #region Descriptor + /// File descriptor for helloworld.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static HelloworldReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChBoZWxsb3dvcmxkLnByb3RvEgpoZWxsb3dvcmxkIhwKDEhlbGxvUmVxdWVz", + "dBIMCgRuYW1lGAEgASgJIh0KCkhlbGxvUmVwbHkSDwoHbWVzc2FnZRgBIAEo", + "CTJJCgdHcmVldGVyEj4KCFNheUhlbGxvEhguaGVsbG93b3JsZC5IZWxsb1Jl", + "cXVlc3QaFi5oZWxsb3dvcmxkLkhlbGxvUmVwbHkiAEI2Chtpby5ncnBjLmV4", + "YW1wbGVzLmhlbGxvd29ybGRCD0hlbGxvV29ybGRQcm90b1ABogIDSExXYgZw", + "cm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloRequest), global::Helloworld.HelloRequest.Parser, new[]{ "Name" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloReply), global::Helloworld.HelloReply.Parser, new[]{ "Message" }, null, null, null) + })); + } + #endregion + + } + #region Messages + /// + /// The request message containing the user's name. + /// + public sealed partial class HelloRequest : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HelloRequest()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Helloworld.HelloworldReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloRequest(HelloRequest other) : this() { + name_ = other.name_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloRequest Clone() { + return new HelloRequest(this); + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 1; + private string name_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as HelloRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(HelloRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Name != other.Name) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Name.Length != 0) hash ^= Name.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(HelloRequest other) { + if (other == null) { + return; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + Name = input.ReadString(); + break; + } + } + } + } + + } + + /// + /// The response message containing the greetings + /// + public sealed partial class HelloReply : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HelloReply()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Helloworld.HelloworldReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloReply() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloReply(HelloReply other) : this() { + message_ = other.message_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloReply Clone() { + return new HelloReply(this); + } + + /// Field number for the "message" field. + public const int MessageFieldNumber = 1; + private string message_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Message { + get { return message_; } + set { + message_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as HelloReply); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(HelloReply other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Message != other.Message) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Message.Length != 0) hash ^= Message.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Message.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Message); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Message.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Message); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(HelloReply other) { + if (other == null) { + return; + } + if (other.Message.Length != 0) { + Message = other.Message; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + Message = input.ReadString(); + break; + } + } + } + } + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/examples/csharp/HelloworldUnity/Assets/Scripts/HelloworldGrpc.cs b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloworldGrpc.cs new file mode 100644 index 00000000..c808884e --- /dev/null +++ b/examples/csharp/HelloworldUnity/Assets/Scripts/HelloworldGrpc.cs @@ -0,0 +1,150 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: helloworld.proto +// Original file comments: +// Copyright 2015 gRPC authors. +// +// 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. +// +#pragma warning disable 1591 +#region Designer generated code + +using System; +using System.Threading; +using System.Threading.Tasks; +using grpc = global::Grpc.Core; + +namespace Helloworld { + /// + /// The greeting service definition. + /// + public static partial class Greeter + { + static readonly string __ServiceName = "helloworld.Greeter"; + + static readonly grpc::Marshaller __Marshaller_HelloRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloRequest.Parser.ParseFrom); + static readonly grpc::Marshaller __Marshaller_HelloReply = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloReply.Parser.ParseFrom); + + static readonly grpc::Method __Method_SayHello = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "SayHello", + __Marshaller_HelloRequest, + __Marshaller_HelloReply); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Helloworld.HelloworldReflection.Descriptor.Services[0]; } + } + + /// Base class for server-side implementations of Greeter + public abstract partial class GreeterBase + { + /// + /// Sends a greeting + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + public virtual global::System.Threading.Tasks.Task SayHello(global::Helloworld.HelloRequest request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for Greeter + public partial class GreeterClient : grpc::ClientBase + { + /// Creates a new client for Greeter + /// The channel to use to make remote calls. + public GreeterClient(grpc::Channel channel) : base(channel) + { + } + /// Creates a new client for Greeter that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + public GreeterClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + protected GreeterClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + protected GreeterClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// Sends a greeting + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return SayHello(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Sends a greeting + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_SayHello, null, options, request); + } + /// + /// Sends a greeting + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + public virtual grpc::AsyncUnaryCall SayHelloAsync(global::Helloworld.HelloRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return SayHelloAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Sends a greeting + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + public virtual grpc::AsyncUnaryCall SayHelloAsync(global::Helloworld.HelloRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_SayHello, null, options, request); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + protected override GreeterClient NewInstance(ClientBaseConfiguration configuration) + { + return new GreeterClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + public static grpc::ServerServiceDefinition BindService(GreeterBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_SayHello, serviceImpl.SayHello).Build(); + } + + } +} +#endregion diff --git a/examples/csharp/HelloworldXamarin/HelloworldXamarin.Android/Properties/AssemblyInfo.cs b/examples/csharp/HelloworldXamarin/HelloworldXamarin.Android/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..ec1149ee --- /dev/null +++ b/examples/csharp/HelloworldXamarin/HelloworldXamarin.Android/Properties/AssemblyInfo.cs @@ -0,0 +1,46 @@ +#region Copyright notice and license +// Copyright 2020 The gRPC Authors +// +// 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. +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Android.App; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("HelloworldXamarin.Android")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("HelloworldXamarin.Android")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + +// Add some common permissions, these can be removed if not needed +[assembly: UsesPermission(Android.Manifest.Permission.Internet)] +[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)] diff --git a/examples/csharp/HelloworldXamarin/HelloworldXamarin.Android/Resources/Resource.designer.cs b/examples/csharp/HelloworldXamarin/HelloworldXamarin.Android/Resources/Resource.designer.cs new file mode 100644 index 00000000..23236aea --- /dev/null +++ b/examples/csharp/HelloworldXamarin/HelloworldXamarin.Android/Resources/Resource.designer.cs @@ -0,0 +1,14016 @@ +#region Copyright notice and license +// Copyright 2020 The gRPC Authors +// +// 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. +#endregion + +#pragma warning disable 1591 +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +[assembly: global::Android.Runtime.ResourceDesignerAttribute("HelloworldXamarin.Droid.Resource", IsApplication=true)] + +namespace HelloworldXamarin.Droid +{ + + + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")] + public partial class Resource + { + + static Resource() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + public static void UpdateIdValues() + { + global::Xamarin.Essentials.Resource.Attribute.alpha = global::HelloworldXamarin.Droid.Resource.Attribute.alpha; + global::Xamarin.Essentials.Resource.Attribute.coordinatorLayoutStyle = global::HelloworldXamarin.Droid.Resource.Attribute.coordinatorLayoutStyle; + global::Xamarin.Essentials.Resource.Attribute.font = global::HelloworldXamarin.Droid.Resource.Attribute.font; + global::Xamarin.Essentials.Resource.Attribute.fontProviderAuthority = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderAuthority; + global::Xamarin.Essentials.Resource.Attribute.fontProviderCerts = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderCerts; + global::Xamarin.Essentials.Resource.Attribute.fontProviderFetchStrategy = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderFetchStrategy; + global::Xamarin.Essentials.Resource.Attribute.fontProviderFetchTimeout = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderFetchTimeout; + global::Xamarin.Essentials.Resource.Attribute.fontProviderPackage = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderPackage; + global::Xamarin.Essentials.Resource.Attribute.fontProviderQuery = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderQuery; + global::Xamarin.Essentials.Resource.Attribute.fontStyle = global::HelloworldXamarin.Droid.Resource.Attribute.fontStyle; + global::Xamarin.Essentials.Resource.Attribute.fontVariationSettings = global::HelloworldXamarin.Droid.Resource.Attribute.fontVariationSettings; + global::Xamarin.Essentials.Resource.Attribute.fontWeight = global::HelloworldXamarin.Droid.Resource.Attribute.fontWeight; + global::Xamarin.Essentials.Resource.Attribute.keylines = global::HelloworldXamarin.Droid.Resource.Attribute.keylines; + global::Xamarin.Essentials.Resource.Attribute.layout_anchor = global::HelloworldXamarin.Droid.Resource.Attribute.layout_anchor; + global::Xamarin.Essentials.Resource.Attribute.layout_anchorGravity = global::HelloworldXamarin.Droid.Resource.Attribute.layout_anchorGravity; + global::Xamarin.Essentials.Resource.Attribute.layout_behavior = global::HelloworldXamarin.Droid.Resource.Attribute.layout_behavior; + global::Xamarin.Essentials.Resource.Attribute.layout_dodgeInsetEdges = global::HelloworldXamarin.Droid.Resource.Attribute.layout_dodgeInsetEdges; + global::Xamarin.Essentials.Resource.Attribute.layout_insetEdge = global::HelloworldXamarin.Droid.Resource.Attribute.layout_insetEdge; + global::Xamarin.Essentials.Resource.Attribute.layout_keyline = global::HelloworldXamarin.Droid.Resource.Attribute.layout_keyline; + global::Xamarin.Essentials.Resource.Attribute.statusBarBackground = global::HelloworldXamarin.Droid.Resource.Attribute.statusBarBackground; + global::Xamarin.Essentials.Resource.Attribute.ttcIndex = global::HelloworldXamarin.Droid.Resource.Attribute.ttcIndex; + global::Xamarin.Essentials.Resource.Color.browser_actions_bg_grey = global::HelloworldXamarin.Droid.Resource.Color.browser_actions_bg_grey; + global::Xamarin.Essentials.Resource.Color.browser_actions_divider_color = global::HelloworldXamarin.Droid.Resource.Color.browser_actions_divider_color; + global::Xamarin.Essentials.Resource.Color.browser_actions_text_color = global::HelloworldXamarin.Droid.Resource.Color.browser_actions_text_color; + global::Xamarin.Essentials.Resource.Color.browser_actions_title_color = global::HelloworldXamarin.Droid.Resource.Color.browser_actions_title_color; + global::Xamarin.Essentials.Resource.Color.notification_action_color_filter = global::HelloworldXamarin.Droid.Resource.Color.notification_action_color_filter; + global::Xamarin.Essentials.Resource.Color.notification_icon_bg_color = global::HelloworldXamarin.Droid.Resource.Color.notification_icon_bg_color; + global::Xamarin.Essentials.Resource.Color.ripple_material_light = global::HelloworldXamarin.Droid.Resource.Color.ripple_material_light; + global::Xamarin.Essentials.Resource.Color.secondary_text_default_material_light = global::HelloworldXamarin.Droid.Resource.Color.secondary_text_default_material_light; + global::Xamarin.Essentials.Resource.Dimension.browser_actions_context_menu_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.browser_actions_context_menu_max_width; + global::Xamarin.Essentials.Resource.Dimension.browser_actions_context_menu_min_padding = global::HelloworldXamarin.Droid.Resource.Dimension.browser_actions_context_menu_min_padding; + global::Xamarin.Essentials.Resource.Dimension.compat_button_inset_horizontal_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_button_inset_horizontal_material; + global::Xamarin.Essentials.Resource.Dimension.compat_button_inset_vertical_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_button_inset_vertical_material; + global::Xamarin.Essentials.Resource.Dimension.compat_button_padding_horizontal_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_button_padding_horizontal_material; + global::Xamarin.Essentials.Resource.Dimension.compat_button_padding_vertical_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_button_padding_vertical_material; + global::Xamarin.Essentials.Resource.Dimension.compat_control_corner_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_control_corner_material; + global::Xamarin.Essentials.Resource.Dimension.compat_notification_large_icon_max_height = global::HelloworldXamarin.Droid.Resource.Dimension.compat_notification_large_icon_max_height; + global::Xamarin.Essentials.Resource.Dimension.compat_notification_large_icon_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.compat_notification_large_icon_max_width; + global::Xamarin.Essentials.Resource.Dimension.notification_action_icon_size = global::HelloworldXamarin.Droid.Resource.Dimension.notification_action_icon_size; + global::Xamarin.Essentials.Resource.Dimension.notification_action_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.notification_action_text_size; + global::Xamarin.Essentials.Resource.Dimension.notification_big_circle_margin = global::HelloworldXamarin.Droid.Resource.Dimension.notification_big_circle_margin; + global::Xamarin.Essentials.Resource.Dimension.notification_content_margin_start = global::HelloworldXamarin.Droid.Resource.Dimension.notification_content_margin_start; + global::Xamarin.Essentials.Resource.Dimension.notification_large_icon_height = global::HelloworldXamarin.Droid.Resource.Dimension.notification_large_icon_height; + global::Xamarin.Essentials.Resource.Dimension.notification_large_icon_width = global::HelloworldXamarin.Droid.Resource.Dimension.notification_large_icon_width; + global::Xamarin.Essentials.Resource.Dimension.notification_main_column_padding_top = global::HelloworldXamarin.Droid.Resource.Dimension.notification_main_column_padding_top; + global::Xamarin.Essentials.Resource.Dimension.notification_media_narrow_margin = global::HelloworldXamarin.Droid.Resource.Dimension.notification_media_narrow_margin; + global::Xamarin.Essentials.Resource.Dimension.notification_right_icon_size = global::HelloworldXamarin.Droid.Resource.Dimension.notification_right_icon_size; + global::Xamarin.Essentials.Resource.Dimension.notification_right_side_padding_top = global::HelloworldXamarin.Droid.Resource.Dimension.notification_right_side_padding_top; + global::Xamarin.Essentials.Resource.Dimension.notification_small_icon_background_padding = global::HelloworldXamarin.Droid.Resource.Dimension.notification_small_icon_background_padding; + global::Xamarin.Essentials.Resource.Dimension.notification_small_icon_size_as_large = global::HelloworldXamarin.Droid.Resource.Dimension.notification_small_icon_size_as_large; + global::Xamarin.Essentials.Resource.Dimension.notification_subtext_size = global::HelloworldXamarin.Droid.Resource.Dimension.notification_subtext_size; + global::Xamarin.Essentials.Resource.Dimension.notification_top_pad = global::HelloworldXamarin.Droid.Resource.Dimension.notification_top_pad; + global::Xamarin.Essentials.Resource.Dimension.notification_top_pad_large_text = global::HelloworldXamarin.Droid.Resource.Dimension.notification_top_pad_large_text; + global::Xamarin.Essentials.Resource.Drawable.notification_action_background = global::HelloworldXamarin.Droid.Resource.Drawable.notification_action_background; + global::Xamarin.Essentials.Resource.Drawable.notification_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg; + global::Xamarin.Essentials.Resource.Drawable.notification_bg_low = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_low; + global::Xamarin.Essentials.Resource.Drawable.notification_bg_low_normal = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_low_normal; + global::Xamarin.Essentials.Resource.Drawable.notification_bg_low_pressed = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_low_pressed; + global::Xamarin.Essentials.Resource.Drawable.notification_bg_normal = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_normal; + global::Xamarin.Essentials.Resource.Drawable.notification_bg_normal_pressed = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_normal_pressed; + global::Xamarin.Essentials.Resource.Drawable.notification_icon_background = global::HelloworldXamarin.Droid.Resource.Drawable.notification_icon_background; + global::Xamarin.Essentials.Resource.Drawable.notification_template_icon_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notification_template_icon_bg; + global::Xamarin.Essentials.Resource.Drawable.notification_template_icon_low_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notification_template_icon_low_bg; + global::Xamarin.Essentials.Resource.Drawable.notification_tile_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notification_tile_bg; + global::Xamarin.Essentials.Resource.Drawable.notify_panel_notification_icon_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notify_panel_notification_icon_bg; + global::Xamarin.Essentials.Resource.Id.actions = global::HelloworldXamarin.Droid.Resource.Id.actions; + global::Xamarin.Essentials.Resource.Id.action_container = global::HelloworldXamarin.Droid.Resource.Id.action_container; + global::Xamarin.Essentials.Resource.Id.action_divider = global::HelloworldXamarin.Droid.Resource.Id.action_divider; + global::Xamarin.Essentials.Resource.Id.action_image = global::HelloworldXamarin.Droid.Resource.Id.action_image; + global::Xamarin.Essentials.Resource.Id.action_text = global::HelloworldXamarin.Droid.Resource.Id.action_text; + global::Xamarin.Essentials.Resource.Id.all = global::HelloworldXamarin.Droid.Resource.Id.all; + global::Xamarin.Essentials.Resource.Id.async = global::HelloworldXamarin.Droid.Resource.Id.async; + global::Xamarin.Essentials.Resource.Id.blocking = global::HelloworldXamarin.Droid.Resource.Id.blocking; + global::Xamarin.Essentials.Resource.Id.bottom = global::HelloworldXamarin.Droid.Resource.Id.bottom; + global::Xamarin.Essentials.Resource.Id.browser_actions_header_text = global::HelloworldXamarin.Droid.Resource.Id.browser_actions_header_text; + global::Xamarin.Essentials.Resource.Id.browser_actions_menu_items = global::HelloworldXamarin.Droid.Resource.Id.browser_actions_menu_items; + global::Xamarin.Essentials.Resource.Id.browser_actions_menu_item_icon = global::HelloworldXamarin.Droid.Resource.Id.browser_actions_menu_item_icon; + global::Xamarin.Essentials.Resource.Id.browser_actions_menu_item_text = global::HelloworldXamarin.Droid.Resource.Id.browser_actions_menu_item_text; + global::Xamarin.Essentials.Resource.Id.browser_actions_menu_view = global::HelloworldXamarin.Droid.Resource.Id.browser_actions_menu_view; + global::Xamarin.Essentials.Resource.Id.center = global::HelloworldXamarin.Droid.Resource.Id.center; + global::Xamarin.Essentials.Resource.Id.center_horizontal = global::HelloworldXamarin.Droid.Resource.Id.center_horizontal; + global::Xamarin.Essentials.Resource.Id.center_vertical = global::HelloworldXamarin.Droid.Resource.Id.center_vertical; + global::Xamarin.Essentials.Resource.Id.chronometer = global::HelloworldXamarin.Droid.Resource.Id.chronometer; + global::Xamarin.Essentials.Resource.Id.clip_horizontal = global::HelloworldXamarin.Droid.Resource.Id.clip_horizontal; + global::Xamarin.Essentials.Resource.Id.clip_vertical = global::HelloworldXamarin.Droid.Resource.Id.clip_vertical; + global::Xamarin.Essentials.Resource.Id.end = global::HelloworldXamarin.Droid.Resource.Id.end; + global::Xamarin.Essentials.Resource.Id.fill = global::HelloworldXamarin.Droid.Resource.Id.fill; + global::Xamarin.Essentials.Resource.Id.fill_horizontal = global::HelloworldXamarin.Droid.Resource.Id.fill_horizontal; + global::Xamarin.Essentials.Resource.Id.fill_vertical = global::HelloworldXamarin.Droid.Resource.Id.fill_vertical; + global::Xamarin.Essentials.Resource.Id.forever = global::HelloworldXamarin.Droid.Resource.Id.forever; + global::Xamarin.Essentials.Resource.Id.icon = global::HelloworldXamarin.Droid.Resource.Id.icon; + global::Xamarin.Essentials.Resource.Id.icon_group = global::HelloworldXamarin.Droid.Resource.Id.icon_group; + global::Xamarin.Essentials.Resource.Id.info = global::HelloworldXamarin.Droid.Resource.Id.info; + global::Xamarin.Essentials.Resource.Id.italic = global::HelloworldXamarin.Droid.Resource.Id.italic; + global::Xamarin.Essentials.Resource.Id.left = global::HelloworldXamarin.Droid.Resource.Id.left; + global::Xamarin.Essentials.Resource.Id.line1 = global::HelloworldXamarin.Droid.Resource.Id.line1; + global::Xamarin.Essentials.Resource.Id.line3 = global::HelloworldXamarin.Droid.Resource.Id.line3; + global::Xamarin.Essentials.Resource.Id.none = global::HelloworldXamarin.Droid.Resource.Id.none; + global::Xamarin.Essentials.Resource.Id.normal = global::HelloworldXamarin.Droid.Resource.Id.normal; + global::Xamarin.Essentials.Resource.Id.notification_background = global::HelloworldXamarin.Droid.Resource.Id.notification_background; + global::Xamarin.Essentials.Resource.Id.notification_main_column = global::HelloworldXamarin.Droid.Resource.Id.notification_main_column; + global::Xamarin.Essentials.Resource.Id.notification_main_column_container = global::HelloworldXamarin.Droid.Resource.Id.notification_main_column_container; + global::Xamarin.Essentials.Resource.Id.right = global::HelloworldXamarin.Droid.Resource.Id.right; + global::Xamarin.Essentials.Resource.Id.right_icon = global::HelloworldXamarin.Droid.Resource.Id.right_icon; + global::Xamarin.Essentials.Resource.Id.right_side = global::HelloworldXamarin.Droid.Resource.Id.right_side; + global::Xamarin.Essentials.Resource.Id.start = global::HelloworldXamarin.Droid.Resource.Id.start; + global::Xamarin.Essentials.Resource.Id.tag_transition_group = global::HelloworldXamarin.Droid.Resource.Id.tag_transition_group; + global::Xamarin.Essentials.Resource.Id.tag_unhandled_key_event_manager = global::HelloworldXamarin.Droid.Resource.Id.tag_unhandled_key_event_manager; + global::Xamarin.Essentials.Resource.Id.tag_unhandled_key_listeners = global::HelloworldXamarin.Droid.Resource.Id.tag_unhandled_key_listeners; + global::Xamarin.Essentials.Resource.Id.text = global::HelloworldXamarin.Droid.Resource.Id.text; + global::Xamarin.Essentials.Resource.Id.text2 = global::HelloworldXamarin.Droid.Resource.Id.text2; + global::Xamarin.Essentials.Resource.Id.time = global::HelloworldXamarin.Droid.Resource.Id.time; + global::Xamarin.Essentials.Resource.Id.title = global::HelloworldXamarin.Droid.Resource.Id.title; + global::Xamarin.Essentials.Resource.Id.top = global::HelloworldXamarin.Droid.Resource.Id.top; + global::Xamarin.Essentials.Resource.Integer.status_bar_notification_info_maxnum = global::HelloworldXamarin.Droid.Resource.Integer.status_bar_notification_info_maxnum; + global::Xamarin.Essentials.Resource.Layout.browser_actions_context_menu_page = global::HelloworldXamarin.Droid.Resource.Layout.browser_actions_context_menu_page; + global::Xamarin.Essentials.Resource.Layout.browser_actions_context_menu_row = global::HelloworldXamarin.Droid.Resource.Layout.browser_actions_context_menu_row; + global::Xamarin.Essentials.Resource.Layout.notification_action = global::HelloworldXamarin.Droid.Resource.Layout.notification_action; + global::Xamarin.Essentials.Resource.Layout.notification_action_tombstone = global::HelloworldXamarin.Droid.Resource.Layout.notification_action_tombstone; + global::Xamarin.Essentials.Resource.Layout.notification_template_custom_big = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_custom_big; + global::Xamarin.Essentials.Resource.Layout.notification_template_icon_group = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_icon_group; + global::Xamarin.Essentials.Resource.Layout.notification_template_part_chronometer = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_part_chronometer; + global::Xamarin.Essentials.Resource.Layout.notification_template_part_time = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_part_time; + global::Xamarin.Essentials.Resource.String.status_bar_notification_info_overflow = global::HelloworldXamarin.Droid.Resource.String.status_bar_notification_info_overflow; + global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification; + global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification_Info = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Info; + global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification_Line2 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Line2; + global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification_Time = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Time; + global::Xamarin.Essentials.Resource.Style.TextAppearance_Compat_Notification_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Title; + global::Xamarin.Essentials.Resource.Style.Widget_Compat_NotificationActionContainer = global::HelloworldXamarin.Droid.Resource.Style.Widget_Compat_NotificationActionContainer; + global::Xamarin.Essentials.Resource.Style.Widget_Compat_NotificationActionText = global::HelloworldXamarin.Droid.Resource.Style.Widget_Compat_NotificationActionText; + global::Xamarin.Essentials.Resource.Style.Widget_Support_CoordinatorLayout = global::HelloworldXamarin.Droid.Resource.Style.Widget_Support_CoordinatorLayout; + global::Xamarin.Essentials.Resource.Styleable.ColorStateListItem = global::HelloworldXamarin.Droid.Resource.Styleable.ColorStateListItem; + global::Xamarin.Essentials.Resource.Styleable.ColorStateListItem_alpha = global::HelloworldXamarin.Droid.Resource.Styleable.ColorStateListItem_alpha; + global::Xamarin.Essentials.Resource.Styleable.ColorStateListItem_android_alpha = global::HelloworldXamarin.Droid.Resource.Styleable.ColorStateListItem_android_alpha; + global::Xamarin.Essentials.Resource.Styleable.ColorStateListItem_android_color = global::HelloworldXamarin.Droid.Resource.Styleable.ColorStateListItem_android_color; + global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout; + global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_keylines = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_keylines; + global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout; + global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity; + global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor; + global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity; + global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior; + global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges; + global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge; + global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline; + global::Xamarin.Essentials.Resource.Styleable.CoordinatorLayout_statusBarBackground = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_statusBarBackground; + global::Xamarin.Essentials.Resource.Styleable.FontFamily = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily; + global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont; + global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_font = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_font; + global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_fontStyle = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_fontStyle; + global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_fontVariationSettings = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_fontVariationSettings; + global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_fontWeight = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_fontWeight; + global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_android_ttcIndex = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_ttcIndex; + global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_font = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_font; + global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontStyle = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_fontStyle; + global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontVariationSettings = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_fontVariationSettings; + global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_fontWeight = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_fontWeight; + global::Xamarin.Essentials.Resource.Styleable.FontFamilyFont_ttcIndex = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_ttcIndex; + global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderAuthority = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderAuthority; + global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderCerts = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderCerts; + global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderFetchStrategy = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderFetchStrategy; + global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderFetchTimeout = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderFetchTimeout; + global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderPackage = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderPackage; + global::Xamarin.Essentials.Resource.Styleable.FontFamily_fontProviderQuery = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderQuery; + global::Xamarin.Essentials.Resource.Styleable.GradientColor = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor; + global::Xamarin.Essentials.Resource.Styleable.GradientColorItem = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColorItem; + global::Xamarin.Essentials.Resource.Styleable.GradientColorItem_android_color = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColorItem_android_color; + global::Xamarin.Essentials.Resource.Styleable.GradientColorItem_android_offset = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColorItem_android_offset; + global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_centerColor = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_centerColor; + global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_centerX = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_centerX; + global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_centerY = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_centerY; + global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_endColor = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_endColor; + global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_endX = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_endX; + global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_endY = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_endY; + global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_gradientRadius = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_gradientRadius; + global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_startColor = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_startColor; + global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_startX = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_startX; + global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_startY = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_startY; + global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_tileMode = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_tileMode; + global::Xamarin.Essentials.Resource.Styleable.GradientColor_android_type = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_type; + global::Xamarin.Essentials.Resource.Xml.xamarin_essentials_fileprovider_file_paths = global::HelloworldXamarin.Droid.Resource.Xml.xamarin_essentials_fileprovider_file_paths; + global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_fade_in = global::HelloworldXamarin.Droid.Resource.Animation.abc_fade_in; + global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_fade_out = global::HelloworldXamarin.Droid.Resource.Animation.abc_fade_out; + global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_grow_fade_in_from_bottom = global::HelloworldXamarin.Droid.Resource.Animation.abc_grow_fade_in_from_bottom; + global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_popup_enter = global::HelloworldXamarin.Droid.Resource.Animation.abc_popup_enter; + global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_popup_exit = global::HelloworldXamarin.Droid.Resource.Animation.abc_popup_exit; + global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_shrink_fade_out_from_bottom = global::HelloworldXamarin.Droid.Resource.Animation.abc_shrink_fade_out_from_bottom; + global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_slide_in_bottom = global::HelloworldXamarin.Droid.Resource.Animation.abc_slide_in_bottom; + global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_slide_in_top = global::HelloworldXamarin.Droid.Resource.Animation.abc_slide_in_top; + global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_slide_out_bottom = global::HelloworldXamarin.Droid.Resource.Animation.abc_slide_out_bottom; + global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_slide_out_top = global::HelloworldXamarin.Droid.Resource.Animation.abc_slide_out_top; + global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_tooltip_enter = global::HelloworldXamarin.Droid.Resource.Animation.abc_tooltip_enter; + global::Xamarin.Forms.Platform.Android.Resource.Animation.abc_tooltip_exit = global::HelloworldXamarin.Droid.Resource.Animation.abc_tooltip_exit; + global::Xamarin.Forms.Platform.Android.Resource.Animation.design_bottom_sheet_slide_in = global::HelloworldXamarin.Droid.Resource.Animation.design_bottom_sheet_slide_in; + global::Xamarin.Forms.Platform.Android.Resource.Animation.design_bottom_sheet_slide_out = global::HelloworldXamarin.Droid.Resource.Animation.design_bottom_sheet_slide_out; + global::Xamarin.Forms.Platform.Android.Resource.Animation.design_snackbar_in = global::HelloworldXamarin.Droid.Resource.Animation.design_snackbar_in; + global::Xamarin.Forms.Platform.Android.Resource.Animation.design_snackbar_out = global::HelloworldXamarin.Droid.Resource.Animation.design_snackbar_out; + global::Xamarin.Forms.Platform.Android.Resource.Animation.EnterFromLeft = global::HelloworldXamarin.Droid.Resource.Animation.EnterFromLeft; + global::Xamarin.Forms.Platform.Android.Resource.Animation.EnterFromRight = global::HelloworldXamarin.Droid.Resource.Animation.EnterFromRight; + global::Xamarin.Forms.Platform.Android.Resource.Animation.ExitToLeft = global::HelloworldXamarin.Droid.Resource.Animation.ExitToLeft; + global::Xamarin.Forms.Platform.Android.Resource.Animation.ExitToRight = global::HelloworldXamarin.Droid.Resource.Animation.ExitToRight; + global::Xamarin.Forms.Platform.Android.Resource.Animator.design_appbar_state_list_animator = global::HelloworldXamarin.Droid.Resource.Animator.design_appbar_state_list_animator; + global::Xamarin.Forms.Platform.Android.Resource.Animator.design_fab_hide_motion_spec = global::HelloworldXamarin.Droid.Resource.Animator.design_fab_hide_motion_spec; + global::Xamarin.Forms.Platform.Android.Resource.Animator.design_fab_show_motion_spec = global::HelloworldXamarin.Droid.Resource.Animator.design_fab_show_motion_spec; + global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_btn_state_list_anim = global::HelloworldXamarin.Droid.Resource.Animator.mtrl_btn_state_list_anim; + global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_btn_unelevated_state_list_anim = global::HelloworldXamarin.Droid.Resource.Animator.mtrl_btn_unelevated_state_list_anim; + global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_chip_state_list_anim = global::HelloworldXamarin.Droid.Resource.Animator.mtrl_chip_state_list_anim; + global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_fab_hide_motion_spec = global::HelloworldXamarin.Droid.Resource.Animator.mtrl_fab_hide_motion_spec; + global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_fab_show_motion_spec = global::HelloworldXamarin.Droid.Resource.Animator.mtrl_fab_show_motion_spec; + global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_fab_transformation_sheet_collapse_spec = global::HelloworldXamarin.Droid.Resource.Animator.mtrl_fab_transformation_sheet_collapse_spec; + global::Xamarin.Forms.Platform.Android.Resource.Animator.mtrl_fab_transformation_sheet_expand_spec = global::HelloworldXamarin.Droid.Resource.Animator.mtrl_fab_transformation_sheet_expand_spec; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarDivider = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarDivider; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarItemBackground = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarItemBackground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarPopupTheme = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarPopupTheme; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarSize = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarSize; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarSplitStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarSplitStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarTabBarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarTabBarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarTabStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarTabStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarTabTextStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarTabTextStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarTheme = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarTheme; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionBarWidgetTheme = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarWidgetTheme; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionDropDownStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionDropDownStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionLayout = global::HelloworldXamarin.Droid.Resource.Attribute.actionLayout; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionMenuTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.actionMenuTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionMenuTextColor = global::HelloworldXamarin.Droid.Resource.Attribute.actionMenuTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeBackground = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeBackground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeCloseButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeCloseButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeCloseDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeCloseDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeCopyDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeCopyDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeCutDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeCutDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeFindDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeFindDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModePasteDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModePasteDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModePopupWindowStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionModePopupWindowStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeSelectAllDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeSelectAllDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeShareDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeShareDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeSplitBackground = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeSplitBackground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionModeWebSearchDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeWebSearchDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionOverflowButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionOverflowButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionOverflowMenuStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionOverflowMenuStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionProviderClass = global::HelloworldXamarin.Droid.Resource.Attribute.actionProviderClass; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.actionViewClass = global::HelloworldXamarin.Droid.Resource.Attribute.actionViewClass; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.activityChooserViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.activityChooserViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.alertDialogButtonGroupStyle = global::HelloworldXamarin.Droid.Resource.Attribute.alertDialogButtonGroupStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.alertDialogCenterButtons = global::HelloworldXamarin.Droid.Resource.Attribute.alertDialogCenterButtons; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.alertDialogStyle = global::HelloworldXamarin.Droid.Resource.Attribute.alertDialogStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.alertDialogTheme = global::HelloworldXamarin.Droid.Resource.Attribute.alertDialogTheme; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.allowStacking = global::HelloworldXamarin.Droid.Resource.Attribute.allowStacking; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.alpha = global::HelloworldXamarin.Droid.Resource.Attribute.alpha; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.alphabeticModifiers = global::HelloworldXamarin.Droid.Resource.Attribute.alphabeticModifiers; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.arrowHeadLength = global::HelloworldXamarin.Droid.Resource.Attribute.arrowHeadLength; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.arrowShaftLength = global::HelloworldXamarin.Droid.Resource.Attribute.arrowShaftLength; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.autoCompleteTextViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.autoCompleteTextViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.autoSizeMaxTextSize = global::HelloworldXamarin.Droid.Resource.Attribute.autoSizeMaxTextSize; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.autoSizeMinTextSize = global::HelloworldXamarin.Droid.Resource.Attribute.autoSizeMinTextSize; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.autoSizePresetSizes = global::HelloworldXamarin.Droid.Resource.Attribute.autoSizePresetSizes; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.autoSizeStepGranularity = global::HelloworldXamarin.Droid.Resource.Attribute.autoSizeStepGranularity; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.autoSizeTextType = global::HelloworldXamarin.Droid.Resource.Attribute.autoSizeTextType; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.background = global::HelloworldXamarin.Droid.Resource.Attribute.background; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.backgroundSplit = global::HelloworldXamarin.Droid.Resource.Attribute.backgroundSplit; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.backgroundStacked = global::HelloworldXamarin.Droid.Resource.Attribute.backgroundStacked; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.backgroundTint = global::HelloworldXamarin.Droid.Resource.Attribute.backgroundTint; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.backgroundTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.backgroundTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.barLength = global::HelloworldXamarin.Droid.Resource.Attribute.barLength; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_autoHide = global::HelloworldXamarin.Droid.Resource.Attribute.behavior_autoHide; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_fitToContents = global::HelloworldXamarin.Droid.Resource.Attribute.behavior_fitToContents; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_hideable = global::HelloworldXamarin.Droid.Resource.Attribute.behavior_hideable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_overlapTop = global::HelloworldXamarin.Droid.Resource.Attribute.behavior_overlapTop; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_peekHeight = global::HelloworldXamarin.Droid.Resource.Attribute.behavior_peekHeight; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.behavior_skipCollapsed = global::HelloworldXamarin.Droid.Resource.Attribute.behavior_skipCollapsed; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.borderlessButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.borderlessButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.borderWidth = global::HelloworldXamarin.Droid.Resource.Attribute.borderWidth; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.bottomAppBarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.bottomAppBarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.bottomNavigationStyle = global::HelloworldXamarin.Droid.Resource.Attribute.bottomNavigationStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.bottomSheetDialogTheme = global::HelloworldXamarin.Droid.Resource.Attribute.bottomSheetDialogTheme; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.bottomSheetStyle = global::HelloworldXamarin.Droid.Resource.Attribute.bottomSheetStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxBackgroundColor = global::HelloworldXamarin.Droid.Resource.Attribute.boxBackgroundColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxBackgroundMode = global::HelloworldXamarin.Droid.Resource.Attribute.boxBackgroundMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxCollapsedPaddingTop = global::HelloworldXamarin.Droid.Resource.Attribute.boxCollapsedPaddingTop; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxCornerRadiusBottomEnd = global::HelloworldXamarin.Droid.Resource.Attribute.boxCornerRadiusBottomEnd; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxCornerRadiusBottomStart = global::HelloworldXamarin.Droid.Resource.Attribute.boxCornerRadiusBottomStart; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxCornerRadiusTopEnd = global::HelloworldXamarin.Droid.Resource.Attribute.boxCornerRadiusTopEnd; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxCornerRadiusTopStart = global::HelloworldXamarin.Droid.Resource.Attribute.boxCornerRadiusTopStart; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxStrokeColor = global::HelloworldXamarin.Droid.Resource.Attribute.boxStrokeColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.boxStrokeWidth = global::HelloworldXamarin.Droid.Resource.Attribute.boxStrokeWidth; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonBarButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.buttonBarButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonBarNegativeButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.buttonBarNegativeButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonBarNeutralButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.buttonBarNeutralButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonBarPositiveButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.buttonBarPositiveButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonBarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.buttonBarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonGravity = global::HelloworldXamarin.Droid.Resource.Attribute.buttonGravity; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonIconDimen = global::HelloworldXamarin.Droid.Resource.Attribute.buttonIconDimen; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonPanelSideLayout = global::HelloworldXamarin.Droid.Resource.Attribute.buttonPanelSideLayout; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.buttonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonStyleSmall = global::HelloworldXamarin.Droid.Resource.Attribute.buttonStyleSmall; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonTint = global::HelloworldXamarin.Droid.Resource.Attribute.buttonTint; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.buttonTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.buttonTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardBackgroundColor = global::HelloworldXamarin.Droid.Resource.Attribute.cardBackgroundColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardCornerRadius = global::HelloworldXamarin.Droid.Resource.Attribute.cardCornerRadius; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardElevation = global::HelloworldXamarin.Droid.Resource.Attribute.cardElevation; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardMaxElevation = global::HelloworldXamarin.Droid.Resource.Attribute.cardMaxElevation; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardPreventCornerOverlap = global::HelloworldXamarin.Droid.Resource.Attribute.cardPreventCornerOverlap; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardUseCompatPadding = global::HelloworldXamarin.Droid.Resource.Attribute.cardUseCompatPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.cardViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.cardViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.checkboxStyle = global::HelloworldXamarin.Droid.Resource.Attribute.checkboxStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.checkedChip = global::HelloworldXamarin.Droid.Resource.Attribute.checkedChip; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.checkedIcon = global::HelloworldXamarin.Droid.Resource.Attribute.checkedIcon; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.checkedIconEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.checkedIconEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.checkedIconVisible = global::HelloworldXamarin.Droid.Resource.Attribute.checkedIconVisible; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.checkedTextViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.checkedTextViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipBackgroundColor = global::HelloworldXamarin.Droid.Resource.Attribute.chipBackgroundColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipCornerRadius = global::HelloworldXamarin.Droid.Resource.Attribute.chipCornerRadius; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipEndPadding = global::HelloworldXamarin.Droid.Resource.Attribute.chipEndPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipGroupStyle = global::HelloworldXamarin.Droid.Resource.Attribute.chipGroupStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipIcon = global::HelloworldXamarin.Droid.Resource.Attribute.chipIcon; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipIconEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.chipIconEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipIconSize = global::HelloworldXamarin.Droid.Resource.Attribute.chipIconSize; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipIconTint = global::HelloworldXamarin.Droid.Resource.Attribute.chipIconTint; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipIconVisible = global::HelloworldXamarin.Droid.Resource.Attribute.chipIconVisible; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipMinHeight = global::HelloworldXamarin.Droid.Resource.Attribute.chipMinHeight; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipSpacing = global::HelloworldXamarin.Droid.Resource.Attribute.chipSpacing; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipSpacingHorizontal = global::HelloworldXamarin.Droid.Resource.Attribute.chipSpacingHorizontal; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipSpacingVertical = global::HelloworldXamarin.Droid.Resource.Attribute.chipSpacingVertical; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipStandaloneStyle = global::HelloworldXamarin.Droid.Resource.Attribute.chipStandaloneStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipStartPadding = global::HelloworldXamarin.Droid.Resource.Attribute.chipStartPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipStrokeColor = global::HelloworldXamarin.Droid.Resource.Attribute.chipStrokeColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipStrokeWidth = global::HelloworldXamarin.Droid.Resource.Attribute.chipStrokeWidth; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.chipStyle = global::HelloworldXamarin.Droid.Resource.Attribute.chipStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeIcon = global::HelloworldXamarin.Droid.Resource.Attribute.closeIcon; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeIconEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.closeIconEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeIconEndPadding = global::HelloworldXamarin.Droid.Resource.Attribute.closeIconEndPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeIconSize = global::HelloworldXamarin.Droid.Resource.Attribute.closeIconSize; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeIconStartPadding = global::HelloworldXamarin.Droid.Resource.Attribute.closeIconStartPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeIconTint = global::HelloworldXamarin.Droid.Resource.Attribute.closeIconTint; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeIconVisible = global::HelloworldXamarin.Droid.Resource.Attribute.closeIconVisible; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.closeItemLayout = global::HelloworldXamarin.Droid.Resource.Attribute.closeItemLayout; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.collapseContentDescription = global::HelloworldXamarin.Droid.Resource.Attribute.collapseContentDescription; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.collapsedTitleGravity = global::HelloworldXamarin.Droid.Resource.Attribute.collapsedTitleGravity; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.collapsedTitleTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.collapsedTitleTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.collapseIcon = global::HelloworldXamarin.Droid.Resource.Attribute.collapseIcon; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.color = global::HelloworldXamarin.Droid.Resource.Attribute.color; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorAccent = global::HelloworldXamarin.Droid.Resource.Attribute.colorAccent; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorBackgroundFloating = global::HelloworldXamarin.Droid.Resource.Attribute.colorBackgroundFloating; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorButtonNormal = global::HelloworldXamarin.Droid.Resource.Attribute.colorButtonNormal; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorControlActivated = global::HelloworldXamarin.Droid.Resource.Attribute.colorControlActivated; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorControlHighlight = global::HelloworldXamarin.Droid.Resource.Attribute.colorControlHighlight; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorControlNormal = global::HelloworldXamarin.Droid.Resource.Attribute.colorControlNormal; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorError = global::HelloworldXamarin.Droid.Resource.Attribute.colorError; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorPrimary = global::HelloworldXamarin.Droid.Resource.Attribute.colorPrimary; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorPrimaryDark = global::HelloworldXamarin.Droid.Resource.Attribute.colorPrimaryDark; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorSecondary = global::HelloworldXamarin.Droid.Resource.Attribute.colorSecondary; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.colorSwitchThumbNormal = global::HelloworldXamarin.Droid.Resource.Attribute.colorSwitchThumbNormal; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.commitIcon = global::HelloworldXamarin.Droid.Resource.Attribute.commitIcon; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentDescription = global::HelloworldXamarin.Droid.Resource.Attribute.contentDescription; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentInsetEnd = global::HelloworldXamarin.Droid.Resource.Attribute.contentInsetEnd; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentInsetEndWithActions = global::HelloworldXamarin.Droid.Resource.Attribute.contentInsetEndWithActions; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentInsetLeft = global::HelloworldXamarin.Droid.Resource.Attribute.contentInsetLeft; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentInsetRight = global::HelloworldXamarin.Droid.Resource.Attribute.contentInsetRight; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentInsetStart = global::HelloworldXamarin.Droid.Resource.Attribute.contentInsetStart; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentInsetStartWithNavigation = global::HelloworldXamarin.Droid.Resource.Attribute.contentInsetStartWithNavigation; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentPadding = global::HelloworldXamarin.Droid.Resource.Attribute.contentPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentPaddingBottom = global::HelloworldXamarin.Droid.Resource.Attribute.contentPaddingBottom; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentPaddingLeft = global::HelloworldXamarin.Droid.Resource.Attribute.contentPaddingLeft; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentPaddingRight = global::HelloworldXamarin.Droid.Resource.Attribute.contentPaddingRight; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentPaddingTop = global::HelloworldXamarin.Droid.Resource.Attribute.contentPaddingTop; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.contentScrim = global::HelloworldXamarin.Droid.Resource.Attribute.contentScrim; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.controlBackground = global::HelloworldXamarin.Droid.Resource.Attribute.controlBackground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.coordinatorLayoutStyle = global::HelloworldXamarin.Droid.Resource.Attribute.coordinatorLayoutStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.cornerRadius = global::HelloworldXamarin.Droid.Resource.Attribute.cornerRadius; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.counterEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.counterEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.counterMaxLength = global::HelloworldXamarin.Droid.Resource.Attribute.counterMaxLength; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.counterOverflowTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.counterOverflowTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.counterTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.counterTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.customNavigationLayout = global::HelloworldXamarin.Droid.Resource.Attribute.customNavigationLayout; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.defaultQueryHint = global::HelloworldXamarin.Droid.Resource.Attribute.defaultQueryHint; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.dialogCornerRadius = global::HelloworldXamarin.Droid.Resource.Attribute.dialogCornerRadius; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.dialogPreferredPadding = global::HelloworldXamarin.Droid.Resource.Attribute.dialogPreferredPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.dialogTheme = global::HelloworldXamarin.Droid.Resource.Attribute.dialogTheme; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.displayOptions = global::HelloworldXamarin.Droid.Resource.Attribute.displayOptions; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.divider = global::HelloworldXamarin.Droid.Resource.Attribute.divider; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.dividerHorizontal = global::HelloworldXamarin.Droid.Resource.Attribute.dividerHorizontal; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.dividerPadding = global::HelloworldXamarin.Droid.Resource.Attribute.dividerPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.dividerVertical = global::HelloworldXamarin.Droid.Resource.Attribute.dividerVertical; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.drawableSize = global::HelloworldXamarin.Droid.Resource.Attribute.drawableSize; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.drawerArrowStyle = global::HelloworldXamarin.Droid.Resource.Attribute.drawerArrowStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.dropdownListPreferredItemHeight = global::HelloworldXamarin.Droid.Resource.Attribute.dropdownListPreferredItemHeight; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.dropDownListViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.dropDownListViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.editTextBackground = global::HelloworldXamarin.Droid.Resource.Attribute.editTextBackground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.editTextColor = global::HelloworldXamarin.Droid.Resource.Attribute.editTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.editTextStyle = global::HelloworldXamarin.Droid.Resource.Attribute.editTextStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.elevation = global::HelloworldXamarin.Droid.Resource.Attribute.elevation; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.enforceMaterialTheme = global::HelloworldXamarin.Droid.Resource.Attribute.enforceMaterialTheme; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.enforceTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.enforceTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.errorEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.errorEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.errorTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.errorTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandActivityOverflowButtonDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.expandActivityOverflowButtonDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.expanded = global::HelloworldXamarin.Droid.Resource.Attribute.expanded; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandedTitleGravity = global::HelloworldXamarin.Droid.Resource.Attribute.expandedTitleGravity; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandedTitleMargin = global::HelloworldXamarin.Droid.Resource.Attribute.expandedTitleMargin; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandedTitleMarginBottom = global::HelloworldXamarin.Droid.Resource.Attribute.expandedTitleMarginBottom; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandedTitleMarginEnd = global::HelloworldXamarin.Droid.Resource.Attribute.expandedTitleMarginEnd; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandedTitleMarginStart = global::HelloworldXamarin.Droid.Resource.Attribute.expandedTitleMarginStart; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandedTitleMarginTop = global::HelloworldXamarin.Droid.Resource.Attribute.expandedTitleMarginTop; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.expandedTitleTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.expandedTitleTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fabAlignmentMode = global::HelloworldXamarin.Droid.Resource.Attribute.fabAlignmentMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fabCradleMargin = global::HelloworldXamarin.Droid.Resource.Attribute.fabCradleMargin; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fabCradleRoundedCornerRadius = global::HelloworldXamarin.Droid.Resource.Attribute.fabCradleRoundedCornerRadius; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fabCradleVerticalOffset = global::HelloworldXamarin.Droid.Resource.Attribute.fabCradleVerticalOffset; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fabCustomSize = global::HelloworldXamarin.Droid.Resource.Attribute.fabCustomSize; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fabSize = global::HelloworldXamarin.Droid.Resource.Attribute.fabSize; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fastScrollEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.fastScrollEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fastScrollHorizontalThumbDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.fastScrollHorizontalThumbDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fastScrollHorizontalTrackDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.fastScrollHorizontalTrackDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fastScrollVerticalThumbDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.fastScrollVerticalThumbDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fastScrollVerticalTrackDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.fastScrollVerticalTrackDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.firstBaselineToTopHeight = global::HelloworldXamarin.Droid.Resource.Attribute.firstBaselineToTopHeight; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.floatingActionButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.floatingActionButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.font = global::HelloworldXamarin.Droid.Resource.Attribute.font; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontFamily = global::HelloworldXamarin.Droid.Resource.Attribute.fontFamily; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontProviderAuthority = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderAuthority; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontProviderCerts = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderCerts; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontProviderFetchStrategy = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderFetchStrategy; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontProviderFetchTimeout = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderFetchTimeout; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontProviderPackage = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderPackage; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontProviderQuery = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderQuery; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontStyle = global::HelloworldXamarin.Droid.Resource.Attribute.fontStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontVariationSettings = global::HelloworldXamarin.Droid.Resource.Attribute.fontVariationSettings; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.fontWeight = global::HelloworldXamarin.Droid.Resource.Attribute.fontWeight; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.foregroundInsidePadding = global::HelloworldXamarin.Droid.Resource.Attribute.foregroundInsidePadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.gapBetweenBars = global::HelloworldXamarin.Droid.Resource.Attribute.gapBetweenBars; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.goIcon = global::HelloworldXamarin.Droid.Resource.Attribute.goIcon; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.headerLayout = global::HelloworldXamarin.Droid.Resource.Attribute.headerLayout; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.height = global::HelloworldXamarin.Droid.Resource.Attribute.height; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.helperText = global::HelloworldXamarin.Droid.Resource.Attribute.helperText; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.helperTextEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.helperTextEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.helperTextTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.helperTextTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.hideMotionSpec = global::HelloworldXamarin.Droid.Resource.Attribute.hideMotionSpec; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.hideOnContentScroll = global::HelloworldXamarin.Droid.Resource.Attribute.hideOnContentScroll; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.hideOnScroll = global::HelloworldXamarin.Droid.Resource.Attribute.hideOnScroll; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.hintAnimationEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.hintAnimationEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.hintEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.hintEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.hintTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.hintTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.homeAsUpIndicator = global::HelloworldXamarin.Droid.Resource.Attribute.homeAsUpIndicator; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.homeLayout = global::HelloworldXamarin.Droid.Resource.Attribute.homeLayout; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.hoveredFocusedTranslationZ = global::HelloworldXamarin.Droid.Resource.Attribute.hoveredFocusedTranslationZ; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.icon = global::HelloworldXamarin.Droid.Resource.Attribute.icon; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconEndPadding = global::HelloworldXamarin.Droid.Resource.Attribute.iconEndPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconGravity = global::HelloworldXamarin.Droid.Resource.Attribute.iconGravity; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconifiedByDefault = global::HelloworldXamarin.Droid.Resource.Attribute.iconifiedByDefault; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconPadding = global::HelloworldXamarin.Droid.Resource.Attribute.iconPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconSize = global::HelloworldXamarin.Droid.Resource.Attribute.iconSize; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconStartPadding = global::HelloworldXamarin.Droid.Resource.Attribute.iconStartPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconTint = global::HelloworldXamarin.Droid.Resource.Attribute.iconTint; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.iconTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.iconTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.imageButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.imageButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.indeterminateProgressStyle = global::HelloworldXamarin.Droid.Resource.Attribute.indeterminateProgressStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.initialActivityCount = global::HelloworldXamarin.Droid.Resource.Attribute.initialActivityCount; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.insetForeground = global::HelloworldXamarin.Droid.Resource.Attribute.insetForeground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.isLightTheme = global::HelloworldXamarin.Droid.Resource.Attribute.isLightTheme; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemBackground = global::HelloworldXamarin.Droid.Resource.Attribute.itemBackground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemHorizontalPadding = global::HelloworldXamarin.Droid.Resource.Attribute.itemHorizontalPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemHorizontalTranslationEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.itemHorizontalTranslationEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemIconPadding = global::HelloworldXamarin.Droid.Resource.Attribute.itemIconPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemIconSize = global::HelloworldXamarin.Droid.Resource.Attribute.itemIconSize; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemIconTint = global::HelloworldXamarin.Droid.Resource.Attribute.itemIconTint; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemPadding = global::HelloworldXamarin.Droid.Resource.Attribute.itemPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemSpacing = global::HelloworldXamarin.Droid.Resource.Attribute.itemSpacing; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.itemTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemTextAppearanceActive = global::HelloworldXamarin.Droid.Resource.Attribute.itemTextAppearanceActive; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemTextAppearanceInactive = global::HelloworldXamarin.Droid.Resource.Attribute.itemTextAppearanceInactive; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.itemTextColor = global::HelloworldXamarin.Droid.Resource.Attribute.itemTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.keylines = global::HelloworldXamarin.Droid.Resource.Attribute.keylines; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.labelVisibilityMode = global::HelloworldXamarin.Droid.Resource.Attribute.labelVisibilityMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.lastBaselineToBottomHeight = global::HelloworldXamarin.Droid.Resource.Attribute.lastBaselineToBottomHeight; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout = global::HelloworldXamarin.Droid.Resource.Attribute.layout; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.layoutManager = global::HelloworldXamarin.Droid.Resource.Attribute.layoutManager; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_anchor = global::HelloworldXamarin.Droid.Resource.Attribute.layout_anchor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_anchorGravity = global::HelloworldXamarin.Droid.Resource.Attribute.layout_anchorGravity; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_behavior = global::HelloworldXamarin.Droid.Resource.Attribute.layout_behavior; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_collapseMode = global::HelloworldXamarin.Droid.Resource.Attribute.layout_collapseMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_collapseParallaxMultiplier = global::HelloworldXamarin.Droid.Resource.Attribute.layout_collapseParallaxMultiplier; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_dodgeInsetEdges = global::HelloworldXamarin.Droid.Resource.Attribute.layout_dodgeInsetEdges; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_insetEdge = global::HelloworldXamarin.Droid.Resource.Attribute.layout_insetEdge; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_keyline = global::HelloworldXamarin.Droid.Resource.Attribute.layout_keyline; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_scrollFlags = global::HelloworldXamarin.Droid.Resource.Attribute.layout_scrollFlags; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.layout_scrollInterpolator = global::HelloworldXamarin.Droid.Resource.Attribute.layout_scrollInterpolator; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.liftOnScroll = global::HelloworldXamarin.Droid.Resource.Attribute.liftOnScroll; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.lineHeight = global::HelloworldXamarin.Droid.Resource.Attribute.lineHeight; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.lineSpacing = global::HelloworldXamarin.Droid.Resource.Attribute.lineSpacing; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.listChoiceBackgroundIndicator = global::HelloworldXamarin.Droid.Resource.Attribute.listChoiceBackgroundIndicator; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.listDividerAlertDialog = global::HelloworldXamarin.Droid.Resource.Attribute.listDividerAlertDialog; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.listItemLayout = global::HelloworldXamarin.Droid.Resource.Attribute.listItemLayout; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.listLayout = global::HelloworldXamarin.Droid.Resource.Attribute.listLayout; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.listMenuViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.listMenuViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.listPopupWindowStyle = global::HelloworldXamarin.Droid.Resource.Attribute.listPopupWindowStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.listPreferredItemHeight = global::HelloworldXamarin.Droid.Resource.Attribute.listPreferredItemHeight; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.listPreferredItemHeightLarge = global::HelloworldXamarin.Droid.Resource.Attribute.listPreferredItemHeightLarge; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.listPreferredItemHeightSmall = global::HelloworldXamarin.Droid.Resource.Attribute.listPreferredItemHeightSmall; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.listPreferredItemPaddingLeft = global::HelloworldXamarin.Droid.Resource.Attribute.listPreferredItemPaddingLeft; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.listPreferredItemPaddingRight = global::HelloworldXamarin.Droid.Resource.Attribute.listPreferredItemPaddingRight; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.logo = global::HelloworldXamarin.Droid.Resource.Attribute.logo; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.logoDescription = global::HelloworldXamarin.Droid.Resource.Attribute.logoDescription; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.materialButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.materialCardViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.materialCardViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.maxActionInlineWidth = global::HelloworldXamarin.Droid.Resource.Attribute.maxActionInlineWidth; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.maxButtonHeight = global::HelloworldXamarin.Droid.Resource.Attribute.maxButtonHeight; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.maxImageSize = global::HelloworldXamarin.Droid.Resource.Attribute.maxImageSize; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.measureWithLargestChild = global::HelloworldXamarin.Droid.Resource.Attribute.measureWithLargestChild; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.menu = global::HelloworldXamarin.Droid.Resource.Attribute.menu; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.multiChoiceItemLayout = global::HelloworldXamarin.Droid.Resource.Attribute.multiChoiceItemLayout; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.navigationContentDescription = global::HelloworldXamarin.Droid.Resource.Attribute.navigationContentDescription; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.navigationIcon = global::HelloworldXamarin.Droid.Resource.Attribute.navigationIcon; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.navigationMode = global::HelloworldXamarin.Droid.Resource.Attribute.navigationMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.navigationViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.navigationViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.numericModifiers = global::HelloworldXamarin.Droid.Resource.Attribute.numericModifiers; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.overlapAnchor = global::HelloworldXamarin.Droid.Resource.Attribute.overlapAnchor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.paddingBottomNoButtons = global::HelloworldXamarin.Droid.Resource.Attribute.paddingBottomNoButtons; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.paddingEnd = global::HelloworldXamarin.Droid.Resource.Attribute.paddingEnd; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.paddingStart = global::HelloworldXamarin.Droid.Resource.Attribute.paddingStart; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.paddingTopNoTitle = global::HelloworldXamarin.Droid.Resource.Attribute.paddingTopNoTitle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.panelBackground = global::HelloworldXamarin.Droid.Resource.Attribute.panelBackground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.panelMenuListTheme = global::HelloworldXamarin.Droid.Resource.Attribute.panelMenuListTheme; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.panelMenuListWidth = global::HelloworldXamarin.Droid.Resource.Attribute.panelMenuListWidth; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.passwordToggleContentDescription = global::HelloworldXamarin.Droid.Resource.Attribute.passwordToggleContentDescription; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.passwordToggleDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.passwordToggleDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.passwordToggleEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.passwordToggleEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.passwordToggleTint = global::HelloworldXamarin.Droid.Resource.Attribute.passwordToggleTint; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.passwordToggleTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.passwordToggleTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.popupMenuStyle = global::HelloworldXamarin.Droid.Resource.Attribute.popupMenuStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.popupTheme = global::HelloworldXamarin.Droid.Resource.Attribute.popupTheme; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.popupWindowStyle = global::HelloworldXamarin.Droid.Resource.Attribute.popupWindowStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.preserveIconSpacing = global::HelloworldXamarin.Droid.Resource.Attribute.preserveIconSpacing; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.pressedTranslationZ = global::HelloworldXamarin.Droid.Resource.Attribute.pressedTranslationZ; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.progressBarPadding = global::HelloworldXamarin.Droid.Resource.Attribute.progressBarPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.progressBarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.progressBarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.queryBackground = global::HelloworldXamarin.Droid.Resource.Attribute.queryBackground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.queryHint = global::HelloworldXamarin.Droid.Resource.Attribute.queryHint; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.radioButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.radioButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.ratingBarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.ratingBarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.ratingBarStyleIndicator = global::HelloworldXamarin.Droid.Resource.Attribute.ratingBarStyleIndicator; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.ratingBarStyleSmall = global::HelloworldXamarin.Droid.Resource.Attribute.ratingBarStyleSmall; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.reverseLayout = global::HelloworldXamarin.Droid.Resource.Attribute.reverseLayout; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.rippleColor = global::HelloworldXamarin.Droid.Resource.Attribute.rippleColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrimAnimationDuration = global::HelloworldXamarin.Droid.Resource.Attribute.scrimAnimationDuration; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrimBackground = global::HelloworldXamarin.Droid.Resource.Attribute.scrimBackground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrimVisibleHeightTrigger = global::HelloworldXamarin.Droid.Resource.Attribute.scrimVisibleHeightTrigger; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.searchHintIcon = global::HelloworldXamarin.Droid.Resource.Attribute.searchHintIcon; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.searchIcon = global::HelloworldXamarin.Droid.Resource.Attribute.searchIcon; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.searchViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.searchViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.seekBarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.seekBarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.selectableItemBackground = global::HelloworldXamarin.Droid.Resource.Attribute.selectableItemBackground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.selectableItemBackgroundBorderless = global::HelloworldXamarin.Droid.Resource.Attribute.selectableItemBackgroundBorderless; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.showAsAction = global::HelloworldXamarin.Droid.Resource.Attribute.showAsAction; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.showDividers = global::HelloworldXamarin.Droid.Resource.Attribute.showDividers; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.showMotionSpec = global::HelloworldXamarin.Droid.Resource.Attribute.showMotionSpec; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.showText = global::HelloworldXamarin.Droid.Resource.Attribute.showText; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.showTitle = global::HelloworldXamarin.Droid.Resource.Attribute.showTitle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.singleChoiceItemLayout = global::HelloworldXamarin.Droid.Resource.Attribute.singleChoiceItemLayout; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.singleLine = global::HelloworldXamarin.Droid.Resource.Attribute.singleLine; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.singleSelection = global::HelloworldXamarin.Droid.Resource.Attribute.singleSelection; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.snackbarButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.snackbarButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.snackbarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.snackbarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.spanCount = global::HelloworldXamarin.Droid.Resource.Attribute.spanCount; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.spinBars = global::HelloworldXamarin.Droid.Resource.Attribute.spinBars; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.spinnerDropDownItemStyle = global::HelloworldXamarin.Droid.Resource.Attribute.spinnerDropDownItemStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.spinnerStyle = global::HelloworldXamarin.Droid.Resource.Attribute.spinnerStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.splitTrack = global::HelloworldXamarin.Droid.Resource.Attribute.splitTrack; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.srcCompat = global::HelloworldXamarin.Droid.Resource.Attribute.srcCompat; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.stackFromEnd = global::HelloworldXamarin.Droid.Resource.Attribute.stackFromEnd; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.state_above_anchor = global::HelloworldXamarin.Droid.Resource.Attribute.state_above_anchor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.state_collapsed = global::HelloworldXamarin.Droid.Resource.Attribute.state_collapsed; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.state_collapsible = global::HelloworldXamarin.Droid.Resource.Attribute.state_collapsible; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.state_liftable = global::HelloworldXamarin.Droid.Resource.Attribute.state_liftable; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.state_lifted = global::HelloworldXamarin.Droid.Resource.Attribute.state_lifted; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.statusBarBackground = global::HelloworldXamarin.Droid.Resource.Attribute.statusBarBackground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.statusBarScrim = global::HelloworldXamarin.Droid.Resource.Attribute.statusBarScrim; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.strokeColor = global::HelloworldXamarin.Droid.Resource.Attribute.strokeColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.strokeWidth = global::HelloworldXamarin.Droid.Resource.Attribute.strokeWidth; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.subMenuArrow = global::HelloworldXamarin.Droid.Resource.Attribute.subMenuArrow; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.submitBackground = global::HelloworldXamarin.Droid.Resource.Attribute.submitBackground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.subtitle = global::HelloworldXamarin.Droid.Resource.Attribute.subtitle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.subtitleTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.subtitleTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.subtitleTextColor = global::HelloworldXamarin.Droid.Resource.Attribute.subtitleTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.subtitleTextStyle = global::HelloworldXamarin.Droid.Resource.Attribute.subtitleTextStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.suggestionRowLayout = global::HelloworldXamarin.Droid.Resource.Attribute.suggestionRowLayout; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.switchMinWidth = global::HelloworldXamarin.Droid.Resource.Attribute.switchMinWidth; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.switchPadding = global::HelloworldXamarin.Droid.Resource.Attribute.switchPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.switchStyle = global::HelloworldXamarin.Droid.Resource.Attribute.switchStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.switchTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.switchTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabBackground = global::HelloworldXamarin.Droid.Resource.Attribute.tabBackground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabContentStart = global::HelloworldXamarin.Droid.Resource.Attribute.tabContentStart; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabGravity = global::HelloworldXamarin.Droid.Resource.Attribute.tabGravity; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIconTint = global::HelloworldXamarin.Droid.Resource.Attribute.tabIconTint; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIconTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.tabIconTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIndicator = global::HelloworldXamarin.Droid.Resource.Attribute.tabIndicator; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIndicatorAnimationDuration = global::HelloworldXamarin.Droid.Resource.Attribute.tabIndicatorAnimationDuration; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIndicatorColor = global::HelloworldXamarin.Droid.Resource.Attribute.tabIndicatorColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIndicatorFullWidth = global::HelloworldXamarin.Droid.Resource.Attribute.tabIndicatorFullWidth; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIndicatorGravity = global::HelloworldXamarin.Droid.Resource.Attribute.tabIndicatorGravity; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabIndicatorHeight = global::HelloworldXamarin.Droid.Resource.Attribute.tabIndicatorHeight; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabInlineLabel = global::HelloworldXamarin.Droid.Resource.Attribute.tabInlineLabel; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabMaxWidth = global::HelloworldXamarin.Droid.Resource.Attribute.tabMaxWidth; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabMinWidth = global::HelloworldXamarin.Droid.Resource.Attribute.tabMinWidth; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabMode = global::HelloworldXamarin.Droid.Resource.Attribute.tabMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabPadding = global::HelloworldXamarin.Droid.Resource.Attribute.tabPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabPaddingBottom = global::HelloworldXamarin.Droid.Resource.Attribute.tabPaddingBottom; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabPaddingEnd = global::HelloworldXamarin.Droid.Resource.Attribute.tabPaddingEnd; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabPaddingStart = global::HelloworldXamarin.Droid.Resource.Attribute.tabPaddingStart; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabPaddingTop = global::HelloworldXamarin.Droid.Resource.Attribute.tabPaddingTop; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabRippleColor = global::HelloworldXamarin.Droid.Resource.Attribute.tabRippleColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabSelectedTextColor = global::HelloworldXamarin.Droid.Resource.Attribute.tabSelectedTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabStyle = global::HelloworldXamarin.Droid.Resource.Attribute.tabStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.tabTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabTextColor = global::HelloworldXamarin.Droid.Resource.Attribute.tabTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tabUnboundedRipple = global::HelloworldXamarin.Droid.Resource.Attribute.tabUnboundedRipple; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAllCaps = global::HelloworldXamarin.Droid.Resource.Attribute.textAllCaps; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceBody1 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceBody1; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceBody2 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceBody2; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceButton = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceButton; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceCaption = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceCaption; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceHeadline1 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceHeadline1; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceHeadline2 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceHeadline2; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceHeadline3 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceHeadline3; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceHeadline4 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceHeadline4; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceHeadline5 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceHeadline5; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceHeadline6 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceHeadline6; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceLargePopupMenu = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceLargePopupMenu; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceListItem = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceListItem; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceListItemSecondary = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceListItemSecondary; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceListItemSmall = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceListItemSmall; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceOverline = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceOverline; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearancePopupMenuHeader = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearancePopupMenuHeader; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceSearchResultSubtitle = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceSearchResultSubtitle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceSearchResultTitle = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceSearchResultTitle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceSmallPopupMenu = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceSmallPopupMenu; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceSubtitle1 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceSubtitle1; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textAppearanceSubtitle2 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceSubtitle2; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textColorAlertDialogListItem = global::HelloworldXamarin.Droid.Resource.Attribute.textColorAlertDialogListItem; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textColorSearchUrl = global::HelloworldXamarin.Droid.Resource.Attribute.textColorSearchUrl; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textEndPadding = global::HelloworldXamarin.Droid.Resource.Attribute.textEndPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textInputStyle = global::HelloworldXamarin.Droid.Resource.Attribute.textInputStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.textStartPadding = global::HelloworldXamarin.Droid.Resource.Attribute.textStartPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.theme = global::HelloworldXamarin.Droid.Resource.Attribute.theme; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.thickness = global::HelloworldXamarin.Droid.Resource.Attribute.thickness; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.thumbTextPadding = global::HelloworldXamarin.Droid.Resource.Attribute.thumbTextPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.thumbTint = global::HelloworldXamarin.Droid.Resource.Attribute.thumbTint; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.thumbTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.thumbTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tickMark = global::HelloworldXamarin.Droid.Resource.Attribute.tickMark; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tickMarkTint = global::HelloworldXamarin.Droid.Resource.Attribute.tickMarkTint; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tickMarkTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.tickMarkTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tint = global::HelloworldXamarin.Droid.Resource.Attribute.tint; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tintMode = global::HelloworldXamarin.Droid.Resource.Attribute.tintMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.title = global::HelloworldXamarin.Droid.Resource.Attribute.title; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.titleEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleMargin = global::HelloworldXamarin.Droid.Resource.Attribute.titleMargin; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleMarginBottom = global::HelloworldXamarin.Droid.Resource.Attribute.titleMarginBottom; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleMarginEnd = global::HelloworldXamarin.Droid.Resource.Attribute.titleMarginEnd; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleMargins = global::HelloworldXamarin.Droid.Resource.Attribute.titleMargins; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleMarginStart = global::HelloworldXamarin.Droid.Resource.Attribute.titleMarginStart; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleMarginTop = global::HelloworldXamarin.Droid.Resource.Attribute.titleMarginTop; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.titleTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleTextColor = global::HelloworldXamarin.Droid.Resource.Attribute.titleTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.titleTextStyle = global::HelloworldXamarin.Droid.Resource.Attribute.titleTextStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.toolbarId = global::HelloworldXamarin.Droid.Resource.Attribute.toolbarId; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.toolbarNavigationButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.toolbarNavigationButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.toolbarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.toolbarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tooltipForegroundColor = global::HelloworldXamarin.Droid.Resource.Attribute.tooltipForegroundColor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tooltipFrameBackground = global::HelloworldXamarin.Droid.Resource.Attribute.tooltipFrameBackground; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.tooltipText = global::HelloworldXamarin.Droid.Resource.Attribute.tooltipText; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.track = global::HelloworldXamarin.Droid.Resource.Attribute.track; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.trackTint = global::HelloworldXamarin.Droid.Resource.Attribute.trackTint; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.trackTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.trackTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.ttcIndex = global::HelloworldXamarin.Droid.Resource.Attribute.ttcIndex; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.useCompatPadding = global::HelloworldXamarin.Droid.Resource.Attribute.useCompatPadding; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.viewInflaterClass = global::HelloworldXamarin.Droid.Resource.Attribute.viewInflaterClass; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.voiceIcon = global::HelloworldXamarin.Droid.Resource.Attribute.voiceIcon; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowActionBar = global::HelloworldXamarin.Droid.Resource.Attribute.windowActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowActionBarOverlay = global::HelloworldXamarin.Droid.Resource.Attribute.windowActionBarOverlay; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowActionModeOverlay = global::HelloworldXamarin.Droid.Resource.Attribute.windowActionModeOverlay; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowFixedHeightMajor = global::HelloworldXamarin.Droid.Resource.Attribute.windowFixedHeightMajor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowFixedHeightMinor = global::HelloworldXamarin.Droid.Resource.Attribute.windowFixedHeightMinor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowFixedWidthMajor = global::HelloworldXamarin.Droid.Resource.Attribute.windowFixedWidthMajor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowFixedWidthMinor = global::HelloworldXamarin.Droid.Resource.Attribute.windowFixedWidthMinor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowMinWidthMajor = global::HelloworldXamarin.Droid.Resource.Attribute.windowMinWidthMajor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowMinWidthMinor = global::HelloworldXamarin.Droid.Resource.Attribute.windowMinWidthMinor; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.windowNoTitle = global::HelloworldXamarin.Droid.Resource.Attribute.windowNoTitle; + global::Xamarin.Forms.Platform.Android.Resource.Boolean.abc_action_bar_embed_tabs = global::HelloworldXamarin.Droid.Resource.Boolean.abc_action_bar_embed_tabs; + global::Xamarin.Forms.Platform.Android.Resource.Boolean.abc_allow_stacked_button_bar = global::HelloworldXamarin.Droid.Resource.Boolean.abc_allow_stacked_button_bar; + global::Xamarin.Forms.Platform.Android.Resource.Boolean.abc_config_actionMenuItemAllCaps = global::HelloworldXamarin.Droid.Resource.Boolean.abc_config_actionMenuItemAllCaps; + global::Xamarin.Forms.Platform.Android.Resource.Boolean.mtrl_btn_textappearance_all_caps = global::HelloworldXamarin.Droid.Resource.Boolean.mtrl_btn_textappearance_all_caps; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_background_cache_hint_selector_material_dark = global::HelloworldXamarin.Droid.Resource.Color.abc_background_cache_hint_selector_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_background_cache_hint_selector_material_light = global::HelloworldXamarin.Droid.Resource.Color.abc_background_cache_hint_selector_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_btn_colored_borderless_text_material = global::HelloworldXamarin.Droid.Resource.Color.abc_btn_colored_borderless_text_material; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_btn_colored_text_material = global::HelloworldXamarin.Droid.Resource.Color.abc_btn_colored_text_material; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_color_highlight_material = global::HelloworldXamarin.Droid.Resource.Color.abc_color_highlight_material; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_hint_foreground_material_dark = global::HelloworldXamarin.Droid.Resource.Color.abc_hint_foreground_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_hint_foreground_material_light = global::HelloworldXamarin.Droid.Resource.Color.abc_hint_foreground_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_input_method_navigation_guard = global::HelloworldXamarin.Droid.Resource.Color.abc_input_method_navigation_guard; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_primary_text_disable_only_material_dark = global::HelloworldXamarin.Droid.Resource.Color.abc_primary_text_disable_only_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_primary_text_disable_only_material_light = global::HelloworldXamarin.Droid.Resource.Color.abc_primary_text_disable_only_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_primary_text_material_dark = global::HelloworldXamarin.Droid.Resource.Color.abc_primary_text_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_primary_text_material_light = global::HelloworldXamarin.Droid.Resource.Color.abc_primary_text_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_search_url_text = global::HelloworldXamarin.Droid.Resource.Color.abc_search_url_text; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_search_url_text_normal = global::HelloworldXamarin.Droid.Resource.Color.abc_search_url_text_normal; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_search_url_text_pressed = global::HelloworldXamarin.Droid.Resource.Color.abc_search_url_text_pressed; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_search_url_text_selected = global::HelloworldXamarin.Droid.Resource.Color.abc_search_url_text_selected; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_secondary_text_material_dark = global::HelloworldXamarin.Droid.Resource.Color.abc_secondary_text_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_secondary_text_material_light = global::HelloworldXamarin.Droid.Resource.Color.abc_secondary_text_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_tint_btn_checkable = global::HelloworldXamarin.Droid.Resource.Color.abc_tint_btn_checkable; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_tint_default = global::HelloworldXamarin.Droid.Resource.Color.abc_tint_default; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_tint_edittext = global::HelloworldXamarin.Droid.Resource.Color.abc_tint_edittext; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_tint_seek_thumb = global::HelloworldXamarin.Droid.Resource.Color.abc_tint_seek_thumb; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_tint_spinner = global::HelloworldXamarin.Droid.Resource.Color.abc_tint_spinner; + global::Xamarin.Forms.Platform.Android.Resource.Color.abc_tint_switch_track = global::HelloworldXamarin.Droid.Resource.Color.abc_tint_switch_track; + global::Xamarin.Forms.Platform.Android.Resource.Color.accent_material_dark = global::HelloworldXamarin.Droid.Resource.Color.accent_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.accent_material_light = global::HelloworldXamarin.Droid.Resource.Color.accent_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.background_floating_material_dark = global::HelloworldXamarin.Droid.Resource.Color.background_floating_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.background_floating_material_light = global::HelloworldXamarin.Droid.Resource.Color.background_floating_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.background_material_dark = global::HelloworldXamarin.Droid.Resource.Color.background_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.background_material_light = global::HelloworldXamarin.Droid.Resource.Color.background_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.bright_foreground_disabled_material_dark = global::HelloworldXamarin.Droid.Resource.Color.bright_foreground_disabled_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.bright_foreground_disabled_material_light = global::HelloworldXamarin.Droid.Resource.Color.bright_foreground_disabled_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.bright_foreground_inverse_material_dark = global::HelloworldXamarin.Droid.Resource.Color.bright_foreground_inverse_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.bright_foreground_inverse_material_light = global::HelloworldXamarin.Droid.Resource.Color.bright_foreground_inverse_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.bright_foreground_material_dark = global::HelloworldXamarin.Droid.Resource.Color.bright_foreground_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.bright_foreground_material_light = global::HelloworldXamarin.Droid.Resource.Color.bright_foreground_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.button_material_dark = global::HelloworldXamarin.Droid.Resource.Color.button_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.button_material_light = global::HelloworldXamarin.Droid.Resource.Color.button_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.cardview_dark_background = global::HelloworldXamarin.Droid.Resource.Color.cardview_dark_background; + global::Xamarin.Forms.Platform.Android.Resource.Color.cardview_light_background = global::HelloworldXamarin.Droid.Resource.Color.cardview_light_background; + global::Xamarin.Forms.Platform.Android.Resource.Color.cardview_shadow_end_color = global::HelloworldXamarin.Droid.Resource.Color.cardview_shadow_end_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.cardview_shadow_start_color = global::HelloworldXamarin.Droid.Resource.Color.cardview_shadow_start_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.design_bottom_navigation_shadow_color = global::HelloworldXamarin.Droid.Resource.Color.design_bottom_navigation_shadow_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_primary = global::HelloworldXamarin.Droid.Resource.Color.design_default_color_primary; + global::Xamarin.Forms.Platform.Android.Resource.Color.design_default_color_primary_dark = global::HelloworldXamarin.Droid.Resource.Color.design_default_color_primary_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.design_error = global::HelloworldXamarin.Droid.Resource.Color.design_error; + global::Xamarin.Forms.Platform.Android.Resource.Color.design_fab_shadow_end_color = global::HelloworldXamarin.Droid.Resource.Color.design_fab_shadow_end_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.design_fab_shadow_mid_color = global::HelloworldXamarin.Droid.Resource.Color.design_fab_shadow_mid_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.design_fab_shadow_start_color = global::HelloworldXamarin.Droid.Resource.Color.design_fab_shadow_start_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.design_fab_stroke_end_inner_color = global::HelloworldXamarin.Droid.Resource.Color.design_fab_stroke_end_inner_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.design_fab_stroke_end_outer_color = global::HelloworldXamarin.Droid.Resource.Color.design_fab_stroke_end_outer_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.design_fab_stroke_top_inner_color = global::HelloworldXamarin.Droid.Resource.Color.design_fab_stroke_top_inner_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.design_fab_stroke_top_outer_color = global::HelloworldXamarin.Droid.Resource.Color.design_fab_stroke_top_outer_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.design_snackbar_background_color = global::HelloworldXamarin.Droid.Resource.Color.design_snackbar_background_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.design_tint_password_toggle = global::HelloworldXamarin.Droid.Resource.Color.design_tint_password_toggle; + global::Xamarin.Forms.Platform.Android.Resource.Color.dim_foreground_disabled_material_dark = global::HelloworldXamarin.Droid.Resource.Color.dim_foreground_disabled_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.dim_foreground_disabled_material_light = global::HelloworldXamarin.Droid.Resource.Color.dim_foreground_disabled_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.dim_foreground_material_dark = global::HelloworldXamarin.Droid.Resource.Color.dim_foreground_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.dim_foreground_material_light = global::HelloworldXamarin.Droid.Resource.Color.dim_foreground_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.error_color_material_dark = global::HelloworldXamarin.Droid.Resource.Color.error_color_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.error_color_material_light = global::HelloworldXamarin.Droid.Resource.Color.error_color_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.foreground_material_dark = global::HelloworldXamarin.Droid.Resource.Color.foreground_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.foreground_material_light = global::HelloworldXamarin.Droid.Resource.Color.foreground_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.highlighted_text_material_dark = global::HelloworldXamarin.Droid.Resource.Color.highlighted_text_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.highlighted_text_material_light = global::HelloworldXamarin.Droid.Resource.Color.highlighted_text_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.material_blue_grey_800 = global::HelloworldXamarin.Droid.Resource.Color.material_blue_grey_800; + global::Xamarin.Forms.Platform.Android.Resource.Color.material_blue_grey_900 = global::HelloworldXamarin.Droid.Resource.Color.material_blue_grey_900; + global::Xamarin.Forms.Platform.Android.Resource.Color.material_blue_grey_950 = global::HelloworldXamarin.Droid.Resource.Color.material_blue_grey_950; + global::Xamarin.Forms.Platform.Android.Resource.Color.material_deep_teal_200 = global::HelloworldXamarin.Droid.Resource.Color.material_deep_teal_200; + global::Xamarin.Forms.Platform.Android.Resource.Color.material_deep_teal_500 = global::HelloworldXamarin.Droid.Resource.Color.material_deep_teal_500; + global::Xamarin.Forms.Platform.Android.Resource.Color.material_grey_100 = global::HelloworldXamarin.Droid.Resource.Color.material_grey_100; + global::Xamarin.Forms.Platform.Android.Resource.Color.material_grey_300 = global::HelloworldXamarin.Droid.Resource.Color.material_grey_300; + global::Xamarin.Forms.Platform.Android.Resource.Color.material_grey_50 = global::HelloworldXamarin.Droid.Resource.Color.material_grey_50; + global::Xamarin.Forms.Platform.Android.Resource.Color.material_grey_600 = global::HelloworldXamarin.Droid.Resource.Color.material_grey_600; + global::Xamarin.Forms.Platform.Android.Resource.Color.material_grey_800 = global::HelloworldXamarin.Droid.Resource.Color.material_grey_800; + global::Xamarin.Forms.Platform.Android.Resource.Color.material_grey_850 = global::HelloworldXamarin.Droid.Resource.Color.material_grey_850; + global::Xamarin.Forms.Platform.Android.Resource.Color.material_grey_900 = global::HelloworldXamarin.Droid.Resource.Color.material_grey_900; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_bottom_nav_colored_item_tint = global::HelloworldXamarin.Droid.Resource.Color.mtrl_bottom_nav_colored_item_tint; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_bottom_nav_item_tint = global::HelloworldXamarin.Droid.Resource.Color.mtrl_bottom_nav_item_tint; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_bg_color_disabled = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_bg_color_disabled; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_bg_color_selector = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_bg_color_selector; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_ripple_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_ripple_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_stroke_color_selector = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_stroke_color_selector; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_text_btn_ripple_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_text_btn_ripple_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_text_color_disabled = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_text_color_disabled; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_text_color_selector = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_text_color_selector; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_btn_transparent_bg_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_transparent_bg_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_chip_background_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_chip_background_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_chip_close_icon_tint = global::HelloworldXamarin.Droid.Resource.Color.mtrl_chip_close_icon_tint; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_chip_ripple_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_chip_ripple_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_chip_text_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_chip_text_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_fab_ripple_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_fab_ripple_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_scrim_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_scrim_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_tabs_colored_ripple_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_tabs_colored_ripple_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_tabs_icon_color_selector = global::HelloworldXamarin.Droid.Resource.Color.mtrl_tabs_icon_color_selector; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_tabs_icon_color_selector_colored = global::HelloworldXamarin.Droid.Resource.Color.mtrl_tabs_icon_color_selector_colored; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_tabs_legacy_text_color_selector = global::HelloworldXamarin.Droid.Resource.Color.mtrl_tabs_legacy_text_color_selector; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_tabs_ripple_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_tabs_ripple_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_textinput_default_box_stroke_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_textinput_default_box_stroke_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_textinput_disabled_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_textinput_disabled_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_textinput_filled_box_default_background_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_textinput_filled_box_default_background_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_textinput_hovered_box_stroke_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_textinput_hovered_box_stroke_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.mtrl_text_btn_text_color_selector = global::HelloworldXamarin.Droid.Resource.Color.mtrl_text_btn_text_color_selector; + global::Xamarin.Forms.Platform.Android.Resource.Color.notification_action_color_filter = global::HelloworldXamarin.Droid.Resource.Color.notification_action_color_filter; + global::Xamarin.Forms.Platform.Android.Resource.Color.notification_icon_bg_color = global::HelloworldXamarin.Droid.Resource.Color.notification_icon_bg_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.notification_material_background_media_default_color = global::HelloworldXamarin.Droid.Resource.Color.notification_material_background_media_default_color; + global::Xamarin.Forms.Platform.Android.Resource.Color.primary_dark_material_dark = global::HelloworldXamarin.Droid.Resource.Color.primary_dark_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.primary_dark_material_light = global::HelloworldXamarin.Droid.Resource.Color.primary_dark_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.primary_material_dark = global::HelloworldXamarin.Droid.Resource.Color.primary_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.primary_material_light = global::HelloworldXamarin.Droid.Resource.Color.primary_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.primary_text_default_material_dark = global::HelloworldXamarin.Droid.Resource.Color.primary_text_default_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.primary_text_default_material_light = global::HelloworldXamarin.Droid.Resource.Color.primary_text_default_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.primary_text_disabled_material_dark = global::HelloworldXamarin.Droid.Resource.Color.primary_text_disabled_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.primary_text_disabled_material_light = global::HelloworldXamarin.Droid.Resource.Color.primary_text_disabled_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.ripple_material_dark = global::HelloworldXamarin.Droid.Resource.Color.ripple_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.ripple_material_light = global::HelloworldXamarin.Droid.Resource.Color.ripple_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.secondary_text_default_material_dark = global::HelloworldXamarin.Droid.Resource.Color.secondary_text_default_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.secondary_text_default_material_light = global::HelloworldXamarin.Droid.Resource.Color.secondary_text_default_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.secondary_text_disabled_material_dark = global::HelloworldXamarin.Droid.Resource.Color.secondary_text_disabled_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.secondary_text_disabled_material_light = global::HelloworldXamarin.Droid.Resource.Color.secondary_text_disabled_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.switch_thumb_disabled_material_dark = global::HelloworldXamarin.Droid.Resource.Color.switch_thumb_disabled_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.switch_thumb_disabled_material_light = global::HelloworldXamarin.Droid.Resource.Color.switch_thumb_disabled_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.switch_thumb_material_dark = global::HelloworldXamarin.Droid.Resource.Color.switch_thumb_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.switch_thumb_material_light = global::HelloworldXamarin.Droid.Resource.Color.switch_thumb_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.switch_thumb_normal_material_dark = global::HelloworldXamarin.Droid.Resource.Color.switch_thumb_normal_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.switch_thumb_normal_material_light = global::HelloworldXamarin.Droid.Resource.Color.switch_thumb_normal_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Color.tooltip_background_dark = global::HelloworldXamarin.Droid.Resource.Color.tooltip_background_dark; + global::Xamarin.Forms.Platform.Android.Resource.Color.tooltip_background_light = global::HelloworldXamarin.Droid.Resource.Color.tooltip_background_light; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_content_inset_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_content_inset_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_content_inset_with_nav = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_content_inset_with_nav; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_default_height_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_default_height_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_default_padding_end_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_default_padding_end_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_default_padding_start_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_default_padding_start_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_elevation_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_elevation_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_icon_vertical_padding_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_icon_vertical_padding_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_overflow_padding_end_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_overflow_padding_end_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_overflow_padding_start_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_overflow_padding_start_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_stacked_max_height = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_stacked_max_height; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_stacked_tab_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_stacked_tab_max_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_subtitle_bottom_margin_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_subtitle_bottom_margin_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_bar_subtitle_top_margin_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_subtitle_top_margin_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_button_min_height_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_button_min_height_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_button_min_width_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_button_min_width_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_action_button_min_width_overflow_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_button_min_width_overflow_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_alert_dialog_button_bar_height = global::HelloworldXamarin.Droid.Resource.Dimension.abc_alert_dialog_button_bar_height; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_alert_dialog_button_dimen = global::HelloworldXamarin.Droid.Resource.Dimension.abc_alert_dialog_button_dimen; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_button_inset_horizontal_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_button_inset_horizontal_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_button_inset_vertical_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_button_inset_vertical_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_button_padding_horizontal_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_button_padding_horizontal_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_button_padding_vertical_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_button_padding_vertical_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_cascading_menus_min_smallest_width = global::HelloworldXamarin.Droid.Resource.Dimension.abc_cascading_menus_min_smallest_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_config_prefDialogWidth = global::HelloworldXamarin.Droid.Resource.Dimension.abc_config_prefDialogWidth; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_control_corner_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_control_corner_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_control_inset_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_control_inset_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_control_padding_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_control_padding_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_corner_radius_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_corner_radius_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_fixed_height_major = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_fixed_height_major; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_fixed_height_minor = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_fixed_height_minor; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_fixed_width_major = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_fixed_width_major; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_fixed_width_minor = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_fixed_width_minor; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_list_padding_bottom_no_buttons = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_list_padding_bottom_no_buttons; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_list_padding_top_no_title = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_list_padding_top_no_title; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_min_width_major = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_min_width_major; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_min_width_minor = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_min_width_minor; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_padding_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_padding_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_padding_top_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_padding_top_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dialog_title_divider_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_title_divider_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_disabled_alpha_material_dark = global::HelloworldXamarin.Droid.Resource.Dimension.abc_disabled_alpha_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_disabled_alpha_material_light = global::HelloworldXamarin.Droid.Resource.Dimension.abc_disabled_alpha_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dropdownitem_icon_width = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dropdownitem_icon_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dropdownitem_text_padding_left = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dropdownitem_text_padding_left; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_dropdownitem_text_padding_right = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dropdownitem_text_padding_right; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_edit_text_inset_bottom_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_edit_text_inset_bottom_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_edit_text_inset_horizontal_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_edit_text_inset_horizontal_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_edit_text_inset_top_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_edit_text_inset_top_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_floating_window_z = global::HelloworldXamarin.Droid.Resource.Dimension.abc_floating_window_z; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_list_item_padding_horizontal_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_list_item_padding_horizontal_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_panel_menu_list_width = global::HelloworldXamarin.Droid.Resource.Dimension.abc_panel_menu_list_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_progress_bar_height_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_progress_bar_height_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_search_view_preferred_height = global::HelloworldXamarin.Droid.Resource.Dimension.abc_search_view_preferred_height; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_search_view_preferred_width = global::HelloworldXamarin.Droid.Resource.Dimension.abc_search_view_preferred_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_seekbar_track_background_height_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_seekbar_track_background_height_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_seekbar_track_progress_height_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_seekbar_track_progress_height_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_select_dialog_padding_start_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_select_dialog_padding_start_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_switch_padding = global::HelloworldXamarin.Droid.Resource.Dimension.abc_switch_padding; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_body_1_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_body_1_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_body_2_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_body_2_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_button_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_button_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_caption_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_caption_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_display_1_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_display_1_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_display_2_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_display_2_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_display_3_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_display_3_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_display_4_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_display_4_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_headline_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_headline_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_large_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_large_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_medium_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_medium_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_menu_header_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_menu_header_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_menu_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_menu_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_small_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_small_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_subhead_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_subhead_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_subtitle_material_toolbar = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_subtitle_material_toolbar; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_title_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_title_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.abc_text_size_title_material_toolbar = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_title_material_toolbar; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.cardview_compat_inset_shadow = global::HelloworldXamarin.Droid.Resource.Dimension.cardview_compat_inset_shadow; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.cardview_default_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.cardview_default_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.cardview_default_radius = global::HelloworldXamarin.Droid.Resource.Dimension.cardview_default_radius; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.compat_button_inset_horizontal_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_button_inset_horizontal_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.compat_button_inset_vertical_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_button_inset_vertical_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.compat_button_padding_horizontal_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_button_padding_horizontal_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.compat_button_padding_vertical_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_button_padding_vertical_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.compat_control_corner_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_control_corner_material; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.compat_notification_large_icon_max_height = global::HelloworldXamarin.Droid.Resource.Dimension.compat_notification_large_icon_max_height; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.compat_notification_large_icon_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.compat_notification_large_icon_max_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_appbar_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.design_appbar_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_active_item_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_active_item_max_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_active_item_min_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_active_item_min_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_active_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_active_text_size; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_height = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_height; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_icon_size = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_icon_size; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_item_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_item_max_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_item_min_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_item_min_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_margin = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_margin; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_shadow_height = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_shadow_height; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_navigation_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_text_size; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_sheet_modal_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_sheet_modal_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_bottom_sheet_peek_height_min = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_sheet_peek_height_min; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_fab_border_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_fab_border_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_fab_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.design_fab_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_fab_image_size = global::HelloworldXamarin.Droid.Resource.Dimension.design_fab_image_size; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_fab_size_mini = global::HelloworldXamarin.Droid.Resource.Dimension.design_fab_size_mini; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_fab_size_normal = global::HelloworldXamarin.Droid.Resource.Dimension.design_fab_size_normal; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_fab_translation_z_hovered_focused = global::HelloworldXamarin.Droid.Resource.Dimension.design_fab_translation_z_hovered_focused; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_fab_translation_z_pressed = global::HelloworldXamarin.Droid.Resource.Dimension.design_fab_translation_z_pressed; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_icon_padding = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_icon_padding; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_icon_size = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_icon_size; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_item_horizontal_padding = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_item_horizontal_padding; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_item_icon_padding = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_item_icon_padding; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_max_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_padding_bottom = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_padding_bottom; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_navigation_separator_vertical_padding = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_separator_vertical_padding; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_action_inline_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_action_inline_max_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_background_corner_radius = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_background_corner_radius; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_extra_spacing_horizontal = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_extra_spacing_horizontal; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_max_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_min_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_min_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_padding_horizontal = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_padding_horizontal; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_padding_vertical = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_padding_vertical; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_padding_vertical_2lines = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_padding_vertical_2lines; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_snackbar_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_text_size; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_tab_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_tab_max_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_tab_scrollable_min_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_tab_scrollable_min_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_tab_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.design_tab_text_size; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_tab_text_size_2line = global::HelloworldXamarin.Droid.Resource.Dimension.design_tab_text_size_2line; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.design_textinput_caption_translate_y = global::HelloworldXamarin.Droid.Resource.Dimension.design_textinput_caption_translate_y; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.disabled_alpha_material_dark = global::HelloworldXamarin.Droid.Resource.Dimension.disabled_alpha_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.disabled_alpha_material_light = global::HelloworldXamarin.Droid.Resource.Dimension.disabled_alpha_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.fastscroll_default_thickness = global::HelloworldXamarin.Droid.Resource.Dimension.fastscroll_default_thickness; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.fastscroll_margin = global::HelloworldXamarin.Droid.Resource.Dimension.fastscroll_margin; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.fastscroll_minimum_range = global::HelloworldXamarin.Droid.Resource.Dimension.fastscroll_minimum_range; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.highlight_alpha_material_colored = global::HelloworldXamarin.Droid.Resource.Dimension.highlight_alpha_material_colored; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.highlight_alpha_material_dark = global::HelloworldXamarin.Droid.Resource.Dimension.highlight_alpha_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.highlight_alpha_material_light = global::HelloworldXamarin.Droid.Resource.Dimension.highlight_alpha_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.hint_alpha_material_dark = global::HelloworldXamarin.Droid.Resource.Dimension.hint_alpha_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.hint_alpha_material_light = global::HelloworldXamarin.Droid.Resource.Dimension.hint_alpha_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.hint_pressed_alpha_material_dark = global::HelloworldXamarin.Droid.Resource.Dimension.hint_pressed_alpha_material_dark; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.hint_pressed_alpha_material_light = global::HelloworldXamarin.Droid.Resource.Dimension.hint_pressed_alpha_material_light; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.item_touch_helper_max_drag_scroll_per_frame = global::HelloworldXamarin.Droid.Resource.Dimension.item_touch_helper_max_drag_scroll_per_frame; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.item_touch_helper_swipe_escape_max_velocity = global::HelloworldXamarin.Droid.Resource.Dimension.item_touch_helper_swipe_escape_max_velocity; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.item_touch_helper_swipe_escape_velocity = global::HelloworldXamarin.Droid.Resource.Dimension.item_touch_helper_swipe_escape_velocity; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_bottomappbar_fabOffsetEndMode = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_bottomappbar_fabOffsetEndMode; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_bottomappbar_fab_cradle_margin = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_bottomappbar_fab_cradle_margin; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_bottomappbar_fab_cradle_rounded_corner_radius = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_bottomappbar_fab_cradle_rounded_corner_radius; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_bottomappbar_fab_cradle_vertical_offset = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_bottomappbar_fab_cradle_vertical_offset; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_bottomappbar_height = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_bottomappbar_height; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_corner_radius = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_corner_radius; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_dialog_btn_min_width = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_dialog_btn_min_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_disabled_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_disabled_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_disabled_z = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_disabled_z; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_focused_z = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_focused_z; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_hovered_z = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_hovered_z; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_icon_btn_padding_left = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_icon_btn_padding_left; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_icon_padding = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_icon_padding; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_inset = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_inset; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_letter_spacing = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_letter_spacing; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_padding_bottom = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_padding_bottom; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_padding_left = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_padding_left; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_padding_right = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_padding_right; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_padding_top = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_padding_top; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_pressed_z = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_pressed_z; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_stroke_size = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_stroke_size; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_text_btn_icon_padding = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_text_btn_icon_padding; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_text_btn_padding_left = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_text_btn_padding_left; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_text_btn_padding_right = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_text_btn_padding_right; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_text_size; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_btn_z = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_z; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_card_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_card_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_card_spacing = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_card_spacing; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_chip_pressed_translation_z = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_chip_pressed_translation_z; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_chip_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_chip_text_size; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_fab_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_fab_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_fab_translation_z_hovered_focused = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_fab_translation_z_hovered_focused; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_fab_translation_z_pressed = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_fab_translation_z_pressed; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_navigation_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_navigation_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_navigation_item_horizontal_padding = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_navigation_item_horizontal_padding; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_navigation_item_icon_padding = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_navigation_item_icon_padding; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_snackbar_background_corner_radius = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_snackbar_background_corner_radius; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_snackbar_margin = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_snackbar_margin; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_box_bottom_offset = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_box_bottom_offset; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_box_corner_radius_medium = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_box_corner_radius_medium; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_box_corner_radius_small = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_box_corner_radius_small; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_box_label_cutout_padding = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_box_label_cutout_padding; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_box_padding_end = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_box_padding_end; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_box_stroke_width_default = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_box_stroke_width_default; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_box_stroke_width_focused = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_box_stroke_width_focused; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_textinput_outline_box_expanded_padding = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_outline_box_expanded_padding; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.mtrl_toolbar_default_height = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_toolbar_default_height; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_action_icon_size = global::HelloworldXamarin.Droid.Resource.Dimension.notification_action_icon_size; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_action_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.notification_action_text_size; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_big_circle_margin = global::HelloworldXamarin.Droid.Resource.Dimension.notification_big_circle_margin; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_content_margin_start = global::HelloworldXamarin.Droid.Resource.Dimension.notification_content_margin_start; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_large_icon_height = global::HelloworldXamarin.Droid.Resource.Dimension.notification_large_icon_height; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_large_icon_width = global::HelloworldXamarin.Droid.Resource.Dimension.notification_large_icon_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_main_column_padding_top = global::HelloworldXamarin.Droid.Resource.Dimension.notification_main_column_padding_top; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_media_narrow_margin = global::HelloworldXamarin.Droid.Resource.Dimension.notification_media_narrow_margin; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_right_icon_size = global::HelloworldXamarin.Droid.Resource.Dimension.notification_right_icon_size; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_right_side_padding_top = global::HelloworldXamarin.Droid.Resource.Dimension.notification_right_side_padding_top; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_small_icon_background_padding = global::HelloworldXamarin.Droid.Resource.Dimension.notification_small_icon_background_padding; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_small_icon_size_as_large = global::HelloworldXamarin.Droid.Resource.Dimension.notification_small_icon_size_as_large; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_subtext_size = global::HelloworldXamarin.Droid.Resource.Dimension.notification_subtext_size; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_top_pad = global::HelloworldXamarin.Droid.Resource.Dimension.notification_top_pad; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.notification_top_pad_large_text = global::HelloworldXamarin.Droid.Resource.Dimension.notification_top_pad_large_text; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.subtitle_corner_radius = global::HelloworldXamarin.Droid.Resource.Dimension.subtitle_corner_radius; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.subtitle_outline_width = global::HelloworldXamarin.Droid.Resource.Dimension.subtitle_outline_width; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.subtitle_shadow_offset = global::HelloworldXamarin.Droid.Resource.Dimension.subtitle_shadow_offset; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.subtitle_shadow_radius = global::HelloworldXamarin.Droid.Resource.Dimension.subtitle_shadow_radius; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_corner_radius = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_corner_radius; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_horizontal_padding = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_horizontal_padding; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_margin = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_margin; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_precise_anchor_extra_offset = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_precise_anchor_extra_offset; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_precise_anchor_threshold = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_precise_anchor_threshold; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_vertical_padding = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_vertical_padding; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_y_offset_non_touch = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_y_offset_non_touch; + global::Xamarin.Forms.Platform.Android.Resource.Dimension.tooltip_y_offset_touch = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_y_offset_touch; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ab_share_pack_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ab_share_pack_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_action_bar_item_background_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_action_bar_item_background_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_borderless_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_borderless_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_check_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_check_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_check_to_on_mtrl_000 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_check_to_on_mtrl_000; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_check_to_on_mtrl_015 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_check_to_on_mtrl_015; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_colored_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_colored_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_default_mtrl_shape = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_default_mtrl_shape; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_radio_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_radio_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_radio_to_on_mtrl_000 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_radio_to_on_mtrl_000; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_radio_to_on_mtrl_015 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_radio_to_on_mtrl_015; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_switch_to_on_mtrl_00001 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_switch_to_on_mtrl_00001; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_btn_switch_to_on_mtrl_00012 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_switch_to_on_mtrl_00012; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_cab_background_internal_bg = global::HelloworldXamarin.Droid.Resource.Drawable.abc_cab_background_internal_bg; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_cab_background_top_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_cab_background_top_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_cab_background_top_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_cab_background_top_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_control_background_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_control_background_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_dialog_material_background = global::HelloworldXamarin.Droid.Resource.Drawable.abc_dialog_material_background; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_edit_text_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_edit_text_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_ab_back_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_ab_back_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_arrow_drop_right_black_24dp = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_arrow_drop_right_black_24dp; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_clear_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_clear_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_commit_search_api_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_commit_search_api_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_go_search_api_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_go_search_api_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_menu_copy_mtrl_am_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_menu_copy_mtrl_am_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_menu_cut_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_menu_cut_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_menu_overflow_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_menu_overflow_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_menu_paste_mtrl_am_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_menu_paste_mtrl_am_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_menu_selectall_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_menu_selectall_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_menu_share_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_menu_share_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_search_api_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_search_api_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_star_black_16dp = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_star_black_16dp; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_star_black_36dp = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_star_black_36dp; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_star_black_48dp = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_star_black_48dp; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_star_half_black_16dp = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_star_half_black_16dp; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_star_half_black_36dp = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_star_half_black_36dp; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_star_half_black_48dp = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_star_half_black_48dp; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ic_voice_search_api_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_voice_search_api_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_item_background_holo_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_item_background_holo_dark; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_item_background_holo_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_item_background_holo_light; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_divider_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_divider_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_divider_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_divider_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_focused_holo = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_focused_holo; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_longpressed_holo = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_longpressed_holo; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_pressed_holo_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_pressed_holo_dark; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_pressed_holo_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_pressed_holo_light; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_selector_background_transition_holo_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_selector_background_transition_holo_dark; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_selector_background_transition_holo_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_selector_background_transition_holo_light; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_selector_disabled_holo_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_selector_disabled_holo_dark; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_selector_disabled_holo_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_selector_disabled_holo_light; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_selector_holo_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_selector_holo_dark; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_list_selector_holo_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_selector_holo_light; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_menu_hardkey_panel_mtrl_mult = global::HelloworldXamarin.Droid.Resource.Drawable.abc_menu_hardkey_panel_mtrl_mult; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_popup_background_mtrl_mult = global::HelloworldXamarin.Droid.Resource.Drawable.abc_popup_background_mtrl_mult; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ratingbar_indicator_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ratingbar_indicator_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ratingbar_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ratingbar_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_ratingbar_small_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ratingbar_small_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_scrubber_control_off_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_scrubber_control_off_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_000 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_000; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_005 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_005; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_scrubber_primary_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_scrubber_primary_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_scrubber_track_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_scrubber_track_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_seekbar_thumb_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_seekbar_thumb_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_seekbar_tick_mark_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_seekbar_tick_mark_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_seekbar_track_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_seekbar_track_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_spinner_mtrl_am_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_spinner_mtrl_am_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_spinner_textfield_background_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_spinner_textfield_background_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_switch_thumb_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_switch_thumb_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_switch_track_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_switch_track_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_tab_indicator_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_tab_indicator_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_tab_indicator_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_tab_indicator_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_textfield_activated_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_textfield_activated_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_textfield_default_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_textfield_default_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_textfield_search_activated_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_textfield_search_activated_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_textfield_search_default_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_textfield_search_default_mtrl_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_textfield_search_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_textfield_search_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_text_cursor_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_text_cursor_material; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_text_select_handle_left_mtrl_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_text_select_handle_left_mtrl_dark; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_text_select_handle_left_mtrl_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_text_select_handle_left_mtrl_light; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_text_select_handle_middle_mtrl_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_text_select_handle_middle_mtrl_dark; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_text_select_handle_middle_mtrl_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_text_select_handle_middle_mtrl_light; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_text_select_handle_right_mtrl_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_text_select_handle_right_mtrl_dark; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_text_select_handle_right_mtrl_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_text_select_handle_right_mtrl_light; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.abc_vector_test = global::HelloworldXamarin.Droid.Resource.Drawable.abc_vector_test; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.avd_hide_password = global::HelloworldXamarin.Droid.Resource.Drawable.avd_hide_password; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.avd_show_password = global::HelloworldXamarin.Droid.Resource.Drawable.avd_show_password; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.design_bottom_navigation_item_background = global::HelloworldXamarin.Droid.Resource.Drawable.design_bottom_navigation_item_background; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.design_fab_background = global::HelloworldXamarin.Droid.Resource.Drawable.design_fab_background; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.design_ic_visibility = global::HelloworldXamarin.Droid.Resource.Drawable.design_ic_visibility; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.design_ic_visibility_off = global::HelloworldXamarin.Droid.Resource.Drawable.design_ic_visibility_off; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.design_password_eye = global::HelloworldXamarin.Droid.Resource.Drawable.design_password_eye; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.design_snackbar_background = global::HelloworldXamarin.Droid.Resource.Drawable.design_snackbar_background; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.ic_mtrl_chip_checked_black = global::HelloworldXamarin.Droid.Resource.Drawable.ic_mtrl_chip_checked_black; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.ic_mtrl_chip_checked_circle = global::HelloworldXamarin.Droid.Resource.Drawable.ic_mtrl_chip_checked_circle; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.ic_mtrl_chip_close_circle = global::HelloworldXamarin.Droid.Resource.Drawable.ic_mtrl_chip_close_circle; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.mtrl_snackbar_background = global::HelloworldXamarin.Droid.Resource.Drawable.mtrl_snackbar_background; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.mtrl_tabs_default_indicator = global::HelloworldXamarin.Droid.Resource.Drawable.mtrl_tabs_default_indicator; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.navigation_empty_icon = global::HelloworldXamarin.Droid.Resource.Drawable.navigation_empty_icon; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_action_background = global::HelloworldXamarin.Droid.Resource.Drawable.notification_action_background; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_bg_low = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_low; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_bg_low_normal = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_low_normal; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_bg_low_pressed = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_low_pressed; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_bg_normal = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_normal; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_bg_normal_pressed = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_normal_pressed; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_icon_background = global::HelloworldXamarin.Droid.Resource.Drawable.notification_icon_background; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_template_icon_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notification_template_icon_bg; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_template_icon_low_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notification_template_icon_low_bg; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.notification_tile_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notification_tile_bg; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.notify_panel_notification_icon_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notify_panel_notification_icon_bg; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.tooltip_frame_dark = global::HelloworldXamarin.Droid.Resource.Drawable.tooltip_frame_dark; + global::Xamarin.Forms.Platform.Android.Resource.Drawable.tooltip_frame_light = global::HelloworldXamarin.Droid.Resource.Drawable.tooltip_frame_light; + global::Xamarin.Forms.Platform.Android.Resource.Id.action0 = global::HelloworldXamarin.Droid.Resource.Id.action0; + global::Xamarin.Forms.Platform.Android.Resource.Id.actions = global::HelloworldXamarin.Droid.Resource.Id.actions; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_bar = global::HelloworldXamarin.Droid.Resource.Id.action_bar; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_bar_activity_content = global::HelloworldXamarin.Droid.Resource.Id.action_bar_activity_content; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_bar_container = global::HelloworldXamarin.Droid.Resource.Id.action_bar_container; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_bar_root = global::HelloworldXamarin.Droid.Resource.Id.action_bar_root; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_bar_spinner = global::HelloworldXamarin.Droid.Resource.Id.action_bar_spinner; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_bar_subtitle = global::HelloworldXamarin.Droid.Resource.Id.action_bar_subtitle; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_bar_title = global::HelloworldXamarin.Droid.Resource.Id.action_bar_title; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_container = global::HelloworldXamarin.Droid.Resource.Id.action_container; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_context_bar = global::HelloworldXamarin.Droid.Resource.Id.action_context_bar; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_divider = global::HelloworldXamarin.Droid.Resource.Id.action_divider; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_image = global::HelloworldXamarin.Droid.Resource.Id.action_image; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_menu_divider = global::HelloworldXamarin.Droid.Resource.Id.action_menu_divider; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_menu_presenter = global::HelloworldXamarin.Droid.Resource.Id.action_menu_presenter; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_mode_bar = global::HelloworldXamarin.Droid.Resource.Id.action_mode_bar; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_mode_bar_stub = global::HelloworldXamarin.Droid.Resource.Id.action_mode_bar_stub; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_mode_close_button = global::HelloworldXamarin.Droid.Resource.Id.action_mode_close_button; + global::Xamarin.Forms.Platform.Android.Resource.Id.action_text = global::HelloworldXamarin.Droid.Resource.Id.action_text; + global::Xamarin.Forms.Platform.Android.Resource.Id.activity_chooser_view_content = global::HelloworldXamarin.Droid.Resource.Id.activity_chooser_view_content; + global::Xamarin.Forms.Platform.Android.Resource.Id.add = global::HelloworldXamarin.Droid.Resource.Id.add; + global::Xamarin.Forms.Platform.Android.Resource.Id.alertTitle = global::HelloworldXamarin.Droid.Resource.Id.alertTitle; + global::Xamarin.Forms.Platform.Android.Resource.Id.all = global::HelloworldXamarin.Droid.Resource.Id.all; + global::Xamarin.Forms.Platform.Android.Resource.Id.ALT = global::HelloworldXamarin.Droid.Resource.Id.ALT; + global::Xamarin.Forms.Platform.Android.Resource.Id.always = global::HelloworldXamarin.Droid.Resource.Id.always; + global::Xamarin.Forms.Platform.Android.Resource.Id.async = global::HelloworldXamarin.Droid.Resource.Id.async; + global::Xamarin.Forms.Platform.Android.Resource.Id.auto = global::HelloworldXamarin.Droid.Resource.Id.auto; + global::Xamarin.Forms.Platform.Android.Resource.Id.beginning = global::HelloworldXamarin.Droid.Resource.Id.beginning; + global::Xamarin.Forms.Platform.Android.Resource.Id.blocking = global::HelloworldXamarin.Droid.Resource.Id.blocking; + global::Xamarin.Forms.Platform.Android.Resource.Id.bottom = global::HelloworldXamarin.Droid.Resource.Id.bottom; + global::Xamarin.Forms.Platform.Android.Resource.Id.bottomtab_navarea = global::HelloworldXamarin.Droid.Resource.Id.bottomtab_navarea; + global::Xamarin.Forms.Platform.Android.Resource.Id.bottomtab_tabbar = global::HelloworldXamarin.Droid.Resource.Id.bottomtab_tabbar; + global::Xamarin.Forms.Platform.Android.Resource.Id.buttonPanel = global::HelloworldXamarin.Droid.Resource.Id.buttonPanel; + global::Xamarin.Forms.Platform.Android.Resource.Id.cancel_action = global::HelloworldXamarin.Droid.Resource.Id.cancel_action; + global::Xamarin.Forms.Platform.Android.Resource.Id.center = global::HelloworldXamarin.Droid.Resource.Id.center; + global::Xamarin.Forms.Platform.Android.Resource.Id.center_horizontal = global::HelloworldXamarin.Droid.Resource.Id.center_horizontal; + global::Xamarin.Forms.Platform.Android.Resource.Id.center_vertical = global::HelloworldXamarin.Droid.Resource.Id.center_vertical; + global::Xamarin.Forms.Platform.Android.Resource.Id.checkbox = global::HelloworldXamarin.Droid.Resource.Id.checkbox; + global::Xamarin.Forms.Platform.Android.Resource.Id.chronometer = global::HelloworldXamarin.Droid.Resource.Id.chronometer; + global::Xamarin.Forms.Platform.Android.Resource.Id.clip_horizontal = global::HelloworldXamarin.Droid.Resource.Id.clip_horizontal; + global::Xamarin.Forms.Platform.Android.Resource.Id.clip_vertical = global::HelloworldXamarin.Droid.Resource.Id.clip_vertical; + global::Xamarin.Forms.Platform.Android.Resource.Id.collapseActionView = global::HelloworldXamarin.Droid.Resource.Id.collapseActionView; + global::Xamarin.Forms.Platform.Android.Resource.Id.container = global::HelloworldXamarin.Droid.Resource.Id.container; + global::Xamarin.Forms.Platform.Android.Resource.Id.content = global::HelloworldXamarin.Droid.Resource.Id.content; + global::Xamarin.Forms.Platform.Android.Resource.Id.contentPanel = global::HelloworldXamarin.Droid.Resource.Id.contentPanel; + global::Xamarin.Forms.Platform.Android.Resource.Id.coordinator = global::HelloworldXamarin.Droid.Resource.Id.coordinator; + global::Xamarin.Forms.Platform.Android.Resource.Id.CTRL = global::HelloworldXamarin.Droid.Resource.Id.CTRL; + global::Xamarin.Forms.Platform.Android.Resource.Id.custom = global::HelloworldXamarin.Droid.Resource.Id.custom; + global::Xamarin.Forms.Platform.Android.Resource.Id.customPanel = global::HelloworldXamarin.Droid.Resource.Id.customPanel; + global::Xamarin.Forms.Platform.Android.Resource.Id.decor_content_parent = global::HelloworldXamarin.Droid.Resource.Id.decor_content_parent; + global::Xamarin.Forms.Platform.Android.Resource.Id.default_activity_button = global::HelloworldXamarin.Droid.Resource.Id.default_activity_button; + global::Xamarin.Forms.Platform.Android.Resource.Id.design_bottom_sheet = global::HelloworldXamarin.Droid.Resource.Id.design_bottom_sheet; + global::Xamarin.Forms.Platform.Android.Resource.Id.design_menu_item_action_area = global::HelloworldXamarin.Droid.Resource.Id.design_menu_item_action_area; + global::Xamarin.Forms.Platform.Android.Resource.Id.design_menu_item_action_area_stub = global::HelloworldXamarin.Droid.Resource.Id.design_menu_item_action_area_stub; + global::Xamarin.Forms.Platform.Android.Resource.Id.design_menu_item_text = global::HelloworldXamarin.Droid.Resource.Id.design_menu_item_text; + global::Xamarin.Forms.Platform.Android.Resource.Id.design_navigation_view = global::HelloworldXamarin.Droid.Resource.Id.design_navigation_view; + global::Xamarin.Forms.Platform.Android.Resource.Id.disableHome = global::HelloworldXamarin.Droid.Resource.Id.disableHome; + global::Xamarin.Forms.Platform.Android.Resource.Id.edit_query = global::HelloworldXamarin.Droid.Resource.Id.edit_query; + global::Xamarin.Forms.Platform.Android.Resource.Id.end = global::HelloworldXamarin.Droid.Resource.Id.end; + global::Xamarin.Forms.Platform.Android.Resource.Id.end_padder = global::HelloworldXamarin.Droid.Resource.Id.end_padder; + global::Xamarin.Forms.Platform.Android.Resource.Id.enterAlways = global::HelloworldXamarin.Droid.Resource.Id.enterAlways; + global::Xamarin.Forms.Platform.Android.Resource.Id.enterAlwaysCollapsed = global::HelloworldXamarin.Droid.Resource.Id.enterAlwaysCollapsed; + global::Xamarin.Forms.Platform.Android.Resource.Id.exitUntilCollapsed = global::HelloworldXamarin.Droid.Resource.Id.exitUntilCollapsed; + global::Xamarin.Forms.Platform.Android.Resource.Id.expanded_menu = global::HelloworldXamarin.Droid.Resource.Id.expanded_menu; + global::Xamarin.Forms.Platform.Android.Resource.Id.expand_activities_button = global::HelloworldXamarin.Droid.Resource.Id.expand_activities_button; + global::Xamarin.Forms.Platform.Android.Resource.Id.fill = global::HelloworldXamarin.Droid.Resource.Id.fill; + global::Xamarin.Forms.Platform.Android.Resource.Id.filled = global::HelloworldXamarin.Droid.Resource.Id.filled; + global::Xamarin.Forms.Platform.Android.Resource.Id.fill_horizontal = global::HelloworldXamarin.Droid.Resource.Id.fill_horizontal; + global::Xamarin.Forms.Platform.Android.Resource.Id.fill_vertical = global::HelloworldXamarin.Droid.Resource.Id.fill_vertical; + global::Xamarin.Forms.Platform.Android.Resource.Id.@fixed = global::HelloworldXamarin.Droid.Resource.Id.@fixed; + global::Xamarin.Forms.Platform.Android.Resource.Id.flyoutcontent_appbar = global::HelloworldXamarin.Droid.Resource.Id.flyoutcontent_appbar; + global::Xamarin.Forms.Platform.Android.Resource.Id.flyoutcontent_recycler = global::HelloworldXamarin.Droid.Resource.Id.flyoutcontent_recycler; + global::Xamarin.Forms.Platform.Android.Resource.Id.forever = global::HelloworldXamarin.Droid.Resource.Id.forever; + global::Xamarin.Forms.Platform.Android.Resource.Id.FUNCTION = global::HelloworldXamarin.Droid.Resource.Id.FUNCTION; + global::Xamarin.Forms.Platform.Android.Resource.Id.ghost_view = global::HelloworldXamarin.Droid.Resource.Id.ghost_view; + global::Xamarin.Forms.Platform.Android.Resource.Id.group_divider = global::HelloworldXamarin.Droid.Resource.Id.group_divider; + global::Xamarin.Forms.Platform.Android.Resource.Id.home = global::HelloworldXamarin.Droid.Resource.Id.home; + global::Xamarin.Forms.Platform.Android.Resource.Id.homeAsUp = global::HelloworldXamarin.Droid.Resource.Id.homeAsUp; + global::Xamarin.Forms.Platform.Android.Resource.Id.icon = global::HelloworldXamarin.Droid.Resource.Id.icon; + global::Xamarin.Forms.Platform.Android.Resource.Id.icon_group = global::HelloworldXamarin.Droid.Resource.Id.icon_group; + global::Xamarin.Forms.Platform.Android.Resource.Id.ifRoom = global::HelloworldXamarin.Droid.Resource.Id.ifRoom; + global::Xamarin.Forms.Platform.Android.Resource.Id.image = global::HelloworldXamarin.Droid.Resource.Id.image; + global::Xamarin.Forms.Platform.Android.Resource.Id.info = global::HelloworldXamarin.Droid.Resource.Id.info; + global::Xamarin.Forms.Platform.Android.Resource.Id.italic = global::HelloworldXamarin.Droid.Resource.Id.italic; + global::Xamarin.Forms.Platform.Android.Resource.Id.item_touch_helper_previous_elevation = global::HelloworldXamarin.Droid.Resource.Id.item_touch_helper_previous_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Id.labeled = global::HelloworldXamarin.Droid.Resource.Id.labeled; + global::Xamarin.Forms.Platform.Android.Resource.Id.largeLabel = global::HelloworldXamarin.Droid.Resource.Id.largeLabel; + global::Xamarin.Forms.Platform.Android.Resource.Id.left = global::HelloworldXamarin.Droid.Resource.Id.left; + global::Xamarin.Forms.Platform.Android.Resource.Id.line1 = global::HelloworldXamarin.Droid.Resource.Id.line1; + global::Xamarin.Forms.Platform.Android.Resource.Id.line3 = global::HelloworldXamarin.Droid.Resource.Id.line3; + global::Xamarin.Forms.Platform.Android.Resource.Id.listMode = global::HelloworldXamarin.Droid.Resource.Id.listMode; + global::Xamarin.Forms.Platform.Android.Resource.Id.list_item = global::HelloworldXamarin.Droid.Resource.Id.list_item; + global::Xamarin.Forms.Platform.Android.Resource.Id.main_appbar = global::HelloworldXamarin.Droid.Resource.Id.main_appbar; + global::Xamarin.Forms.Platform.Android.Resource.Id.main_tablayout = global::HelloworldXamarin.Droid.Resource.Id.main_tablayout; + global::Xamarin.Forms.Platform.Android.Resource.Id.main_toolbar = global::HelloworldXamarin.Droid.Resource.Id.main_toolbar; + global::Xamarin.Forms.Platform.Android.Resource.Id.main_viewpager = global::HelloworldXamarin.Droid.Resource.Id.main_viewpager; + global::Xamarin.Forms.Platform.Android.Resource.Id.masked = global::HelloworldXamarin.Droid.Resource.Id.masked; + global::Xamarin.Forms.Platform.Android.Resource.Id.media_actions = global::HelloworldXamarin.Droid.Resource.Id.media_actions; + global::Xamarin.Forms.Platform.Android.Resource.Id.message = global::HelloworldXamarin.Droid.Resource.Id.message; + global::Xamarin.Forms.Platform.Android.Resource.Id.META = global::HelloworldXamarin.Droid.Resource.Id.META; + global::Xamarin.Forms.Platform.Android.Resource.Id.middle = global::HelloworldXamarin.Droid.Resource.Id.middle; + global::Xamarin.Forms.Platform.Android.Resource.Id.mini = global::HelloworldXamarin.Droid.Resource.Id.mini; + global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_child_content_container = global::HelloworldXamarin.Droid.Resource.Id.mtrl_child_content_container; + global::Xamarin.Forms.Platform.Android.Resource.Id.mtrl_internal_children_alpha_tag = global::HelloworldXamarin.Droid.Resource.Id.mtrl_internal_children_alpha_tag; + global::Xamarin.Forms.Platform.Android.Resource.Id.multiply = global::HelloworldXamarin.Droid.Resource.Id.multiply; + global::Xamarin.Forms.Platform.Android.Resource.Id.navigation_header_container = global::HelloworldXamarin.Droid.Resource.Id.navigation_header_container; + global::Xamarin.Forms.Platform.Android.Resource.Id.never = global::HelloworldXamarin.Droid.Resource.Id.never; + global::Xamarin.Forms.Platform.Android.Resource.Id.none = global::HelloworldXamarin.Droid.Resource.Id.none; + global::Xamarin.Forms.Platform.Android.Resource.Id.normal = global::HelloworldXamarin.Droid.Resource.Id.normal; + global::Xamarin.Forms.Platform.Android.Resource.Id.notification_background = global::HelloworldXamarin.Droid.Resource.Id.notification_background; + global::Xamarin.Forms.Platform.Android.Resource.Id.notification_main_column = global::HelloworldXamarin.Droid.Resource.Id.notification_main_column; + global::Xamarin.Forms.Platform.Android.Resource.Id.notification_main_column_container = global::HelloworldXamarin.Droid.Resource.Id.notification_main_column_container; + global::Xamarin.Forms.Platform.Android.Resource.Id.outline = global::HelloworldXamarin.Droid.Resource.Id.outline; + global::Xamarin.Forms.Platform.Android.Resource.Id.parallax = global::HelloworldXamarin.Droid.Resource.Id.parallax; + global::Xamarin.Forms.Platform.Android.Resource.Id.parentPanel = global::HelloworldXamarin.Droid.Resource.Id.parentPanel; + global::Xamarin.Forms.Platform.Android.Resource.Id.parent_matrix = global::HelloworldXamarin.Droid.Resource.Id.parent_matrix; + global::Xamarin.Forms.Platform.Android.Resource.Id.pin = global::HelloworldXamarin.Droid.Resource.Id.pin; + global::Xamarin.Forms.Platform.Android.Resource.Id.progress_circular = global::HelloworldXamarin.Droid.Resource.Id.progress_circular; + global::Xamarin.Forms.Platform.Android.Resource.Id.progress_horizontal = global::HelloworldXamarin.Droid.Resource.Id.progress_horizontal; + global::Xamarin.Forms.Platform.Android.Resource.Id.radio = global::HelloworldXamarin.Droid.Resource.Id.radio; + global::Xamarin.Forms.Platform.Android.Resource.Id.right = global::HelloworldXamarin.Droid.Resource.Id.right; + global::Xamarin.Forms.Platform.Android.Resource.Id.right_icon = global::HelloworldXamarin.Droid.Resource.Id.right_icon; + global::Xamarin.Forms.Platform.Android.Resource.Id.right_side = global::HelloworldXamarin.Droid.Resource.Id.right_side; + global::Xamarin.Forms.Platform.Android.Resource.Id.save_image_matrix = global::HelloworldXamarin.Droid.Resource.Id.save_image_matrix; + global::Xamarin.Forms.Platform.Android.Resource.Id.save_non_transition_alpha = global::HelloworldXamarin.Droid.Resource.Id.save_non_transition_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Id.save_scale_type = global::HelloworldXamarin.Droid.Resource.Id.save_scale_type; + global::Xamarin.Forms.Platform.Android.Resource.Id.screen = global::HelloworldXamarin.Droid.Resource.Id.screen; + global::Xamarin.Forms.Platform.Android.Resource.Id.scroll = global::HelloworldXamarin.Droid.Resource.Id.scroll; + global::Xamarin.Forms.Platform.Android.Resource.Id.scrollable = global::HelloworldXamarin.Droid.Resource.Id.scrollable; + global::Xamarin.Forms.Platform.Android.Resource.Id.scrollIndicatorDown = global::HelloworldXamarin.Droid.Resource.Id.scrollIndicatorDown; + global::Xamarin.Forms.Platform.Android.Resource.Id.scrollIndicatorUp = global::HelloworldXamarin.Droid.Resource.Id.scrollIndicatorUp; + global::Xamarin.Forms.Platform.Android.Resource.Id.scrollView = global::HelloworldXamarin.Droid.Resource.Id.scrollView; + global::Xamarin.Forms.Platform.Android.Resource.Id.search_badge = global::HelloworldXamarin.Droid.Resource.Id.search_badge; + global::Xamarin.Forms.Platform.Android.Resource.Id.search_bar = global::HelloworldXamarin.Droid.Resource.Id.search_bar; + global::Xamarin.Forms.Platform.Android.Resource.Id.search_button = global::HelloworldXamarin.Droid.Resource.Id.search_button; + global::Xamarin.Forms.Platform.Android.Resource.Id.search_close_btn = global::HelloworldXamarin.Droid.Resource.Id.search_close_btn; + global::Xamarin.Forms.Platform.Android.Resource.Id.search_edit_frame = global::HelloworldXamarin.Droid.Resource.Id.search_edit_frame; + global::Xamarin.Forms.Platform.Android.Resource.Id.search_go_btn = global::HelloworldXamarin.Droid.Resource.Id.search_go_btn; + global::Xamarin.Forms.Platform.Android.Resource.Id.search_mag_icon = global::HelloworldXamarin.Droid.Resource.Id.search_mag_icon; + global::Xamarin.Forms.Platform.Android.Resource.Id.search_plate = global::HelloworldXamarin.Droid.Resource.Id.search_plate; + global::Xamarin.Forms.Platform.Android.Resource.Id.search_src_text = global::HelloworldXamarin.Droid.Resource.Id.search_src_text; + global::Xamarin.Forms.Platform.Android.Resource.Id.search_voice_btn = global::HelloworldXamarin.Droid.Resource.Id.search_voice_btn; + global::Xamarin.Forms.Platform.Android.Resource.Id.selected = global::HelloworldXamarin.Droid.Resource.Id.selected; + global::Xamarin.Forms.Platform.Android.Resource.Id.select_dialog_listview = global::HelloworldXamarin.Droid.Resource.Id.select_dialog_listview; + global::Xamarin.Forms.Platform.Android.Resource.Id.shellcontent_appbar = global::HelloworldXamarin.Droid.Resource.Id.shellcontent_appbar; + global::Xamarin.Forms.Platform.Android.Resource.Id.shellcontent_toolbar = global::HelloworldXamarin.Droid.Resource.Id.shellcontent_toolbar; + global::Xamarin.Forms.Platform.Android.Resource.Id.SHIFT = global::HelloworldXamarin.Droid.Resource.Id.SHIFT; + global::Xamarin.Forms.Platform.Android.Resource.Id.shortcut = global::HelloworldXamarin.Droid.Resource.Id.shortcut; + global::Xamarin.Forms.Platform.Android.Resource.Id.showCustom = global::HelloworldXamarin.Droid.Resource.Id.showCustom; + global::Xamarin.Forms.Platform.Android.Resource.Id.showHome = global::HelloworldXamarin.Droid.Resource.Id.showHome; + global::Xamarin.Forms.Platform.Android.Resource.Id.showTitle = global::HelloworldXamarin.Droid.Resource.Id.showTitle; + global::Xamarin.Forms.Platform.Android.Resource.Id.smallLabel = global::HelloworldXamarin.Droid.Resource.Id.smallLabel; + global::Xamarin.Forms.Platform.Android.Resource.Id.snackbar_action = global::HelloworldXamarin.Droid.Resource.Id.snackbar_action; + global::Xamarin.Forms.Platform.Android.Resource.Id.snackbar_text = global::HelloworldXamarin.Droid.Resource.Id.snackbar_text; + global::Xamarin.Forms.Platform.Android.Resource.Id.snap = global::HelloworldXamarin.Droid.Resource.Id.snap; + global::Xamarin.Forms.Platform.Android.Resource.Id.snapMargins = global::HelloworldXamarin.Droid.Resource.Id.snapMargins; + global::Xamarin.Forms.Platform.Android.Resource.Id.spacer = global::HelloworldXamarin.Droid.Resource.Id.spacer; + global::Xamarin.Forms.Platform.Android.Resource.Id.split_action_bar = global::HelloworldXamarin.Droid.Resource.Id.split_action_bar; + global::Xamarin.Forms.Platform.Android.Resource.Id.src_atop = global::HelloworldXamarin.Droid.Resource.Id.src_atop; + global::Xamarin.Forms.Platform.Android.Resource.Id.src_in = global::HelloworldXamarin.Droid.Resource.Id.src_in; + global::Xamarin.Forms.Platform.Android.Resource.Id.src_over = global::HelloworldXamarin.Droid.Resource.Id.src_over; + global::Xamarin.Forms.Platform.Android.Resource.Id.start = global::HelloworldXamarin.Droid.Resource.Id.start; + global::Xamarin.Forms.Platform.Android.Resource.Id.status_bar_latest_event_content = global::HelloworldXamarin.Droid.Resource.Id.status_bar_latest_event_content; + global::Xamarin.Forms.Platform.Android.Resource.Id.stretch = global::HelloworldXamarin.Droid.Resource.Id.stretch; + global::Xamarin.Forms.Platform.Android.Resource.Id.submenuarrow = global::HelloworldXamarin.Droid.Resource.Id.submenuarrow; + global::Xamarin.Forms.Platform.Android.Resource.Id.submit_area = global::HelloworldXamarin.Droid.Resource.Id.submit_area; + global::Xamarin.Forms.Platform.Android.Resource.Id.SYM = global::HelloworldXamarin.Droid.Resource.Id.SYM; + global::Xamarin.Forms.Platform.Android.Resource.Id.tabMode = global::HelloworldXamarin.Droid.Resource.Id.tabMode; + global::Xamarin.Forms.Platform.Android.Resource.Id.tag_transition_group = global::HelloworldXamarin.Droid.Resource.Id.tag_transition_group; + global::Xamarin.Forms.Platform.Android.Resource.Id.tag_unhandled_key_event_manager = global::HelloworldXamarin.Droid.Resource.Id.tag_unhandled_key_event_manager; + global::Xamarin.Forms.Platform.Android.Resource.Id.tag_unhandled_key_listeners = global::HelloworldXamarin.Droid.Resource.Id.tag_unhandled_key_listeners; + global::Xamarin.Forms.Platform.Android.Resource.Id.text = global::HelloworldXamarin.Droid.Resource.Id.text; + global::Xamarin.Forms.Platform.Android.Resource.Id.text2 = global::HelloworldXamarin.Droid.Resource.Id.text2; + global::Xamarin.Forms.Platform.Android.Resource.Id.textinput_counter = global::HelloworldXamarin.Droid.Resource.Id.textinput_counter; + global::Xamarin.Forms.Platform.Android.Resource.Id.textinput_error = global::HelloworldXamarin.Droid.Resource.Id.textinput_error; + global::Xamarin.Forms.Platform.Android.Resource.Id.textinput_helper_text = global::HelloworldXamarin.Droid.Resource.Id.textinput_helper_text; + global::Xamarin.Forms.Platform.Android.Resource.Id.textSpacerNoButtons = global::HelloworldXamarin.Droid.Resource.Id.textSpacerNoButtons; + global::Xamarin.Forms.Platform.Android.Resource.Id.textSpacerNoTitle = global::HelloworldXamarin.Droid.Resource.Id.textSpacerNoTitle; + global::Xamarin.Forms.Platform.Android.Resource.Id.textStart = global::HelloworldXamarin.Droid.Resource.Id.textStart; + global::Xamarin.Forms.Platform.Android.Resource.Id.text_input_password_toggle = global::HelloworldXamarin.Droid.Resource.Id.text_input_password_toggle; + global::Xamarin.Forms.Platform.Android.Resource.Id.time = global::HelloworldXamarin.Droid.Resource.Id.time; + global::Xamarin.Forms.Platform.Android.Resource.Id.title = global::HelloworldXamarin.Droid.Resource.Id.title; + global::Xamarin.Forms.Platform.Android.Resource.Id.titleDividerNoCustom = global::HelloworldXamarin.Droid.Resource.Id.titleDividerNoCustom; + global::Xamarin.Forms.Platform.Android.Resource.Id.title_template = global::HelloworldXamarin.Droid.Resource.Id.title_template; + global::Xamarin.Forms.Platform.Android.Resource.Id.top = global::HelloworldXamarin.Droid.Resource.Id.top; + global::Xamarin.Forms.Platform.Android.Resource.Id.topPanel = global::HelloworldXamarin.Droid.Resource.Id.topPanel; + global::Xamarin.Forms.Platform.Android.Resource.Id.touch_outside = global::HelloworldXamarin.Droid.Resource.Id.touch_outside; + global::Xamarin.Forms.Platform.Android.Resource.Id.transition_current_scene = global::HelloworldXamarin.Droid.Resource.Id.transition_current_scene; + global::Xamarin.Forms.Platform.Android.Resource.Id.transition_layout_save = global::HelloworldXamarin.Droid.Resource.Id.transition_layout_save; + global::Xamarin.Forms.Platform.Android.Resource.Id.transition_position = global::HelloworldXamarin.Droid.Resource.Id.transition_position; + global::Xamarin.Forms.Platform.Android.Resource.Id.transition_scene_layoutid_cache = global::HelloworldXamarin.Droid.Resource.Id.transition_scene_layoutid_cache; + global::Xamarin.Forms.Platform.Android.Resource.Id.transition_transform = global::HelloworldXamarin.Droid.Resource.Id.transition_transform; + global::Xamarin.Forms.Platform.Android.Resource.Id.uniform = global::HelloworldXamarin.Droid.Resource.Id.uniform; + global::Xamarin.Forms.Platform.Android.Resource.Id.unlabeled = global::HelloworldXamarin.Droid.Resource.Id.unlabeled; + global::Xamarin.Forms.Platform.Android.Resource.Id.up = global::HelloworldXamarin.Droid.Resource.Id.up; + global::Xamarin.Forms.Platform.Android.Resource.Id.useLogo = global::HelloworldXamarin.Droid.Resource.Id.useLogo; + global::Xamarin.Forms.Platform.Android.Resource.Id.view_offset_helper = global::HelloworldXamarin.Droid.Resource.Id.view_offset_helper; + global::Xamarin.Forms.Platform.Android.Resource.Id.visible = global::HelloworldXamarin.Droid.Resource.Id.visible; + global::Xamarin.Forms.Platform.Android.Resource.Id.withText = global::HelloworldXamarin.Droid.Resource.Id.withText; + global::Xamarin.Forms.Platform.Android.Resource.Id.wrap_content = global::HelloworldXamarin.Droid.Resource.Id.wrap_content; + global::Xamarin.Forms.Platform.Android.Resource.Integer.abc_config_activityDefaultDur = global::HelloworldXamarin.Droid.Resource.Integer.abc_config_activityDefaultDur; + global::Xamarin.Forms.Platform.Android.Resource.Integer.abc_config_activityShortDur = global::HelloworldXamarin.Droid.Resource.Integer.abc_config_activityShortDur; + global::Xamarin.Forms.Platform.Android.Resource.Integer.app_bar_elevation_anim_duration = global::HelloworldXamarin.Droid.Resource.Integer.app_bar_elevation_anim_duration; + global::Xamarin.Forms.Platform.Android.Resource.Integer.bottom_sheet_slide_duration = global::HelloworldXamarin.Droid.Resource.Integer.bottom_sheet_slide_duration; + global::Xamarin.Forms.Platform.Android.Resource.Integer.cancel_button_image_alpha = global::HelloworldXamarin.Droid.Resource.Integer.cancel_button_image_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Integer.config_tooltipAnimTime = global::HelloworldXamarin.Droid.Resource.Integer.config_tooltipAnimTime; + global::Xamarin.Forms.Platform.Android.Resource.Integer.design_snackbar_text_max_lines = global::HelloworldXamarin.Droid.Resource.Integer.design_snackbar_text_max_lines; + global::Xamarin.Forms.Platform.Android.Resource.Integer.design_tab_indicator_anim_duration_ms = global::HelloworldXamarin.Droid.Resource.Integer.design_tab_indicator_anim_duration_ms; + global::Xamarin.Forms.Platform.Android.Resource.Integer.hide_password_duration = global::HelloworldXamarin.Droid.Resource.Integer.hide_password_duration; + global::Xamarin.Forms.Platform.Android.Resource.Integer.mtrl_btn_anim_delay_ms = global::HelloworldXamarin.Droid.Resource.Integer.mtrl_btn_anim_delay_ms; + global::Xamarin.Forms.Platform.Android.Resource.Integer.mtrl_btn_anim_duration_ms = global::HelloworldXamarin.Droid.Resource.Integer.mtrl_btn_anim_duration_ms; + global::Xamarin.Forms.Platform.Android.Resource.Integer.mtrl_chip_anim_duration = global::HelloworldXamarin.Droid.Resource.Integer.mtrl_chip_anim_duration; + global::Xamarin.Forms.Platform.Android.Resource.Integer.mtrl_tab_indicator_anim_duration_ms = global::HelloworldXamarin.Droid.Resource.Integer.mtrl_tab_indicator_anim_duration_ms; + global::Xamarin.Forms.Platform.Android.Resource.Integer.show_password_duration = global::HelloworldXamarin.Droid.Resource.Integer.show_password_duration; + global::Xamarin.Forms.Platform.Android.Resource.Integer.status_bar_notification_info_maxnum = global::HelloworldXamarin.Droid.Resource.Integer.status_bar_notification_info_maxnum; + global::Xamarin.Forms.Platform.Android.Resource.Interpolator.mtrl_fast_out_linear_in = global::HelloworldXamarin.Droid.Resource.Interpolator.mtrl_fast_out_linear_in; + global::Xamarin.Forms.Platform.Android.Resource.Interpolator.mtrl_fast_out_slow_in = global::HelloworldXamarin.Droid.Resource.Interpolator.mtrl_fast_out_slow_in; + global::Xamarin.Forms.Platform.Android.Resource.Interpolator.mtrl_linear = global::HelloworldXamarin.Droid.Resource.Interpolator.mtrl_linear; + global::Xamarin.Forms.Platform.Android.Resource.Interpolator.mtrl_linear_out_slow_in = global::HelloworldXamarin.Droid.Resource.Interpolator.mtrl_linear_out_slow_in; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_action_bar_title_item = global::HelloworldXamarin.Droid.Resource.Layout.abc_action_bar_title_item; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_action_bar_up_container = global::HelloworldXamarin.Droid.Resource.Layout.abc_action_bar_up_container; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_action_menu_item_layout = global::HelloworldXamarin.Droid.Resource.Layout.abc_action_menu_item_layout; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_action_menu_layout = global::HelloworldXamarin.Droid.Resource.Layout.abc_action_menu_layout; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_action_mode_bar = global::HelloworldXamarin.Droid.Resource.Layout.abc_action_mode_bar; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_action_mode_close_item_material = global::HelloworldXamarin.Droid.Resource.Layout.abc_action_mode_close_item_material; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_activity_chooser_view = global::HelloworldXamarin.Droid.Resource.Layout.abc_activity_chooser_view; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_activity_chooser_view_list_item = global::HelloworldXamarin.Droid.Resource.Layout.abc_activity_chooser_view_list_item; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_alert_dialog_button_bar_material = global::HelloworldXamarin.Droid.Resource.Layout.abc_alert_dialog_button_bar_material; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_alert_dialog_material = global::HelloworldXamarin.Droid.Resource.Layout.abc_alert_dialog_material; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_alert_dialog_title_material = global::HelloworldXamarin.Droid.Resource.Layout.abc_alert_dialog_title_material; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_cascading_menu_item_layout = global::HelloworldXamarin.Droid.Resource.Layout.abc_cascading_menu_item_layout; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_dialog_title_material = global::HelloworldXamarin.Droid.Resource.Layout.abc_dialog_title_material; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_expanded_menu_layout = global::HelloworldXamarin.Droid.Resource.Layout.abc_expanded_menu_layout; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_list_menu_item_checkbox = global::HelloworldXamarin.Droid.Resource.Layout.abc_list_menu_item_checkbox; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_list_menu_item_icon = global::HelloworldXamarin.Droid.Resource.Layout.abc_list_menu_item_icon; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_list_menu_item_layout = global::HelloworldXamarin.Droid.Resource.Layout.abc_list_menu_item_layout; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_list_menu_item_radio = global::HelloworldXamarin.Droid.Resource.Layout.abc_list_menu_item_radio; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_popup_menu_header_item_layout = global::HelloworldXamarin.Droid.Resource.Layout.abc_popup_menu_header_item_layout; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_popup_menu_item_layout = global::HelloworldXamarin.Droid.Resource.Layout.abc_popup_menu_item_layout; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_screen_content_include = global::HelloworldXamarin.Droid.Resource.Layout.abc_screen_content_include; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_screen_simple = global::HelloworldXamarin.Droid.Resource.Layout.abc_screen_simple; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_screen_simple_overlay_action_mode = global::HelloworldXamarin.Droid.Resource.Layout.abc_screen_simple_overlay_action_mode; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_screen_toolbar = global::HelloworldXamarin.Droid.Resource.Layout.abc_screen_toolbar; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_search_dropdown_item_icons_2line = global::HelloworldXamarin.Droid.Resource.Layout.abc_search_dropdown_item_icons_2line; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_search_view = global::HelloworldXamarin.Droid.Resource.Layout.abc_search_view; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_select_dialog_material = global::HelloworldXamarin.Droid.Resource.Layout.abc_select_dialog_material; + global::Xamarin.Forms.Platform.Android.Resource.Layout.abc_tooltip = global::HelloworldXamarin.Droid.Resource.Layout.abc_tooltip; + global::Xamarin.Forms.Platform.Android.Resource.Layout.BottomTabLayout = global::HelloworldXamarin.Droid.Resource.Layout.BottomTabLayout; + global::Xamarin.Forms.Platform.Android.Resource.Layout.design_bottom_navigation_item = global::HelloworldXamarin.Droid.Resource.Layout.design_bottom_navigation_item; + global::Xamarin.Forms.Platform.Android.Resource.Layout.design_bottom_sheet_dialog = global::HelloworldXamarin.Droid.Resource.Layout.design_bottom_sheet_dialog; + global::Xamarin.Forms.Platform.Android.Resource.Layout.design_layout_snackbar = global::HelloworldXamarin.Droid.Resource.Layout.design_layout_snackbar; + global::Xamarin.Forms.Platform.Android.Resource.Layout.design_layout_snackbar_include = global::HelloworldXamarin.Droid.Resource.Layout.design_layout_snackbar_include; + global::Xamarin.Forms.Platform.Android.Resource.Layout.design_layout_tab_icon = global::HelloworldXamarin.Droid.Resource.Layout.design_layout_tab_icon; + global::Xamarin.Forms.Platform.Android.Resource.Layout.design_layout_tab_text = global::HelloworldXamarin.Droid.Resource.Layout.design_layout_tab_text; + global::Xamarin.Forms.Platform.Android.Resource.Layout.design_menu_item_action_area = global::HelloworldXamarin.Droid.Resource.Layout.design_menu_item_action_area; + global::Xamarin.Forms.Platform.Android.Resource.Layout.design_navigation_item = global::HelloworldXamarin.Droid.Resource.Layout.design_navigation_item; + global::Xamarin.Forms.Platform.Android.Resource.Layout.design_navigation_item_header = global::HelloworldXamarin.Droid.Resource.Layout.design_navigation_item_header; + global::Xamarin.Forms.Platform.Android.Resource.Layout.design_navigation_item_separator = global::HelloworldXamarin.Droid.Resource.Layout.design_navigation_item_separator; + global::Xamarin.Forms.Platform.Android.Resource.Layout.design_navigation_item_subheader = global::HelloworldXamarin.Droid.Resource.Layout.design_navigation_item_subheader; + global::Xamarin.Forms.Platform.Android.Resource.Layout.design_navigation_menu = global::HelloworldXamarin.Droid.Resource.Layout.design_navigation_menu; + global::Xamarin.Forms.Platform.Android.Resource.Layout.design_navigation_menu_item = global::HelloworldXamarin.Droid.Resource.Layout.design_navigation_menu_item; + global::Xamarin.Forms.Platform.Android.Resource.Layout.design_text_input_password_icon = global::HelloworldXamarin.Droid.Resource.Layout.design_text_input_password_icon; + global::Xamarin.Forms.Platform.Android.Resource.Layout.FlyoutContent = global::HelloworldXamarin.Droid.Resource.Layout.FlyoutContent; + global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_layout_snackbar = global::HelloworldXamarin.Droid.Resource.Layout.mtrl_layout_snackbar; + global::Xamarin.Forms.Platform.Android.Resource.Layout.mtrl_layout_snackbar_include = global::HelloworldXamarin.Droid.Resource.Layout.mtrl_layout_snackbar_include; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_action = global::HelloworldXamarin.Droid.Resource.Layout.notification_action; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_action_tombstone = global::HelloworldXamarin.Droid.Resource.Layout.notification_action_tombstone; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_media_action = global::HelloworldXamarin.Droid.Resource.Layout.notification_media_action; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_media_cancel_action = global::HelloworldXamarin.Droid.Resource.Layout.notification_media_cancel_action; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_big_media = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_big_media; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_big_media_custom = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_big_media_custom; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_big_media_narrow = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_big_media_narrow; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_big_media_narrow_custom = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_big_media_narrow_custom; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_custom_big = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_custom_big; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_icon_group = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_icon_group; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_lines_media = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_lines_media; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_media = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_media; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_media_custom = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_media_custom; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_part_chronometer = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_part_chronometer; + global::Xamarin.Forms.Platform.Android.Resource.Layout.notification_template_part_time = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_part_time; + global::Xamarin.Forms.Platform.Android.Resource.Layout.RootLayout = global::HelloworldXamarin.Droid.Resource.Layout.RootLayout; + global::Xamarin.Forms.Platform.Android.Resource.Layout.select_dialog_item_material = global::HelloworldXamarin.Droid.Resource.Layout.select_dialog_item_material; + global::Xamarin.Forms.Platform.Android.Resource.Layout.select_dialog_multichoice_material = global::HelloworldXamarin.Droid.Resource.Layout.select_dialog_multichoice_material; + global::Xamarin.Forms.Platform.Android.Resource.Layout.select_dialog_singlechoice_material = global::HelloworldXamarin.Droid.Resource.Layout.select_dialog_singlechoice_material; + global::Xamarin.Forms.Platform.Android.Resource.Layout.ShellContent = global::HelloworldXamarin.Droid.Resource.Layout.ShellContent; + global::Xamarin.Forms.Platform.Android.Resource.Layout.support_simple_spinner_dropdown_item = global::HelloworldXamarin.Droid.Resource.Layout.support_simple_spinner_dropdown_item; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_action_bar_home_description = global::HelloworldXamarin.Droid.Resource.String.abc_action_bar_home_description; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_action_bar_up_description = global::HelloworldXamarin.Droid.Resource.String.abc_action_bar_up_description; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_action_menu_overflow_description = global::HelloworldXamarin.Droid.Resource.String.abc_action_menu_overflow_description; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_action_mode_done = global::HelloworldXamarin.Droid.Resource.String.abc_action_mode_done; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_activitychooserview_choose_application = global::HelloworldXamarin.Droid.Resource.String.abc_activitychooserview_choose_application; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_activity_chooser_view_see_all = global::HelloworldXamarin.Droid.Resource.String.abc_activity_chooser_view_see_all; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_capital_off = global::HelloworldXamarin.Droid.Resource.String.abc_capital_off; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_capital_on = global::HelloworldXamarin.Droid.Resource.String.abc_capital_on; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_font_family_body_1_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_body_1_material; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_font_family_body_2_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_body_2_material; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_font_family_button_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_button_material; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_font_family_caption_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_caption_material; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_font_family_display_1_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_display_1_material; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_font_family_display_2_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_display_2_material; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_font_family_display_3_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_display_3_material; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_font_family_display_4_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_display_4_material; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_font_family_headline_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_headline_material; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_font_family_menu_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_menu_material; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_font_family_subhead_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_subhead_material; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_font_family_title_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_title_material; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_alt_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_alt_shortcut_label; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_ctrl_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_ctrl_shortcut_label; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_delete_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_delete_shortcut_label; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_enter_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_enter_shortcut_label; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_function_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_function_shortcut_label; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_meta_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_meta_shortcut_label; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_shift_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_shift_shortcut_label; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_space_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_space_shortcut_label; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_menu_sym_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_sym_shortcut_label; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_prepend_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_prepend_shortcut_label; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_searchview_description_clear = global::HelloworldXamarin.Droid.Resource.String.abc_searchview_description_clear; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_searchview_description_query = global::HelloworldXamarin.Droid.Resource.String.abc_searchview_description_query; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_searchview_description_search = global::HelloworldXamarin.Droid.Resource.String.abc_searchview_description_search; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_searchview_description_submit = global::HelloworldXamarin.Droid.Resource.String.abc_searchview_description_submit; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_searchview_description_voice = global::HelloworldXamarin.Droid.Resource.String.abc_searchview_description_voice; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_search_hint = global::HelloworldXamarin.Droid.Resource.String.abc_search_hint; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_shareactionprovider_share_with = global::HelloworldXamarin.Droid.Resource.String.abc_shareactionprovider_share_with; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_shareactionprovider_share_with_application = global::HelloworldXamarin.Droid.Resource.String.abc_shareactionprovider_share_with_application; + global::Xamarin.Forms.Platform.Android.Resource.String.abc_toolbar_collapse_description = global::HelloworldXamarin.Droid.Resource.String.abc_toolbar_collapse_description; + global::Xamarin.Forms.Platform.Android.Resource.String.appbar_scrolling_view_behavior = global::HelloworldXamarin.Droid.Resource.String.appbar_scrolling_view_behavior; + global::Xamarin.Forms.Platform.Android.Resource.String.bottom_sheet_behavior = global::HelloworldXamarin.Droid.Resource.String.bottom_sheet_behavior; + global::Xamarin.Forms.Platform.Android.Resource.String.character_counter_content_description = global::HelloworldXamarin.Droid.Resource.String.character_counter_content_description; + global::Xamarin.Forms.Platform.Android.Resource.String.character_counter_pattern = global::HelloworldXamarin.Droid.Resource.String.character_counter_pattern; + global::Xamarin.Forms.Platform.Android.Resource.String.fab_transformation_scrim_behavior = global::HelloworldXamarin.Droid.Resource.String.fab_transformation_scrim_behavior; + global::Xamarin.Forms.Platform.Android.Resource.String.fab_transformation_sheet_behavior = global::HelloworldXamarin.Droid.Resource.String.fab_transformation_sheet_behavior; + global::Xamarin.Forms.Platform.Android.Resource.String.hide_bottom_view_on_scroll_behavior = global::HelloworldXamarin.Droid.Resource.String.hide_bottom_view_on_scroll_behavior; + global::Xamarin.Forms.Platform.Android.Resource.String.mtrl_chip_close_icon_content_description = global::HelloworldXamarin.Droid.Resource.String.mtrl_chip_close_icon_content_description; + global::Xamarin.Forms.Platform.Android.Resource.String.password_toggle_content_description = global::HelloworldXamarin.Droid.Resource.String.password_toggle_content_description; + global::Xamarin.Forms.Platform.Android.Resource.String.path_password_eye = global::HelloworldXamarin.Droid.Resource.String.path_password_eye; + global::Xamarin.Forms.Platform.Android.Resource.String.path_password_eye_mask_strike_through = global::HelloworldXamarin.Droid.Resource.String.path_password_eye_mask_strike_through; + global::Xamarin.Forms.Platform.Android.Resource.String.path_password_eye_mask_visible = global::HelloworldXamarin.Droid.Resource.String.path_password_eye_mask_visible; + global::Xamarin.Forms.Platform.Android.Resource.String.path_password_strike_through = global::HelloworldXamarin.Droid.Resource.String.path_password_strike_through; + global::Xamarin.Forms.Platform.Android.Resource.String.search_menu_title = global::HelloworldXamarin.Droid.Resource.String.search_menu_title; + global::Xamarin.Forms.Platform.Android.Resource.String.status_bar_notification_info_overflow = global::HelloworldXamarin.Droid.Resource.String.status_bar_notification_info_overflow; + global::Xamarin.Forms.Platform.Android.Resource.Style.AlertDialog_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.AlertDialog_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.AlertDialog_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.AlertDialog_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Animation_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Animation_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Animation_AppCompat_DropDownUp = global::HelloworldXamarin.Droid.Resource.Style.Animation_AppCompat_DropDownUp; + global::Xamarin.Forms.Platform.Android.Resource.Style.Animation_AppCompat_Tooltip = global::HelloworldXamarin.Droid.Resource.Style.Animation_AppCompat_Tooltip; + global::Xamarin.Forms.Platform.Android.Resource.Style.Animation_Design_BottomSheetDialog = global::HelloworldXamarin.Droid.Resource.Style.Animation_Design_BottomSheetDialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.AppCompatDialogStyle = global::HelloworldXamarin.Droid.Resource.Style.AppCompatDialogStyle; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_AlertDialog_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_AlertDialog_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_AlertDialog_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_AlertDialog_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Animation_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_Animation_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Animation_AppCompat_DropDownUp = global::HelloworldXamarin.Droid.Resource.Style.Base_Animation_AppCompat_DropDownUp; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Animation_AppCompat_Tooltip = global::HelloworldXamarin.Droid.Resource.Style.Base_Animation_AppCompat_Tooltip; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_CardView = global::HelloworldXamarin.Droid.Resource.Style.Base_CardView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_DialogWindowTitleBackground_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_DialogWindowTitleBackground_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_DialogWindowTitle_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_DialogWindowTitle_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Body1 = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Body1; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Body2 = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Body2; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Button = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Button; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Caption = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Caption; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Display1 = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display1; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Display2 = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display2; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Display3 = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display3; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Display4 = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display4; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Headline = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Headline; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Large = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Large; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Large_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Large_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Large; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Small; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Medium = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Medium; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Medium_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Medium_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Menu = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Menu; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_SearchResult = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_SearchResult; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Subtitle; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Title = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Title; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Small = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Small; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Small_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Small_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Subhead = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Subhead; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Subhead_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Subhead_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Title = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Title; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Title_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Title_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Tooltip = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Tooltip; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Menu = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Menu; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Subtitle; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Title = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Title; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Borderless_Colored = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Borderless_Colored; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Colored = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Colored; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_DropDownItem = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_DropDownItem; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Header = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Header; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Large = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Large; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Small = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Small; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_Switch = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Switch; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_AppCompat_Widget_TextView_SpinnerItem = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_TextView_SpinnerItem; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_Widget_AppCompat_ExpandedMenu_Item = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_Widget_AppCompat_ExpandedMenu_Item; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Subtitle; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Title = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Title; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_AppCompat_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_AppCompat_Dark = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dark; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_AppCompat_Dark_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dark_ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog_Alert; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog_Alert; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_CompactMenu = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_CompactMenu; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_DialogWhenLarge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Dialog_Alert; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Dialog_FixedSize = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Dialog_FixedSize; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Light_DarkActionBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Light_DarkActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Light_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Light_DialogWhenLarge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Light_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog_Alert; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Light_Dialog_FixedSize = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog_FixedSize; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_AppCompat_Light_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Bridge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_CompactMenu = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_CompactMenu; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_DialogWhenLarge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog_Alert; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Dialog_FixedSize = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog_FixedSize; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Bridge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar_Bridge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_DialogWhenLarge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_Alert; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_FixedSize = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_FixedSize; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog_Alert; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_Theme_MaterialComponents; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Bridge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Bridge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents_Light_DarkActionBar_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light_DarkActionBar_Bridge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V21_ThemeOverlay_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V21_ThemeOverlay_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V21_Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_V21_Theme_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V21_Theme_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V21_Theme_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V21_Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_V21_Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V21_Theme_AppCompat_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V21_Theme_AppCompat_Light_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V22_Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_V22_Theme_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V22_Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_V22_Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V23_Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_V23_Theme_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V23_Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_V23_Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V26_Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_V26_Theme_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V26_Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_V26_Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V26_Widget_AppCompat_Toolbar = global::HelloworldXamarin.Droid.Resource.Style.Base_V26_Widget_AppCompat_Toolbar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V28_Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_V28_Theme_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V28_Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_V28_Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_ThemeOverlay_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_ThemeOverlay_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_Theme_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_Theme_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_Theme_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_Theme_AppCompat_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_Theme_AppCompat_Light_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_Widget_AppCompat_AutoCompleteTextView = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_Widget_AppCompat_AutoCompleteTextView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_Widget_AppCompat_EditText = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_Widget_AppCompat_EditText; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_V7_Widget_AppCompat_Toolbar = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_Widget_AppCompat_Toolbar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionBar_Solid = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_Solid; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionBar_TabBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_TabBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionBar_TabText = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_TabText; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionBar_TabView = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_TabView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionButton = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionButton; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionButton_CloseMode = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionButton_CloseMode; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionButton_Overflow = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionButton_Overflow; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActionMode = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionMode; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ActivityChooserView = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActivityChooserView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_AutoCompleteTextView = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_AutoCompleteTextView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Button = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Button; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ButtonBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ButtonBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ButtonBar_AlertDialog = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ButtonBar_AlertDialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Button_Borderless = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Button_Borderless; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Button_Borderless_Colored = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Button_Borderless_Colored; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Button_ButtonBar_AlertDialog = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Button_ButtonBar_AlertDialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Button_Colored = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Button_Colored; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Button_Small = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Button_Small; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_CompoundButton_CheckBox = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_CompoundButton_CheckBox; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_CompoundButton_RadioButton = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_CompoundButton_RadioButton; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_CompoundButton_Switch = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_CompoundButton_Switch; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle_Common = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle_Common; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_DropDownItem_Spinner = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_DropDownItem_Spinner; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_EditText = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_EditText; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ImageButton = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ImageButton; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_Solid = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_Solid; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabView = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu_Overflow = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu_Overflow; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ListMenuView = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ListMenuView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ListPopupWindow = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ListPopupWindow; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ListView = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ListView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ListView_DropDown = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ListView_DropDown; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ListView_Menu = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ListView_Menu; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_PopupMenu = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_PopupMenu; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_PopupMenu_Overflow = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_PopupMenu_Overflow; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_PopupWindow = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_PopupWindow; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ProgressBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ProgressBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_ProgressBar_Horizontal = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ProgressBar_Horizontal; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_RatingBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_RatingBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_RatingBar_Indicator = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_RatingBar_Indicator; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_RatingBar_Small = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_RatingBar_Small; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_SearchView = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_SearchView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_SearchView_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_SearchView_ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_SeekBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_SeekBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_SeekBar_Discrete = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_SeekBar_Discrete; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Spinner = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Spinner; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Spinner_Underlined = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Spinner_Underlined; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_TextView_SpinnerItem = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_TextView_SpinnerItem; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Toolbar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Toolbar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_AppCompat_Toolbar_Button_Navigation = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Toolbar_Button_Navigation; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_Design_TabLayout = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_Design_TabLayout; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_MaterialComponents_Chip = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_MaterialComponents_Chip; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_MaterialComponents_TextInputEditText = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_MaterialComponents_TextInputEditText; + global::Xamarin.Forms.Platform.Android.Resource.Style.Base_Widget_MaterialComponents_TextInputLayout = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_MaterialComponents_TextInputLayout; + global::Xamarin.Forms.Platform.Android.Resource.Style.CardView = global::HelloworldXamarin.Droid.Resource.Style.CardView; + global::Xamarin.Forms.Platform.Android.Resource.Style.CardView_Dark = global::HelloworldXamarin.Droid.Resource.Style.CardView_Dark; + global::Xamarin.Forms.Platform.Android.Resource.Style.CardView_Light = global::HelloworldXamarin.Droid.Resource.Style.CardView_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.collectionViewStyle = global::HelloworldXamarin.Droid.Resource.Style.collectionViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Style.MainTheme = global::HelloworldXamarin.Droid.Resource.Style.MainTheme; + global::Xamarin.Forms.Platform.Android.Resource.Style.MainTheme_Base = global::HelloworldXamarin.Droid.Resource.Style.MainTheme_Base; + global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Platform_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Platform_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_MaterialComponents = global::HelloworldXamarin.Droid.Resource.Style.Platform_MaterialComponents; + global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_MaterialComponents_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Platform_MaterialComponents_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_MaterialComponents_Light = global::HelloworldXamarin.Droid.Resource.Style.Platform_MaterialComponents_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_MaterialComponents_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Platform_MaterialComponents_Light_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_ThemeOverlay_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Platform_ThemeOverlay_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_ThemeOverlay_AppCompat_Dark = global::HelloworldXamarin.Droid.Resource.Style.Platform_ThemeOverlay_AppCompat_Dark; + global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_ThemeOverlay_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Platform_ThemeOverlay_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_V21_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Platform_V21_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_V21_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Platform_V21_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_V25_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Platform_V25_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_V25_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Platform_V25_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Platform_Widget_AppCompat_Spinner = global::HelloworldXamarin.Droid.Resource.Style.Platform_Widget_AppCompat_Spinner; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_DialogWindowTitle_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_DialogWindowTitle_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_ActionBar_TitleItem = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_ActionBar_TitleItem; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_DialogTitle_Icon = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_DialogTitle_Icon; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_InternalGroup = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_InternalGroup; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Shortcut = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Shortcut; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_SubmenuArrow = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_SubmenuArrow; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Text = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Text; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Title = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Title; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_SearchView_MagIcon = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_SearchView_MagIcon; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon1 = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon1; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon2 = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon2; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Query = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Query; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton = global::HelloworldXamarin.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton; + global::Xamarin.Forms.Platform.Android.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow = global::HelloworldXamarin.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Body1 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Body1; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Body2 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Body2; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Button = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Button; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Caption = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Caption; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Display1 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Display1; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Display2 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Display2; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Display3 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Display3; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Display4 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Display4; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Headline = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Headline; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Large = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Large; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Large_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Large_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Subtitle; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Title; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Large; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Small; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Medium = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Medium; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Medium_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Medium_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Menu = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Menu; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_SearchResult_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_SearchResult_Subtitle; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_SearchResult_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_SearchResult_Title; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Small = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Small; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Small_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Small_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Subhead = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Subhead; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Subhead_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Subhead_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Title; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Title_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Title_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Tooltip = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Tooltip; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Menu = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Menu; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_Button = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_Button_Borderless_Colored = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button_Borderless_Colored; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_Button_Colored = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button_Colored; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_Button_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_DropDownItem = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_DropDownItem; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Header = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Header; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Large = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Large; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Small = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Small; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_Switch = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Switch; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Widget_TextView_SpinnerItem = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_TextView_SpinnerItem; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Info = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Info; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Info_Media = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Info_Media; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Line2 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Line2; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Line2_Media = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Line2_Media; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Media = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Media; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Time = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Time; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Time_Media = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Time_Media; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Title; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Compat_Notification_Title_Media = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Title_Media; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_CollapsingToolbar_Expanded = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_CollapsingToolbar_Expanded; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Counter = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_Counter; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Counter_Overflow = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_Counter_Overflow; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Error = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_Error; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_HelperText = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_HelperText; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Hint = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_Hint; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Snackbar_Message = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_Snackbar_Message; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Design_Tab = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_Tab; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Body1 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Body1; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Body2 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Body2; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Button = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Button; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Caption = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Caption; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Chip = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Chip; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Headline1 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline1; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Headline2 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline2; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Headline3 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline3; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Headline4 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline4; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Headline5 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline5; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Headline6 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline6; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Overline = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Overline; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Subtitle1 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Subtitle1; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Subtitle2 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Subtitle2; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_MaterialComponents_Tab = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Tab; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Widget_AppCompat_ExpandedMenu_Item = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Widget_AppCompat_ExpandedMenu_Item; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Subtitle; + global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Title; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_AppCompat_ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat_Dark = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_AppCompat_Dark; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat_Dark_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_AppCompat_Dark_ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_AppCompat_Dialog_Alert; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Dark = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dark; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Dark_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dark_ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Dialog = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dialog_Alert; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_Light = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox_Dense = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox_Dense; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox; + global::Xamarin.Forms.Platform.Android.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox_Dense = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox_Dense; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_CompactMenu = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_CompactMenu; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DayNight = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DayNight; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DayNight_DarkActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DayNight_DarkActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DayNight_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DayNight_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DayNight_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DayNight_DialogWhenLarge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DayNight_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DayNight_Dialog_Alert; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DayNight_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DayNight_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DayNight_NoActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DayNight_NoActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DialogWhenLarge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Dialog_Alert; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Light_DarkActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Light_DarkActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Light_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Light_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Light_DialogWhenLarge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Light_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Light_Dialog_Alert; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Light_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Light_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_Light_NoActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Light_NoActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_AppCompat_NoActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_NoActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_Design = global::HelloworldXamarin.Droid.Resource.Style.Theme_Design; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_Design_BottomSheetDialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_Design_BottomSheetDialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_Design_Light = global::HelloworldXamarin.Droid.Resource.Style.Theme_Design_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_Design_Light_BottomSheetDialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_Design_Light_BottomSheetDialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_Design_Light_NoActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_Design_Light_NoActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_Design_NoActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_Design_NoActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_BottomSheetDialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_BottomSheetDialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Bridge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_CompactMenu = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_CompactMenu; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_DialogWhenLarge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Dialog_Alert; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_BottomSheetDialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_BottomSheetDialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_Bridge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar_Bridge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_DialogWhenLarge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_Alert; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_NoActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_NoActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_Light_NoActionBar_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_NoActionBar_Bridge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_NoActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_NoActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Theme_MaterialComponents_NoActionBar_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_NoActionBar_Bridge; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionBar_Solid = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionBar_Solid; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionBar_TabBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionBar_TabBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionBar_TabText = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionBar_TabText; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionBar_TabView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionBar_TabView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionButton; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionButton_CloseMode = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionButton_CloseMode; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionButton_Overflow = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionButton_Overflow; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActionMode = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionMode; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ActivityChooserView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActivityChooserView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_AutoCompleteTextView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_AutoCompleteTextView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Button = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Button; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ButtonBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ButtonBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ButtonBar_AlertDialog = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ButtonBar_AlertDialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Button_Borderless = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Button_Borderless; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Button_Borderless_Colored = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Button_Borderless_Colored; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Button_ButtonBar_AlertDialog = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Button_ButtonBar_AlertDialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Button_Colored = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Button_Colored; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Button_Small = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Button_Small; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_CompoundButton_CheckBox = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_CompoundButton_CheckBox; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_CompoundButton_RadioButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_CompoundButton_RadioButton; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_CompoundButton_Switch = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_CompoundButton_Switch; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_DrawerArrowToggle = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_DrawerArrowToggle; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_DropDownItem_Spinner = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_DropDownItem_Spinner; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_EditText = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_EditText; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ImageButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ImageButton; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionButton; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionButton_CloseMode = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionButton_CloseMode; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionButton_Overflow = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionButton_Overflow; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActionMode_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionMode_Inverse; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ActivityChooserView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActivityChooserView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_AutoCompleteTextView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_AutoCompleteTextView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_DropDownItem_Spinner = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_DropDownItem_Spinner; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ListPopupWindow = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ListPopupWindow; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_ListView_DropDown = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ListView_DropDown; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_PopupMenu = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_PopupMenu; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_PopupMenu_Overflow = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_PopupMenu_Overflow; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_SearchView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_SearchView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Light_Spinner_DropDown_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_Spinner_DropDown_ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ListMenuView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ListMenuView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ListPopupWindow = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ListPopupWindow; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ListView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ListView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ListView_DropDown = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ListView_DropDown; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ListView_Menu = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ListView_Menu; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_PopupMenu = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_PopupMenu; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_PopupMenu_Overflow = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_PopupMenu_Overflow; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_PopupWindow = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_PopupWindow; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ProgressBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ProgressBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_ProgressBar_Horizontal = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ProgressBar_Horizontal; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_RatingBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_RatingBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_RatingBar_Indicator = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_RatingBar_Indicator; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_RatingBar_Small = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_RatingBar_Small; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_SearchView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_SearchView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_SearchView_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_SearchView_ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_SeekBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_SeekBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_SeekBar_Discrete = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_SeekBar_Discrete; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Spinner = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Spinner; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Spinner_DropDown = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Spinner_DropDown; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Spinner_DropDown_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Spinner_DropDown_ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Spinner_Underlined = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Spinner_Underlined; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_TextView_SpinnerItem = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_TextView_SpinnerItem; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Toolbar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Toolbar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_AppCompat_Toolbar_Button_Navigation = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Toolbar_Button_Navigation; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Compat_NotificationActionContainer = global::HelloworldXamarin.Droid.Resource.Style.Widget_Compat_NotificationActionContainer; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Compat_NotificationActionText = global::HelloworldXamarin.Droid.Resource.Style.Widget_Compat_NotificationActionText; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_AppBarLayout = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_AppBarLayout; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_BottomNavigationView = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_BottomNavigationView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_BottomSheet_Modal = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_BottomSheet_Modal; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_CollapsingToolbar = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_CollapsingToolbar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_FloatingActionButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_FloatingActionButton; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_NavigationView = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_NavigationView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_ScrimInsetsFrameLayout = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_ScrimInsetsFrameLayout; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_Snackbar = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_Snackbar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_TabLayout = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_TabLayout; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Design_TextInputLayout = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_TextInputLayout; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_BottomAppBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_BottomAppBar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_BottomAppBar_Colored = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_BottomAppBar_Colored; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_BottomNavigationView = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_BottomNavigationView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_BottomNavigationView_Colored = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_BottomNavigationView_Colored; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_BottomSheet_Modal = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_BottomSheet_Modal; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_Icon = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_Icon; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton_Icon = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton_Icon; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_TextButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog_Icon = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog_Icon; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_TextButton_Icon = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Icon; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton_Icon = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton_Icon; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_CardView = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_CardView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_ChipGroup = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_ChipGroup; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Chip_Action = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Chip_Action; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Chip_Choice = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Chip_Choice; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Chip_Entry = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Chip_Entry; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Chip_Filter = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Chip_Filter; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_FloatingActionButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_FloatingActionButton; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_NavigationView = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_NavigationView; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Snackbar = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Snackbar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Snackbar_FullWidth = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Snackbar_FullWidth; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TabLayout = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TabLayout; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TabLayout_Colored = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TabLayout_Colored; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox_Dense = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox_Dense; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox_Dense = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox_Dense; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_Dense = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_Dense; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_MaterialComponents_Toolbar = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Toolbar; + global::Xamarin.Forms.Platform.Android.Resource.Style.Widget_Support_CoordinatorLayout = global::HelloworldXamarin.Droid.Resource.Style.Widget_Support_CoordinatorLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBarLayout = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBarLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBarLayout_android_layout_gravity = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBarLayout_android_layout_gravity; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_background = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_background; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_backgroundSplit = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_backgroundSplit; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_backgroundStacked = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_backgroundStacked; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_contentInsetEnd = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_contentInsetEnd; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_contentInsetEndWithActions = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_contentInsetEndWithActions; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_contentInsetLeft = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_contentInsetLeft; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_contentInsetRight = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_contentInsetRight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_contentInsetStart = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_contentInsetStart; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_contentInsetStartWithNavigation = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_contentInsetStartWithNavigation; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_customNavigationLayout = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_customNavigationLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_displayOptions = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_displayOptions; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_divider = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_divider; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_elevation = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_height = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_height; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_hideOnContentScroll = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_hideOnContentScroll; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_homeAsUpIndicator = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_homeAsUpIndicator; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_homeLayout = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_homeLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_icon = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_icon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_indeterminateProgressStyle = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_indeterminateProgressStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_itemPadding = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_itemPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_logo = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_logo; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_navigationMode = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_navigationMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_popupTheme = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_popupTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_progressBarPadding = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_progressBarPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_progressBarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_progressBarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_subtitle = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_subtitle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_subtitleTextStyle = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_subtitleTextStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_title = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_title; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionBar_titleTextStyle = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_titleTextStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMenuItemView = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMenuItemView; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMenuItemView_android_minWidth = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMenuItemView_android_minWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMenuView = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMenuView; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMode = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMode_background = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMode_background; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMode_backgroundSplit = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMode_backgroundSplit; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMode_closeItemLayout = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMode_closeItemLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMode_height = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMode_height; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMode_subtitleTextStyle = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMode_subtitleTextStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActionMode_titleTextStyle = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMode_titleTextStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActivityChooserView = global::HelloworldXamarin.Droid.Resource.Styleable.ActivityChooserView; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActivityChooserView_expandActivityOverflowButtonDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.ActivityChooserView_expandActivityOverflowButtonDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ActivityChooserView_initialActivityCount = global::HelloworldXamarin.Droid.Resource.Styleable.ActivityChooserView_initialActivityCount; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_android_layout = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_android_layout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_buttonIconDimen = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_buttonIconDimen; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_buttonPanelSideLayout = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_buttonPanelSideLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_listItemLayout = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_listItemLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_listLayout = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_listLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_multiChoiceItemLayout = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_multiChoiceItemLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_showTitle = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_showTitle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AlertDialog_singleChoiceItemLayout = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_singleChoiceItemLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableCompat = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableCompat; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableCompat_android_constantSize = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_constantSize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableCompat_android_dither = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_dither; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableCompat_android_enterFadeDuration = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_enterFadeDuration; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableCompat_android_exitFadeDuration = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_exitFadeDuration; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableCompat_android_variablePadding = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_variablePadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableCompat_android_visible = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_visible; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableItem = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableItem; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableItem_android_drawable = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableItem_android_drawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableItem_android_id = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableItem_android_id; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableTransition = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableTransition; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableTransition_android_drawable = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_drawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableTransition_android_fromId = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_fromId; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableTransition_android_reversible = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_reversible; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AnimatedStateListDrawableTransition_android_toId = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_toId; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayoutStates = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayoutStates; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayoutStates_state_collapsed = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayoutStates_state_collapsed; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayoutStates_state_collapsible = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayoutStates_state_collapsible; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayoutStates_state_liftable = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayoutStates_state_liftable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayoutStates_state_lifted = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayoutStates_state_lifted; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_android_background = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_android_background; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_android_keyboardNavigationCluster = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_android_keyboardNavigationCluster; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_android_touchscreenBlocksFocus = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_android_touchscreenBlocksFocus; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_elevation = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_expanded = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_expanded; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_Layout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_Layout_layout_scrollFlags = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_Layout_layout_scrollFlags; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_Layout_layout_scrollInterpolator = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_Layout_layout_scrollInterpolator; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppBarLayout_liftOnScroll = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_liftOnScroll; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatImageView = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatImageView; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatImageView_android_src = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatImageView_android_src; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatImageView_srcCompat = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatImageView_srcCompat; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatImageView_tint = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatImageView_tint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatImageView_tintMode = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatImageView_tintMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatSeekBar = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatSeekBar; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatSeekBar_android_thumb = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatSeekBar_android_thumb; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatSeekBar_tickMark = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatSeekBar_tickMark; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatSeekBar_tickMarkTint = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatSeekBar_tickMarkTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatSeekBar_tickMarkTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatSeekBar_tickMarkTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper_android_drawableBottom = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableBottom; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper_android_drawableEnd = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableEnd; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper_android_drawableLeft = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableLeft; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper_android_drawableRight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableRight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper_android_drawableStart = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableStart; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper_android_drawableTop = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableTop; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextHelper_android_textAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper_android_textAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_android_textAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_android_textAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_autoSizeMaxTextSize = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_autoSizeMaxTextSize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_autoSizeMinTextSize = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_autoSizeMinTextSize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_autoSizePresetSizes = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_autoSizePresetSizes; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_autoSizeStepGranularity = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_autoSizeStepGranularity; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_autoSizeTextType = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_autoSizeTextType; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_firstBaselineToTopHeight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_firstBaselineToTopHeight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_fontFamily = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_fontFamily; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_lastBaselineToBottomHeight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_lastBaselineToBottomHeight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_lineHeight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_lineHeight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTextView_textAllCaps = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_textAllCaps; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarDivider = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarDivider; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarItemBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarItemBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarPopupTheme = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarPopupTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarSize = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarSize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarSplitStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarSplitStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarTabBarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarTabBarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarTabStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarTabStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarTabTextStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarTabTextStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarTheme = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionBarWidgetTheme = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarWidgetTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionDropDownStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionDropDownStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionMenuTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionMenuTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionMenuTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionMenuTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeCloseButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeCloseButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeCloseDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeCloseDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeCopyDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeCopyDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeCutDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeCutDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeFindDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeFindDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModePasteDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModePasteDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModePopupWindowStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModePopupWindowStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeSelectAllDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeSelectAllDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeShareDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeShareDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeSplitBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeSplitBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionModeWebSearchDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeWebSearchDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionOverflowButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionOverflowButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_actionOverflowMenuStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionOverflowMenuStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_activityChooserViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_activityChooserViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_alertDialogButtonGroupStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_alertDialogButtonGroupStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_alertDialogCenterButtons = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_alertDialogCenterButtons; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_alertDialogStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_alertDialogStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_alertDialogTheme = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_alertDialogTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_android_windowAnimationStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_android_windowAnimationStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_android_windowIsFloating = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_android_windowIsFloating; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_autoCompleteTextViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_autoCompleteTextViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_borderlessButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_borderlessButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_buttonBarButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_buttonBarButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_buttonBarNegativeButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_buttonBarNegativeButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_buttonBarNeutralButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_buttonBarNeutralButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_buttonBarPositiveButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_buttonBarPositiveButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_buttonBarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_buttonBarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_buttonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_buttonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_buttonStyleSmall = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_buttonStyleSmall; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_checkboxStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_checkboxStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_checkedTextViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_checkedTextViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorAccent = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorAccent; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorBackgroundFloating = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorBackgroundFloating; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorButtonNormal = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorButtonNormal; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorControlActivated = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorControlActivated; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorControlHighlight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorControlHighlight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorControlNormal = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorControlNormal; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorError = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorError; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorPrimary = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorPrimary; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorPrimaryDark = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorPrimaryDark; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_colorSwitchThumbNormal = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorSwitchThumbNormal; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_controlBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_controlBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_dialogCornerRadius = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_dialogCornerRadius; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_dialogPreferredPadding = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_dialogPreferredPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_dialogTheme = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_dialogTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_dividerHorizontal = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_dividerHorizontal; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_dividerVertical = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_dividerVertical; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_dropdownListPreferredItemHeight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_dropdownListPreferredItemHeight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_dropDownListViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_dropDownListViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_editTextBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_editTextBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_editTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_editTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_editTextStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_editTextStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_homeAsUpIndicator = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_homeAsUpIndicator; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_imageButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_imageButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listChoiceBackgroundIndicator = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listChoiceBackgroundIndicator; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listDividerAlertDialog = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listDividerAlertDialog; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listMenuViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listMenuViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listPopupWindowStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listPopupWindowStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listPreferredItemHeight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemHeight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listPreferredItemHeightLarge = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemHeightLarge; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listPreferredItemHeightSmall = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemHeightSmall; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingLeft = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingLeft; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingRight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingRight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_panelBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_panelBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_panelMenuListTheme = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_panelMenuListTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_panelMenuListWidth = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_panelMenuListWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_popupMenuStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_popupMenuStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_popupWindowStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_popupWindowStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_radioButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_radioButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_ratingBarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_ratingBarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_ratingBarStyleIndicator = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_ratingBarStyleIndicator; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_ratingBarStyleSmall = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_ratingBarStyleSmall; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_searchViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_searchViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_seekBarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_seekBarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_selectableItemBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_selectableItemBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_selectableItemBackgroundBorderless = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_selectableItemBackgroundBorderless; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_spinnerDropDownItemStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_spinnerDropDownItemStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_spinnerStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_spinnerStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_switchStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_switchStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearanceLargePopupMenu = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearanceLargePopupMenu; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearanceListItem = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearanceListItem; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearanceListItemSecondary = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearanceListItemSecondary; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearanceListItemSmall = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearanceListItemSmall; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearancePopupMenuHeader = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearancePopupMenuHeader; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultSubtitle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultSubtitle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultTitle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultTitle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textAppearanceSmallPopupMenu = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearanceSmallPopupMenu; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textColorAlertDialogListItem = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textColorAlertDialogListItem; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_textColorSearchUrl = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textColorSearchUrl; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_toolbarNavigationButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_toolbarNavigationButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_toolbarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_toolbarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_tooltipForegroundColor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_tooltipForegroundColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_tooltipFrameBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_tooltipFrameBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_viewInflaterClass = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_viewInflaterClass; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowActionBar = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowActionBar; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowActionBarOverlay = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowActionBarOverlay; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowActionModeOverlay = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowActionModeOverlay; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowFixedHeightMajor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowFixedHeightMajor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowFixedHeightMinor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowFixedHeightMinor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowFixedWidthMajor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowFixedWidthMajor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowFixedWidthMinor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowFixedWidthMinor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowMinWidthMajor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowMinWidthMajor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowMinWidthMinor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowMinWidthMinor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.AppCompatTheme_windowNoTitle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowNoTitle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar = global::HelloworldXamarin.Droid.Resource.Styleable.BottomAppBar; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_backgroundTint = global::HelloworldXamarin.Droid.Resource.Styleable.BottomAppBar_backgroundTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_fabAlignmentMode = global::HelloworldXamarin.Droid.Resource.Styleable.BottomAppBar_fabAlignmentMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_fabCradleMargin = global::HelloworldXamarin.Droid.Resource.Styleable.BottomAppBar_fabCradleMargin; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_fabCradleRoundedCornerRadius = global::HelloworldXamarin.Droid.Resource.Styleable.BottomAppBar_fabCradleRoundedCornerRadius; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_fabCradleVerticalOffset = global::HelloworldXamarin.Droid.Resource.Styleable.BottomAppBar_fabCradleVerticalOffset; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomAppBar_hideOnScroll = global::HelloworldXamarin.Droid.Resource.Styleable.BottomAppBar_hideOnScroll; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_elevation = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemBackground = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_itemBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemHorizontalTranslationEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_itemHorizontalTranslationEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemIconSize = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_itemIconSize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemIconTint = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_itemIconTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemTextAppearanceActive = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_itemTextAppearanceActive; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemTextAppearanceInactive = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_itemTextAppearanceInactive; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_itemTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_itemTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_labelVisibilityMode = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_labelVisibilityMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomNavigationView_menu = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_menu; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.BottomSheetBehavior_Layout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_behavior_fitToContents = global::HelloworldXamarin.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_fitToContents; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_behavior_hideable = global::HelloworldXamarin.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_hideable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_behavior_peekHeight = global::HelloworldXamarin.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_peekHeight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.BottomSheetBehavior_Layout_behavior_skipCollapsed = global::HelloworldXamarin.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_skipCollapsed; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ButtonBarLayout = global::HelloworldXamarin.Droid.Resource.Styleable.ButtonBarLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ButtonBarLayout_allowStacking = global::HelloworldXamarin.Droid.Resource.Styleable.ButtonBarLayout_allowStacking; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView = global::HelloworldXamarin.Droid.Resource.Styleable.CardView; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_android_minHeight = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_android_minHeight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_android_minWidth = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_android_minWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_cardBackgroundColor = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_cardBackgroundColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_cardCornerRadius = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_cardCornerRadius; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_cardElevation = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_cardElevation; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_cardMaxElevation = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_cardMaxElevation; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_cardPreventCornerOverlap = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_cardPreventCornerOverlap; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_cardUseCompatPadding = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_cardUseCompatPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_contentPadding = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_contentPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_contentPaddingBottom = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_contentPaddingBottom; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_contentPaddingLeft = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_contentPaddingLeft; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_contentPaddingRight = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_contentPaddingRight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CardView_contentPaddingTop = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_contentPaddingTop; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip = global::HelloworldXamarin.Droid.Resource.Styleable.Chip; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup = global::HelloworldXamarin.Droid.Resource.Styleable.ChipGroup; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup_checkedChip = global::HelloworldXamarin.Droid.Resource.Styleable.ChipGroup_checkedChip; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup_chipSpacing = global::HelloworldXamarin.Droid.Resource.Styleable.ChipGroup_chipSpacing; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup_chipSpacingHorizontal = global::HelloworldXamarin.Droid.Resource.Styleable.ChipGroup_chipSpacingHorizontal; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup_chipSpacingVertical = global::HelloworldXamarin.Droid.Resource.Styleable.ChipGroup_chipSpacingVertical; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup_singleLine = global::HelloworldXamarin.Droid.Resource.Styleable.ChipGroup_singleLine; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ChipGroup_singleSelection = global::HelloworldXamarin.Droid.Resource.Styleable.ChipGroup_singleSelection; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_android_checkable = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_android_checkable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_android_ellipsize = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_android_ellipsize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_android_maxWidth = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_android_maxWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_android_text = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_android_text; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_android_textAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_android_textAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_checkedIcon = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_checkedIcon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_checkedIconEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_checkedIconEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_checkedIconVisible = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_checkedIconVisible; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipBackgroundColor = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipBackgroundColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipCornerRadius = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipCornerRadius; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipEndPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipEndPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipIcon = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipIcon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipIconEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipIconEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipIconSize = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipIconSize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipIconTint = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipIconTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipIconVisible = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipIconVisible; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipMinHeight = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipMinHeight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipStartPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipStartPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipStrokeColor = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipStrokeColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_chipStrokeWidth = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipStrokeWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_closeIcon = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_closeIcon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_closeIconEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_closeIconEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_closeIconEndPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_closeIconEndPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_closeIconSize = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_closeIconSize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_closeIconStartPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_closeIconStartPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_closeIconTint = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_closeIconTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_closeIconVisible = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_closeIconVisible; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_hideMotionSpec = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_hideMotionSpec; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_iconEndPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_iconEndPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_iconStartPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_iconStartPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_rippleColor = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_rippleColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_showMotionSpec = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_showMotionSpec; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_textEndPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_textEndPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Chip_textStartPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_textStartPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleGravity = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleGravity; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_contentScrim = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_contentScrim; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_expandedTitleGravity = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleGravity; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMargin = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMargin; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginBottom = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginBottom; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginEnd = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginEnd; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginStart = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginStart; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginTop = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginTop; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_expandedTitleTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_Layout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseMode = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseParallaxMultiplier = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseParallaxMultiplier; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_scrimAnimationDuration = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_scrimAnimationDuration; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_scrimVisibleHeightTrigger = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_scrimVisibleHeightTrigger; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_statusBarScrim = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_statusBarScrim; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_title = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_title; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_titleEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_titleEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CollapsingToolbarLayout_toolbarId = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_toolbarId; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ColorStateListItem = global::HelloworldXamarin.Droid.Resource.Styleable.ColorStateListItem; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ColorStateListItem_alpha = global::HelloworldXamarin.Droid.Resource.Styleable.ColorStateListItem_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ColorStateListItem_android_alpha = global::HelloworldXamarin.Droid.Resource.Styleable.ColorStateListItem_android_alpha; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ColorStateListItem_android_color = global::HelloworldXamarin.Droid.Resource.Styleable.ColorStateListItem_android_color; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CompoundButton = global::HelloworldXamarin.Droid.Resource.Styleable.CompoundButton; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CompoundButton_android_button = global::HelloworldXamarin.Droid.Resource.Styleable.CompoundButton_android_button; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CompoundButton_buttonTint = global::HelloworldXamarin.Droid.Resource.Styleable.CompoundButton_buttonTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CompoundButton_buttonTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.CompoundButton_buttonTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_keylines = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_keylines; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.CoordinatorLayout_statusBarBackground = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_statusBarBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.DesignTheme = global::HelloworldXamarin.Droid.Resource.Styleable.DesignTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.DesignTheme_bottomSheetDialogTheme = global::HelloworldXamarin.Droid.Resource.Styleable.DesignTheme_bottomSheetDialogTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.DesignTheme_bottomSheetStyle = global::HelloworldXamarin.Droid.Resource.Styleable.DesignTheme_bottomSheetStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_arrowHeadLength = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_arrowHeadLength; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_arrowShaftLength = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_arrowShaftLength; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_barLength = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_barLength; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_color = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_color; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_drawableSize = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_drawableSize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_gapBetweenBars = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_gapBetweenBars; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_spinBars = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_spinBars; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.DrawerArrowToggle_thickness = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_thickness; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_backgroundTint = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_backgroundTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_backgroundTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_backgroundTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_Behavior_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_Behavior_Layout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_Behavior_Layout_behavior_autoHide = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_Behavior_Layout_behavior_autoHide; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_borderWidth = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_borderWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_elevation = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_fabCustomSize = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_fabCustomSize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_fabSize = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_fabSize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_hideMotionSpec = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_hideMotionSpec; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_hoveredFocusedTranslationZ = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_hoveredFocusedTranslationZ; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_maxImageSize = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_maxImageSize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_pressedTranslationZ = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_pressedTranslationZ; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_rippleColor = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_rippleColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_showMotionSpec = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_showMotionSpec; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FloatingActionButton_useCompatPadding = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_useCompatPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FlowLayout = global::HelloworldXamarin.Droid.Resource.Styleable.FlowLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FlowLayout_itemSpacing = global::HelloworldXamarin.Droid.Resource.Styleable.FlowLayout_itemSpacing; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FlowLayout_lineSpacing = global::HelloworldXamarin.Droid.Resource.Styleable.FlowLayout_lineSpacing; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamily = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_android_font = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_font; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_android_fontStyle = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_fontStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_android_fontVariationSettings = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_fontVariationSettings; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_android_fontWeight = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_fontWeight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_android_ttcIndex = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_ttcIndex; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_font = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_font; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_fontStyle = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_fontStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_fontVariationSettings = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_fontVariationSettings; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_fontWeight = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_fontWeight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamilyFont_ttcIndex = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_ttcIndex; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamily_fontProviderAuthority = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderAuthority; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamily_fontProviderCerts = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderCerts; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamily_fontProviderFetchStrategy = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderFetchStrategy; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamily_fontProviderFetchTimeout = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderFetchTimeout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamily_fontProviderPackage = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderPackage; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.FontFamily_fontProviderQuery = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderQuery; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ForegroundLinearLayout = global::HelloworldXamarin.Droid.Resource.Styleable.ForegroundLinearLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ForegroundLinearLayout_android_foreground = global::HelloworldXamarin.Droid.Resource.Styleable.ForegroundLinearLayout_android_foreground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ForegroundLinearLayout_android_foregroundGravity = global::HelloworldXamarin.Droid.Resource.Styleable.ForegroundLinearLayout_android_foregroundGravity; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ForegroundLinearLayout_foregroundInsidePadding = global::HelloworldXamarin.Droid.Resource.Styleable.ForegroundLinearLayout_foregroundInsidePadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColorItem = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColorItem; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColorItem_android_color = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColorItem_android_color; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColorItem_android_offset = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColorItem_android_offset; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_centerColor = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_centerColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_centerX = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_centerX; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_centerY = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_centerY; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_endColor = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_endColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_endX = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_endX; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_endY = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_endY; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_gradientRadius = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_gradientRadius; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_startColor = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_startColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_startX = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_startX; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_startY = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_startY; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_tileMode = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_tileMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.GradientColor_android_type = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_type; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_android_baselineAligned = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_android_baselineAligned; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_android_baselineAlignedChildIndex = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_android_baselineAlignedChildIndex; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_android_gravity = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_android_gravity; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_android_orientation = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_android_orientation; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_android_weightSum = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_android_weightSum; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_divider = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_divider; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_dividerPadding = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_dividerPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_Layout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_gravity = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_gravity; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_height = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_height; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_weight = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_weight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_width = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_width; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_measureWithLargestChild = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_measureWithLargestChild; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.LinearLayoutCompat_showDividers = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_showDividers; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ListPopupWindow = global::HelloworldXamarin.Droid.Resource.Styleable.ListPopupWindow; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ListPopupWindow_android_dropDownHorizontalOffset = global::HelloworldXamarin.Droid.Resource.Styleable.ListPopupWindow_android_dropDownHorizontalOffset; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ListPopupWindow_android_dropDownVerticalOffset = global::HelloworldXamarin.Droid.Resource.Styleable.ListPopupWindow_android_dropDownVerticalOffset; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_android_insetBottom = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_android_insetBottom; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_android_insetLeft = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_android_insetLeft; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_android_insetRight = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_android_insetRight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_android_insetTop = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_android_insetTop; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_backgroundTint = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_backgroundTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_backgroundTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_backgroundTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_cornerRadius = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_cornerRadius; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_icon = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_icon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_iconGravity = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_iconGravity; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_iconPadding = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_iconPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_iconSize = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_iconSize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_iconTint = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_iconTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_iconTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_iconTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_rippleColor = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_rippleColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_strokeColor = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_strokeColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialButton_strokeWidth = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_strokeWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCardView = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialCardView; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCardView_strokeColor = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialCardView_strokeColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialCardView_strokeWidth = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialCardView_strokeWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_bottomSheetDialogTheme = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_bottomSheetDialogTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_bottomSheetStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_bottomSheetStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_chipGroupStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_chipGroupStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_chipStandaloneStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_chipStandaloneStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_chipStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_chipStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_colorAccent = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_colorAccent; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_colorBackgroundFloating = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_colorBackgroundFloating; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_colorPrimary = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_colorPrimary; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_colorPrimaryDark = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_colorPrimaryDark; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_colorSecondary = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_colorSecondary; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_editTextStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_editTextStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_floatingActionButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_floatingActionButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_materialButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_materialButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_materialCardViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_materialCardViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_navigationViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_navigationViewStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_scrimBackground = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_scrimBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_snackbarButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_snackbarButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_tabStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_tabStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_textAppearanceBody1 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceBody1; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_textAppearanceBody2 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceBody2; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_textAppearanceButton = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceButton; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_textAppearanceCaption = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceCaption; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline1 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline1; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline2 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline2; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline3 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline3; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline4 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline4; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline5 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline5; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline6 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline6; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_textAppearanceOverline = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceOverline; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_textAppearanceSubtitle1 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceSubtitle1; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_textAppearanceSubtitle2 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceSubtitle2; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MaterialComponentsTheme_textInputStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textInputStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuGroup = global::HelloworldXamarin.Droid.Resource.Styleable.MenuGroup; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuGroup_android_checkableBehavior = global::HelloworldXamarin.Droid.Resource.Styleable.MenuGroup_android_checkableBehavior; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuGroup_android_enabled = global::HelloworldXamarin.Droid.Resource.Styleable.MenuGroup_android_enabled; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuGroup_android_id = global::HelloworldXamarin.Droid.Resource.Styleable.MenuGroup_android_id; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuGroup_android_menuCategory = global::HelloworldXamarin.Droid.Resource.Styleable.MenuGroup_android_menuCategory; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuGroup_android_orderInCategory = global::HelloworldXamarin.Droid.Resource.Styleable.MenuGroup_android_orderInCategory; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuGroup_android_visible = global::HelloworldXamarin.Droid.Resource.Styleable.MenuGroup_android_visible; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_actionLayout = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_actionLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_actionProviderClass = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_actionProviderClass; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_actionViewClass = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_actionViewClass; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_alphabeticModifiers = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_alphabeticModifiers; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_alphabeticShortcut = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_alphabeticShortcut; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_checkable = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_checkable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_checked = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_checked; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_enabled = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_enabled; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_icon = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_icon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_id = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_id; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_menuCategory = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_menuCategory; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_numericShortcut = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_numericShortcut; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_onClick = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_onClick; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_orderInCategory = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_orderInCategory; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_title = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_title; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_titleCondensed = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_titleCondensed; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_android_visible = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_visible; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_contentDescription = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_contentDescription; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_iconTint = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_iconTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_iconTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_iconTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_numericModifiers = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_numericModifiers; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_showAsAction = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_showAsAction; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuItem_tooltipText = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_tooltipText; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_android_headerBackground = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_android_headerBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_android_horizontalDivider = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_android_horizontalDivider; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_android_itemBackground = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_android_itemBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_android_itemIconDisabledAlpha = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_android_itemIconDisabledAlpha; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_android_itemTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_android_itemTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_android_verticalDivider = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_android_verticalDivider; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_android_windowAnimationStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_android_windowAnimationStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_preserveIconSpacing = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_preserveIconSpacing; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.MenuView_subMenuArrow = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_subMenuArrow; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_android_background = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_android_background; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_android_fitsSystemWindows = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_android_fitsSystemWindows; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_android_maxWidth = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_android_maxWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_elevation = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_headerLayout = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_headerLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemBackground = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_itemBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemHorizontalPadding = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_itemHorizontalPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemIconPadding = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_itemIconPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemIconTint = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_itemIconTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_itemTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_itemTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_itemTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.NavigationView_menu = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_menu; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.PopupWindow = global::HelloworldXamarin.Droid.Resource.Styleable.PopupWindow; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.PopupWindowBackgroundState = global::HelloworldXamarin.Droid.Resource.Styleable.PopupWindowBackgroundState; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.PopupWindowBackgroundState_state_above_anchor = global::HelloworldXamarin.Droid.Resource.Styleable.PopupWindowBackgroundState_state_above_anchor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.PopupWindow_android_popupAnimationStyle = global::HelloworldXamarin.Droid.Resource.Styleable.PopupWindow_android_popupAnimationStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.PopupWindow_android_popupBackground = global::HelloworldXamarin.Droid.Resource.Styleable.PopupWindow_android_popupBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.PopupWindow_overlapAnchor = global::HelloworldXamarin.Droid.Resource.Styleable.PopupWindow_overlapAnchor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecycleListView = global::HelloworldXamarin.Droid.Resource.Styleable.RecycleListView; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecycleListView_paddingBottomNoButtons = global::HelloworldXamarin.Droid.Resource.Styleable.RecycleListView_paddingBottomNoButtons; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecycleListView_paddingTopNoTitle = global::HelloworldXamarin.Droid.Resource.Styleable.RecycleListView_paddingTopNoTitle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_android_descendantFocusability = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_android_descendantFocusability; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_android_orientation = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_android_orientation; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_fastScrollEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_fastScrollEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_fastScrollHorizontalThumbDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_fastScrollHorizontalThumbDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_fastScrollHorizontalTrackDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_fastScrollHorizontalTrackDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_fastScrollVerticalThumbDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_fastScrollVerticalThumbDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_fastScrollVerticalTrackDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_fastScrollVerticalTrackDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_layoutManager = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_layoutManager; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_reverseLayout = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_reverseLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_spanCount = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_spanCount; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.RecyclerView_stackFromEnd = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_stackFromEnd; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrimInsetsFrameLayout = global::HelloworldXamarin.Droid.Resource.Styleable.ScrimInsetsFrameLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground = global::HelloworldXamarin.Droid.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrollingViewBehavior_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.ScrollingViewBehavior_Layout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop = global::HelloworldXamarin.Droid.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_android_focusable = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_android_focusable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_android_imeOptions = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_android_imeOptions; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_android_inputType = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_android_inputType; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_android_maxWidth = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_android_maxWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_closeIcon = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_closeIcon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_commitIcon = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_commitIcon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_defaultQueryHint = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_defaultQueryHint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_goIcon = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_goIcon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_iconifiedByDefault = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_iconifiedByDefault; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_layout = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_layout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_queryBackground = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_queryBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_queryHint = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_queryHint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_searchHintIcon = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_searchHintIcon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_searchIcon = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_searchIcon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_submitBackground = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_submitBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_suggestionRowLayout = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_suggestionRowLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_voiceIcon = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_voiceIcon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Snackbar = global::HelloworldXamarin.Droid.Resource.Styleable.Snackbar; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SnackbarLayout = global::HelloworldXamarin.Droid.Resource.Styleable.SnackbarLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SnackbarLayout_android_maxWidth = global::HelloworldXamarin.Droid.Resource.Styleable.SnackbarLayout_android_maxWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SnackbarLayout_elevation = global::HelloworldXamarin.Droid.Resource.Styleable.SnackbarLayout_elevation; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SnackbarLayout_maxActionInlineWidth = global::HelloworldXamarin.Droid.Resource.Styleable.SnackbarLayout_maxActionInlineWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Snackbar_snackbarButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.Snackbar_snackbarButtonStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Snackbar_snackbarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.Snackbar_snackbarStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Spinner = global::HelloworldXamarin.Droid.Resource.Styleable.Spinner; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Spinner_android_dropDownWidth = global::HelloworldXamarin.Droid.Resource.Styleable.Spinner_android_dropDownWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Spinner_android_entries = global::HelloworldXamarin.Droid.Resource.Styleable.Spinner_android_entries; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Spinner_android_popupBackground = global::HelloworldXamarin.Droid.Resource.Styleable.Spinner_android_popupBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Spinner_android_prompt = global::HelloworldXamarin.Droid.Resource.Styleable.Spinner_android_prompt; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Spinner_popupTheme = global::HelloworldXamarin.Droid.Resource.Styleable.Spinner_popupTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawableItem = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawableItem; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawableItem_android_drawable = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawableItem_android_drawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawable_android_constantSize = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawable_android_constantSize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawable_android_dither = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawable_android_dither; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawable_android_enterFadeDuration = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawable_android_enterFadeDuration; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawable_android_exitFadeDuration = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawable_android_exitFadeDuration; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawable_android_variablePadding = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawable_android_variablePadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.StateListDrawable_android_visible = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawable_android_visible; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_android_textOff = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_android_textOff; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_android_textOn = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_android_textOn; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_android_thumb = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_android_thumb; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_showText = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_showText; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_splitTrack = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_splitTrack; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_switchMinWidth = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_switchMinWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_switchPadding = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_switchPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_switchTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_switchTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_thumbTextPadding = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_thumbTextPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_thumbTint = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_thumbTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_thumbTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_thumbTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_track = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_track; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_trackTint = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_trackTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.SwitchCompat_trackTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_trackTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabItem = global::HelloworldXamarin.Droid.Resource.Styleable.TabItem; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabItem_android_icon = global::HelloworldXamarin.Droid.Resource.Styleable.TabItem_android_icon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabItem_android_layout = global::HelloworldXamarin.Droid.Resource.Styleable.TabItem_android_layout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabItem_android_text = global::HelloworldXamarin.Droid.Resource.Styleable.TabItem_android_text; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabBackground = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabBackground; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabContentStart = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabContentStart; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabGravity = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabGravity; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIconTint = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIconTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIconTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIconTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIndicator = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIndicator; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIndicatorAnimationDuration = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIndicatorAnimationDuration; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIndicatorColor = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIndicatorColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIndicatorFullWidth = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIndicatorFullWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIndicatorGravity = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIndicatorGravity; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabIndicatorHeight = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIndicatorHeight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabInlineLabel = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabInlineLabel; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabMaxWidth = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabMaxWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabMinWidth = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabMinWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabMode = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabPadding = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabPadding; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabPaddingBottom = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabPaddingBottom; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabPaddingEnd = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabPaddingEnd; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabPaddingStart = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabPaddingStart; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabPaddingTop = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabPaddingTop; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabRippleColor = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabRippleColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabSelectedTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabSelectedTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TabLayout_tabUnboundedRipple = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabUnboundedRipple; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_fontFamily = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_fontFamily; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_shadowColor = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_shadowColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_shadowDx = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_shadowDx; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_shadowDy = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_shadowDy; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_shadowRadius = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_shadowRadius; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_textColor = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_textColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_textColorHint = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_textColorHint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_textColorLink = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_textColorLink; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_textSize = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_textSize; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_textStyle = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_textStyle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_android_typeface = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_typeface; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_fontFamily = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_fontFamily; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextAppearance_textAllCaps = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_textAllCaps; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_android_hint = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_android_hint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_android_textColorHint = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_android_textColorHint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxBackgroundColor = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxBackgroundColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxBackgroundMode = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxBackgroundMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxCollapsedPaddingTop = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxCollapsedPaddingTop; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomEnd = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomEnd; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomStart = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomStart; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxCornerRadiusTopEnd = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusTopEnd; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxCornerRadiusTopStart = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusTopStart; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxStrokeColor = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxStrokeColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_boxStrokeWidth = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxStrokeWidth; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_counterEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_counterEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_counterMaxLength = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_counterMaxLength; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_counterOverflowTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_counterOverflowTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_counterTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_counterTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_errorEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_errorEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_errorTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_errorTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_helperText = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_helperText; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_helperTextEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_helperTextEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_helperTextTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_helperTextTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_hintAnimationEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_hintAnimationEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_hintEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_hintEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_hintTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_hintTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_passwordToggleContentDescription = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_passwordToggleContentDescription; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_passwordToggleDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_passwordToggleDrawable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_passwordToggleEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_passwordToggleEnabled; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_passwordToggleTint = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_passwordToggleTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.TextInputLayout_passwordToggleTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_passwordToggleTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ThemeEnforcement = global::HelloworldXamarin.Droid.Resource.Styleable.ThemeEnforcement; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ThemeEnforcement_android_textAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.ThemeEnforcement_android_textAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ThemeEnforcement_enforceMaterialTheme = global::HelloworldXamarin.Droid.Resource.Styleable.ThemeEnforcement_enforceMaterialTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ThemeEnforcement_enforceTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.ThemeEnforcement_enforceTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_android_gravity = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_android_gravity; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_android_minHeight = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_android_minHeight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_buttonGravity = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_buttonGravity; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_collapseContentDescription = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_collapseContentDescription; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_collapseIcon = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_collapseIcon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_contentInsetEnd = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_contentInsetEnd; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_contentInsetEndWithActions = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_contentInsetEndWithActions; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_contentInsetLeft = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_contentInsetLeft; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_contentInsetRight = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_contentInsetRight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_contentInsetStart = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_contentInsetStart; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_contentInsetStartWithNavigation = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_contentInsetStartWithNavigation; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_logo = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_logo; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_logoDescription = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_logoDescription; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_maxButtonHeight = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_maxButtonHeight; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_navigationContentDescription = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_navigationContentDescription; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_navigationIcon = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_navigationIcon; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_popupTheme = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_popupTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_subtitle = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_subtitle; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_subtitleTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_subtitleTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_subtitleTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_subtitleTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_title = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_title; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleMargin = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleMargin; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleMarginBottom = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleMarginBottom; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleMarginEnd = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleMarginEnd; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleMargins = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleMargins; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleMarginStart = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleMarginStart; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleMarginTop = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleMarginTop; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleTextAppearance; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.Toolbar_titleTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleTextColor; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.View = global::HelloworldXamarin.Droid.Resource.Styleable.View; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewBackgroundHelper = global::HelloworldXamarin.Droid.Resource.Styleable.ViewBackgroundHelper; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewBackgroundHelper_android_background = global::HelloworldXamarin.Droid.Resource.Styleable.ViewBackgroundHelper_android_background; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewBackgroundHelper_backgroundTint = global::HelloworldXamarin.Droid.Resource.Styleable.ViewBackgroundHelper_backgroundTint; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewBackgroundHelper_backgroundTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.ViewBackgroundHelper_backgroundTintMode; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewStubCompat = global::HelloworldXamarin.Droid.Resource.Styleable.ViewStubCompat; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewStubCompat_android_id = global::HelloworldXamarin.Droid.Resource.Styleable.ViewStubCompat_android_id; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewStubCompat_android_inflatedId = global::HelloworldXamarin.Droid.Resource.Styleable.ViewStubCompat_android_inflatedId; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ViewStubCompat_android_layout = global::HelloworldXamarin.Droid.Resource.Styleable.ViewStubCompat_android_layout; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.View_android_focusable = global::HelloworldXamarin.Droid.Resource.Styleable.View_android_focusable; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.View_android_theme = global::HelloworldXamarin.Droid.Resource.Styleable.View_android_theme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.View_paddingEnd = global::HelloworldXamarin.Droid.Resource.Styleable.View_paddingEnd; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.View_paddingStart = global::HelloworldXamarin.Droid.Resource.Styleable.View_paddingStart; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.View_theme = global::HelloworldXamarin.Droid.Resource.Styleable.View_theme; + global::Xamarin.Forms.Platform.Resource.Animation.abc_fade_in = global::HelloworldXamarin.Droid.Resource.Animation.abc_fade_in; + global::Xamarin.Forms.Platform.Resource.Animation.abc_fade_out = global::HelloworldXamarin.Droid.Resource.Animation.abc_fade_out; + global::Xamarin.Forms.Platform.Resource.Animation.abc_grow_fade_in_from_bottom = global::HelloworldXamarin.Droid.Resource.Animation.abc_grow_fade_in_from_bottom; + global::Xamarin.Forms.Platform.Resource.Animation.abc_popup_enter = global::HelloworldXamarin.Droid.Resource.Animation.abc_popup_enter; + global::Xamarin.Forms.Platform.Resource.Animation.abc_popup_exit = global::HelloworldXamarin.Droid.Resource.Animation.abc_popup_exit; + global::Xamarin.Forms.Platform.Resource.Animation.abc_shrink_fade_out_from_bottom = global::HelloworldXamarin.Droid.Resource.Animation.abc_shrink_fade_out_from_bottom; + global::Xamarin.Forms.Platform.Resource.Animation.abc_slide_in_bottom = global::HelloworldXamarin.Droid.Resource.Animation.abc_slide_in_bottom; + global::Xamarin.Forms.Platform.Resource.Animation.abc_slide_in_top = global::HelloworldXamarin.Droid.Resource.Animation.abc_slide_in_top; + global::Xamarin.Forms.Platform.Resource.Animation.abc_slide_out_bottom = global::HelloworldXamarin.Droid.Resource.Animation.abc_slide_out_bottom; + global::Xamarin.Forms.Platform.Resource.Animation.abc_slide_out_top = global::HelloworldXamarin.Droid.Resource.Animation.abc_slide_out_top; + global::Xamarin.Forms.Platform.Resource.Animation.abc_tooltip_enter = global::HelloworldXamarin.Droid.Resource.Animation.abc_tooltip_enter; + global::Xamarin.Forms.Platform.Resource.Animation.abc_tooltip_exit = global::HelloworldXamarin.Droid.Resource.Animation.abc_tooltip_exit; + global::Xamarin.Forms.Platform.Resource.Animation.design_bottom_sheet_slide_in = global::HelloworldXamarin.Droid.Resource.Animation.design_bottom_sheet_slide_in; + global::Xamarin.Forms.Platform.Resource.Animation.design_bottom_sheet_slide_out = global::HelloworldXamarin.Droid.Resource.Animation.design_bottom_sheet_slide_out; + global::Xamarin.Forms.Platform.Resource.Animation.design_snackbar_in = global::HelloworldXamarin.Droid.Resource.Animation.design_snackbar_in; + global::Xamarin.Forms.Platform.Resource.Animation.design_snackbar_out = global::HelloworldXamarin.Droid.Resource.Animation.design_snackbar_out; + global::Xamarin.Forms.Platform.Resource.Animation.EnterFromLeft = global::HelloworldXamarin.Droid.Resource.Animation.EnterFromLeft; + global::Xamarin.Forms.Platform.Resource.Animation.EnterFromRight = global::HelloworldXamarin.Droid.Resource.Animation.EnterFromRight; + global::Xamarin.Forms.Platform.Resource.Animation.ExitToLeft = global::HelloworldXamarin.Droid.Resource.Animation.ExitToLeft; + global::Xamarin.Forms.Platform.Resource.Animation.ExitToRight = global::HelloworldXamarin.Droid.Resource.Animation.ExitToRight; + global::Xamarin.Forms.Platform.Resource.Animator.design_appbar_state_list_animator = global::HelloworldXamarin.Droid.Resource.Animator.design_appbar_state_list_animator; + global::Xamarin.Forms.Platform.Resource.Animator.design_fab_hide_motion_spec = global::HelloworldXamarin.Droid.Resource.Animator.design_fab_hide_motion_spec; + global::Xamarin.Forms.Platform.Resource.Animator.design_fab_show_motion_spec = global::HelloworldXamarin.Droid.Resource.Animator.design_fab_show_motion_spec; + global::Xamarin.Forms.Platform.Resource.Animator.mtrl_btn_state_list_anim = global::HelloworldXamarin.Droid.Resource.Animator.mtrl_btn_state_list_anim; + global::Xamarin.Forms.Platform.Resource.Animator.mtrl_btn_unelevated_state_list_anim = global::HelloworldXamarin.Droid.Resource.Animator.mtrl_btn_unelevated_state_list_anim; + global::Xamarin.Forms.Platform.Resource.Animator.mtrl_chip_state_list_anim = global::HelloworldXamarin.Droid.Resource.Animator.mtrl_chip_state_list_anim; + global::Xamarin.Forms.Platform.Resource.Animator.mtrl_fab_hide_motion_spec = global::HelloworldXamarin.Droid.Resource.Animator.mtrl_fab_hide_motion_spec; + global::Xamarin.Forms.Platform.Resource.Animator.mtrl_fab_show_motion_spec = global::HelloworldXamarin.Droid.Resource.Animator.mtrl_fab_show_motion_spec; + global::Xamarin.Forms.Platform.Resource.Animator.mtrl_fab_transformation_sheet_collapse_spec = global::HelloworldXamarin.Droid.Resource.Animator.mtrl_fab_transformation_sheet_collapse_spec; + global::Xamarin.Forms.Platform.Resource.Animator.mtrl_fab_transformation_sheet_expand_spec = global::HelloworldXamarin.Droid.Resource.Animator.mtrl_fab_transformation_sheet_expand_spec; + global::Xamarin.Forms.Platform.Resource.Attribute.actionBarDivider = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarDivider; + global::Xamarin.Forms.Platform.Resource.Attribute.actionBarItemBackground = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarItemBackground; + global::Xamarin.Forms.Platform.Resource.Attribute.actionBarPopupTheme = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarPopupTheme; + global::Xamarin.Forms.Platform.Resource.Attribute.actionBarSize = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarSize; + global::Xamarin.Forms.Platform.Resource.Attribute.actionBarSplitStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarSplitStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.actionBarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.actionBarTabBarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarTabBarStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.actionBarTabStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarTabStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.actionBarTabTextStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarTabTextStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.actionBarTheme = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarTheme; + global::Xamarin.Forms.Platform.Resource.Attribute.actionBarWidgetTheme = global::HelloworldXamarin.Droid.Resource.Attribute.actionBarWidgetTheme; + global::Xamarin.Forms.Platform.Resource.Attribute.actionButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionButtonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.actionDropDownStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionDropDownStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.actionLayout = global::HelloworldXamarin.Droid.Resource.Attribute.actionLayout; + global::Xamarin.Forms.Platform.Resource.Attribute.actionMenuTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.actionMenuTextAppearance; + global::Xamarin.Forms.Platform.Resource.Attribute.actionMenuTextColor = global::HelloworldXamarin.Droid.Resource.Attribute.actionMenuTextColor; + global::Xamarin.Forms.Platform.Resource.Attribute.actionModeBackground = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeBackground; + global::Xamarin.Forms.Platform.Resource.Attribute.actionModeCloseButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeCloseButtonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.actionModeCloseDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeCloseDrawable; + global::Xamarin.Forms.Platform.Resource.Attribute.actionModeCopyDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeCopyDrawable; + global::Xamarin.Forms.Platform.Resource.Attribute.actionModeCutDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeCutDrawable; + global::Xamarin.Forms.Platform.Resource.Attribute.actionModeFindDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeFindDrawable; + global::Xamarin.Forms.Platform.Resource.Attribute.actionModePasteDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModePasteDrawable; + global::Xamarin.Forms.Platform.Resource.Attribute.actionModePopupWindowStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionModePopupWindowStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.actionModeSelectAllDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeSelectAllDrawable; + global::Xamarin.Forms.Platform.Resource.Attribute.actionModeShareDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeShareDrawable; + global::Xamarin.Forms.Platform.Resource.Attribute.actionModeSplitBackground = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeSplitBackground; + global::Xamarin.Forms.Platform.Resource.Attribute.actionModeStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.actionModeWebSearchDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.actionModeWebSearchDrawable; + global::Xamarin.Forms.Platform.Resource.Attribute.actionOverflowButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionOverflowButtonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.actionOverflowMenuStyle = global::HelloworldXamarin.Droid.Resource.Attribute.actionOverflowMenuStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.actionProviderClass = global::HelloworldXamarin.Droid.Resource.Attribute.actionProviderClass; + global::Xamarin.Forms.Platform.Resource.Attribute.actionViewClass = global::HelloworldXamarin.Droid.Resource.Attribute.actionViewClass; + global::Xamarin.Forms.Platform.Resource.Attribute.activityChooserViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.activityChooserViewStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.alertDialogButtonGroupStyle = global::HelloworldXamarin.Droid.Resource.Attribute.alertDialogButtonGroupStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.alertDialogCenterButtons = global::HelloworldXamarin.Droid.Resource.Attribute.alertDialogCenterButtons; + global::Xamarin.Forms.Platform.Resource.Attribute.alertDialogStyle = global::HelloworldXamarin.Droid.Resource.Attribute.alertDialogStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.alertDialogTheme = global::HelloworldXamarin.Droid.Resource.Attribute.alertDialogTheme; + global::Xamarin.Forms.Platform.Resource.Attribute.allowStacking = global::HelloworldXamarin.Droid.Resource.Attribute.allowStacking; + global::Xamarin.Forms.Platform.Resource.Attribute.alpha = global::HelloworldXamarin.Droid.Resource.Attribute.alpha; + global::Xamarin.Forms.Platform.Resource.Attribute.alphabeticModifiers = global::HelloworldXamarin.Droid.Resource.Attribute.alphabeticModifiers; + global::Xamarin.Forms.Platform.Resource.Attribute.arrowHeadLength = global::HelloworldXamarin.Droid.Resource.Attribute.arrowHeadLength; + global::Xamarin.Forms.Platform.Resource.Attribute.arrowShaftLength = global::HelloworldXamarin.Droid.Resource.Attribute.arrowShaftLength; + global::Xamarin.Forms.Platform.Resource.Attribute.autoCompleteTextViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.autoCompleteTextViewStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.autoSizeMaxTextSize = global::HelloworldXamarin.Droid.Resource.Attribute.autoSizeMaxTextSize; + global::Xamarin.Forms.Platform.Resource.Attribute.autoSizeMinTextSize = global::HelloworldXamarin.Droid.Resource.Attribute.autoSizeMinTextSize; + global::Xamarin.Forms.Platform.Resource.Attribute.autoSizePresetSizes = global::HelloworldXamarin.Droid.Resource.Attribute.autoSizePresetSizes; + global::Xamarin.Forms.Platform.Resource.Attribute.autoSizeStepGranularity = global::HelloworldXamarin.Droid.Resource.Attribute.autoSizeStepGranularity; + global::Xamarin.Forms.Platform.Resource.Attribute.autoSizeTextType = global::HelloworldXamarin.Droid.Resource.Attribute.autoSizeTextType; + global::Xamarin.Forms.Platform.Resource.Attribute.background = global::HelloworldXamarin.Droid.Resource.Attribute.background; + global::Xamarin.Forms.Platform.Resource.Attribute.backgroundSplit = global::HelloworldXamarin.Droid.Resource.Attribute.backgroundSplit; + global::Xamarin.Forms.Platform.Resource.Attribute.backgroundStacked = global::HelloworldXamarin.Droid.Resource.Attribute.backgroundStacked; + global::Xamarin.Forms.Platform.Resource.Attribute.backgroundTint = global::HelloworldXamarin.Droid.Resource.Attribute.backgroundTint; + global::Xamarin.Forms.Platform.Resource.Attribute.backgroundTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.backgroundTintMode; + global::Xamarin.Forms.Platform.Resource.Attribute.barLength = global::HelloworldXamarin.Droid.Resource.Attribute.barLength; + global::Xamarin.Forms.Platform.Resource.Attribute.behavior_autoHide = global::HelloworldXamarin.Droid.Resource.Attribute.behavior_autoHide; + global::Xamarin.Forms.Platform.Resource.Attribute.behavior_fitToContents = global::HelloworldXamarin.Droid.Resource.Attribute.behavior_fitToContents; + global::Xamarin.Forms.Platform.Resource.Attribute.behavior_hideable = global::HelloworldXamarin.Droid.Resource.Attribute.behavior_hideable; + global::Xamarin.Forms.Platform.Resource.Attribute.behavior_overlapTop = global::HelloworldXamarin.Droid.Resource.Attribute.behavior_overlapTop; + global::Xamarin.Forms.Platform.Resource.Attribute.behavior_peekHeight = global::HelloworldXamarin.Droid.Resource.Attribute.behavior_peekHeight; + global::Xamarin.Forms.Platform.Resource.Attribute.behavior_skipCollapsed = global::HelloworldXamarin.Droid.Resource.Attribute.behavior_skipCollapsed; + global::Xamarin.Forms.Platform.Resource.Attribute.borderlessButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.borderlessButtonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.borderWidth = global::HelloworldXamarin.Droid.Resource.Attribute.borderWidth; + global::Xamarin.Forms.Platform.Resource.Attribute.bottomAppBarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.bottomAppBarStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.bottomNavigationStyle = global::HelloworldXamarin.Droid.Resource.Attribute.bottomNavigationStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.bottomSheetDialogTheme = global::HelloworldXamarin.Droid.Resource.Attribute.bottomSheetDialogTheme; + global::Xamarin.Forms.Platform.Resource.Attribute.bottomSheetStyle = global::HelloworldXamarin.Droid.Resource.Attribute.bottomSheetStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.boxBackgroundColor = global::HelloworldXamarin.Droid.Resource.Attribute.boxBackgroundColor; + global::Xamarin.Forms.Platform.Resource.Attribute.boxBackgroundMode = global::HelloworldXamarin.Droid.Resource.Attribute.boxBackgroundMode; + global::Xamarin.Forms.Platform.Resource.Attribute.boxCollapsedPaddingTop = global::HelloworldXamarin.Droid.Resource.Attribute.boxCollapsedPaddingTop; + global::Xamarin.Forms.Platform.Resource.Attribute.boxCornerRadiusBottomEnd = global::HelloworldXamarin.Droid.Resource.Attribute.boxCornerRadiusBottomEnd; + global::Xamarin.Forms.Platform.Resource.Attribute.boxCornerRadiusBottomStart = global::HelloworldXamarin.Droid.Resource.Attribute.boxCornerRadiusBottomStart; + global::Xamarin.Forms.Platform.Resource.Attribute.boxCornerRadiusTopEnd = global::HelloworldXamarin.Droid.Resource.Attribute.boxCornerRadiusTopEnd; + global::Xamarin.Forms.Platform.Resource.Attribute.boxCornerRadiusTopStart = global::HelloworldXamarin.Droid.Resource.Attribute.boxCornerRadiusTopStart; + global::Xamarin.Forms.Platform.Resource.Attribute.boxStrokeColor = global::HelloworldXamarin.Droid.Resource.Attribute.boxStrokeColor; + global::Xamarin.Forms.Platform.Resource.Attribute.boxStrokeWidth = global::HelloworldXamarin.Droid.Resource.Attribute.boxStrokeWidth; + global::Xamarin.Forms.Platform.Resource.Attribute.buttonBarButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.buttonBarButtonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.buttonBarNegativeButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.buttonBarNegativeButtonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.buttonBarNeutralButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.buttonBarNeutralButtonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.buttonBarPositiveButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.buttonBarPositiveButtonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.buttonBarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.buttonBarStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.buttonGravity = global::HelloworldXamarin.Droid.Resource.Attribute.buttonGravity; + global::Xamarin.Forms.Platform.Resource.Attribute.buttonIconDimen = global::HelloworldXamarin.Droid.Resource.Attribute.buttonIconDimen; + global::Xamarin.Forms.Platform.Resource.Attribute.buttonPanelSideLayout = global::HelloworldXamarin.Droid.Resource.Attribute.buttonPanelSideLayout; + global::Xamarin.Forms.Platform.Resource.Attribute.buttonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.buttonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.buttonStyleSmall = global::HelloworldXamarin.Droid.Resource.Attribute.buttonStyleSmall; + global::Xamarin.Forms.Platform.Resource.Attribute.buttonTint = global::HelloworldXamarin.Droid.Resource.Attribute.buttonTint; + global::Xamarin.Forms.Platform.Resource.Attribute.buttonTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.buttonTintMode; + global::Xamarin.Forms.Platform.Resource.Attribute.cardBackgroundColor = global::HelloworldXamarin.Droid.Resource.Attribute.cardBackgroundColor; + global::Xamarin.Forms.Platform.Resource.Attribute.cardCornerRadius = global::HelloworldXamarin.Droid.Resource.Attribute.cardCornerRadius; + global::Xamarin.Forms.Platform.Resource.Attribute.cardElevation = global::HelloworldXamarin.Droid.Resource.Attribute.cardElevation; + global::Xamarin.Forms.Platform.Resource.Attribute.cardMaxElevation = global::HelloworldXamarin.Droid.Resource.Attribute.cardMaxElevation; + global::Xamarin.Forms.Platform.Resource.Attribute.cardPreventCornerOverlap = global::HelloworldXamarin.Droid.Resource.Attribute.cardPreventCornerOverlap; + global::Xamarin.Forms.Platform.Resource.Attribute.cardUseCompatPadding = global::HelloworldXamarin.Droid.Resource.Attribute.cardUseCompatPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.cardViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.cardViewStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.checkboxStyle = global::HelloworldXamarin.Droid.Resource.Attribute.checkboxStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.checkedChip = global::HelloworldXamarin.Droid.Resource.Attribute.checkedChip; + global::Xamarin.Forms.Platform.Resource.Attribute.checkedIcon = global::HelloworldXamarin.Droid.Resource.Attribute.checkedIcon; + global::Xamarin.Forms.Platform.Resource.Attribute.checkedIconEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.checkedIconEnabled; + global::Xamarin.Forms.Platform.Resource.Attribute.checkedIconVisible = global::HelloworldXamarin.Droid.Resource.Attribute.checkedIconVisible; + global::Xamarin.Forms.Platform.Resource.Attribute.checkedTextViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.checkedTextViewStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.chipBackgroundColor = global::HelloworldXamarin.Droid.Resource.Attribute.chipBackgroundColor; + global::Xamarin.Forms.Platform.Resource.Attribute.chipCornerRadius = global::HelloworldXamarin.Droid.Resource.Attribute.chipCornerRadius; + global::Xamarin.Forms.Platform.Resource.Attribute.chipEndPadding = global::HelloworldXamarin.Droid.Resource.Attribute.chipEndPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.chipGroupStyle = global::HelloworldXamarin.Droid.Resource.Attribute.chipGroupStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.chipIcon = global::HelloworldXamarin.Droid.Resource.Attribute.chipIcon; + global::Xamarin.Forms.Platform.Resource.Attribute.chipIconEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.chipIconEnabled; + global::Xamarin.Forms.Platform.Resource.Attribute.chipIconSize = global::HelloworldXamarin.Droid.Resource.Attribute.chipIconSize; + global::Xamarin.Forms.Platform.Resource.Attribute.chipIconTint = global::HelloworldXamarin.Droid.Resource.Attribute.chipIconTint; + global::Xamarin.Forms.Platform.Resource.Attribute.chipIconVisible = global::HelloworldXamarin.Droid.Resource.Attribute.chipIconVisible; + global::Xamarin.Forms.Platform.Resource.Attribute.chipMinHeight = global::HelloworldXamarin.Droid.Resource.Attribute.chipMinHeight; + global::Xamarin.Forms.Platform.Resource.Attribute.chipSpacing = global::HelloworldXamarin.Droid.Resource.Attribute.chipSpacing; + global::Xamarin.Forms.Platform.Resource.Attribute.chipSpacingHorizontal = global::HelloworldXamarin.Droid.Resource.Attribute.chipSpacingHorizontal; + global::Xamarin.Forms.Platform.Resource.Attribute.chipSpacingVertical = global::HelloworldXamarin.Droid.Resource.Attribute.chipSpacingVertical; + global::Xamarin.Forms.Platform.Resource.Attribute.chipStandaloneStyle = global::HelloworldXamarin.Droid.Resource.Attribute.chipStandaloneStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.chipStartPadding = global::HelloworldXamarin.Droid.Resource.Attribute.chipStartPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.chipStrokeColor = global::HelloworldXamarin.Droid.Resource.Attribute.chipStrokeColor; + global::Xamarin.Forms.Platform.Resource.Attribute.chipStrokeWidth = global::HelloworldXamarin.Droid.Resource.Attribute.chipStrokeWidth; + global::Xamarin.Forms.Platform.Resource.Attribute.chipStyle = global::HelloworldXamarin.Droid.Resource.Attribute.chipStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.closeIcon = global::HelloworldXamarin.Droid.Resource.Attribute.closeIcon; + global::Xamarin.Forms.Platform.Resource.Attribute.closeIconEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.closeIconEnabled; + global::Xamarin.Forms.Platform.Resource.Attribute.closeIconEndPadding = global::HelloworldXamarin.Droid.Resource.Attribute.closeIconEndPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.closeIconSize = global::HelloworldXamarin.Droid.Resource.Attribute.closeIconSize; + global::Xamarin.Forms.Platform.Resource.Attribute.closeIconStartPadding = global::HelloworldXamarin.Droid.Resource.Attribute.closeIconStartPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.closeIconTint = global::HelloworldXamarin.Droid.Resource.Attribute.closeIconTint; + global::Xamarin.Forms.Platform.Resource.Attribute.closeIconVisible = global::HelloworldXamarin.Droid.Resource.Attribute.closeIconVisible; + global::Xamarin.Forms.Platform.Resource.Attribute.closeItemLayout = global::HelloworldXamarin.Droid.Resource.Attribute.closeItemLayout; + global::Xamarin.Forms.Platform.Resource.Attribute.collapseContentDescription = global::HelloworldXamarin.Droid.Resource.Attribute.collapseContentDescription; + global::Xamarin.Forms.Platform.Resource.Attribute.collapsedTitleGravity = global::HelloworldXamarin.Droid.Resource.Attribute.collapsedTitleGravity; + global::Xamarin.Forms.Platform.Resource.Attribute.collapsedTitleTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.collapsedTitleTextAppearance; + global::Xamarin.Forms.Platform.Resource.Attribute.collapseIcon = global::HelloworldXamarin.Droid.Resource.Attribute.collapseIcon; + global::Xamarin.Forms.Platform.Resource.Attribute.color = global::HelloworldXamarin.Droid.Resource.Attribute.color; + global::Xamarin.Forms.Platform.Resource.Attribute.colorAccent = global::HelloworldXamarin.Droid.Resource.Attribute.colorAccent; + global::Xamarin.Forms.Platform.Resource.Attribute.colorBackgroundFloating = global::HelloworldXamarin.Droid.Resource.Attribute.colorBackgroundFloating; + global::Xamarin.Forms.Platform.Resource.Attribute.colorButtonNormal = global::HelloworldXamarin.Droid.Resource.Attribute.colorButtonNormal; + global::Xamarin.Forms.Platform.Resource.Attribute.colorControlActivated = global::HelloworldXamarin.Droid.Resource.Attribute.colorControlActivated; + global::Xamarin.Forms.Platform.Resource.Attribute.colorControlHighlight = global::HelloworldXamarin.Droid.Resource.Attribute.colorControlHighlight; + global::Xamarin.Forms.Platform.Resource.Attribute.colorControlNormal = global::HelloworldXamarin.Droid.Resource.Attribute.colorControlNormal; + global::Xamarin.Forms.Platform.Resource.Attribute.colorError = global::HelloworldXamarin.Droid.Resource.Attribute.colorError; + global::Xamarin.Forms.Platform.Resource.Attribute.colorPrimary = global::HelloworldXamarin.Droid.Resource.Attribute.colorPrimary; + global::Xamarin.Forms.Platform.Resource.Attribute.colorPrimaryDark = global::HelloworldXamarin.Droid.Resource.Attribute.colorPrimaryDark; + global::Xamarin.Forms.Platform.Resource.Attribute.colorSecondary = global::HelloworldXamarin.Droid.Resource.Attribute.colorSecondary; + global::Xamarin.Forms.Platform.Resource.Attribute.colorSwitchThumbNormal = global::HelloworldXamarin.Droid.Resource.Attribute.colorSwitchThumbNormal; + global::Xamarin.Forms.Platform.Resource.Attribute.commitIcon = global::HelloworldXamarin.Droid.Resource.Attribute.commitIcon; + global::Xamarin.Forms.Platform.Resource.Attribute.contentDescription = global::HelloworldXamarin.Droid.Resource.Attribute.contentDescription; + global::Xamarin.Forms.Platform.Resource.Attribute.contentInsetEnd = global::HelloworldXamarin.Droid.Resource.Attribute.contentInsetEnd; + global::Xamarin.Forms.Platform.Resource.Attribute.contentInsetEndWithActions = global::HelloworldXamarin.Droid.Resource.Attribute.contentInsetEndWithActions; + global::Xamarin.Forms.Platform.Resource.Attribute.contentInsetLeft = global::HelloworldXamarin.Droid.Resource.Attribute.contentInsetLeft; + global::Xamarin.Forms.Platform.Resource.Attribute.contentInsetRight = global::HelloworldXamarin.Droid.Resource.Attribute.contentInsetRight; + global::Xamarin.Forms.Platform.Resource.Attribute.contentInsetStart = global::HelloworldXamarin.Droid.Resource.Attribute.contentInsetStart; + global::Xamarin.Forms.Platform.Resource.Attribute.contentInsetStartWithNavigation = global::HelloworldXamarin.Droid.Resource.Attribute.contentInsetStartWithNavigation; + global::Xamarin.Forms.Platform.Resource.Attribute.contentPadding = global::HelloworldXamarin.Droid.Resource.Attribute.contentPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.contentPaddingBottom = global::HelloworldXamarin.Droid.Resource.Attribute.contentPaddingBottom; + global::Xamarin.Forms.Platform.Resource.Attribute.contentPaddingLeft = global::HelloworldXamarin.Droid.Resource.Attribute.contentPaddingLeft; + global::Xamarin.Forms.Platform.Resource.Attribute.contentPaddingRight = global::HelloworldXamarin.Droid.Resource.Attribute.contentPaddingRight; + global::Xamarin.Forms.Platform.Resource.Attribute.contentPaddingTop = global::HelloworldXamarin.Droid.Resource.Attribute.contentPaddingTop; + global::Xamarin.Forms.Platform.Resource.Attribute.contentScrim = global::HelloworldXamarin.Droid.Resource.Attribute.contentScrim; + global::Xamarin.Forms.Platform.Resource.Attribute.controlBackground = global::HelloworldXamarin.Droid.Resource.Attribute.controlBackground; + global::Xamarin.Forms.Platform.Resource.Attribute.coordinatorLayoutStyle = global::HelloworldXamarin.Droid.Resource.Attribute.coordinatorLayoutStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.cornerRadius = global::HelloworldXamarin.Droid.Resource.Attribute.cornerRadius; + global::Xamarin.Forms.Platform.Resource.Attribute.counterEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.counterEnabled; + global::Xamarin.Forms.Platform.Resource.Attribute.counterMaxLength = global::HelloworldXamarin.Droid.Resource.Attribute.counterMaxLength; + global::Xamarin.Forms.Platform.Resource.Attribute.counterOverflowTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.counterOverflowTextAppearance; + global::Xamarin.Forms.Platform.Resource.Attribute.counterTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.counterTextAppearance; + global::Xamarin.Forms.Platform.Resource.Attribute.customNavigationLayout = global::HelloworldXamarin.Droid.Resource.Attribute.customNavigationLayout; + global::Xamarin.Forms.Platform.Resource.Attribute.defaultQueryHint = global::HelloworldXamarin.Droid.Resource.Attribute.defaultQueryHint; + global::Xamarin.Forms.Platform.Resource.Attribute.dialogCornerRadius = global::HelloworldXamarin.Droid.Resource.Attribute.dialogCornerRadius; + global::Xamarin.Forms.Platform.Resource.Attribute.dialogPreferredPadding = global::HelloworldXamarin.Droid.Resource.Attribute.dialogPreferredPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.dialogTheme = global::HelloworldXamarin.Droid.Resource.Attribute.dialogTheme; + global::Xamarin.Forms.Platform.Resource.Attribute.displayOptions = global::HelloworldXamarin.Droid.Resource.Attribute.displayOptions; + global::Xamarin.Forms.Platform.Resource.Attribute.divider = global::HelloworldXamarin.Droid.Resource.Attribute.divider; + global::Xamarin.Forms.Platform.Resource.Attribute.dividerHorizontal = global::HelloworldXamarin.Droid.Resource.Attribute.dividerHorizontal; + global::Xamarin.Forms.Platform.Resource.Attribute.dividerPadding = global::HelloworldXamarin.Droid.Resource.Attribute.dividerPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.dividerVertical = global::HelloworldXamarin.Droid.Resource.Attribute.dividerVertical; + global::Xamarin.Forms.Platform.Resource.Attribute.drawableSize = global::HelloworldXamarin.Droid.Resource.Attribute.drawableSize; + global::Xamarin.Forms.Platform.Resource.Attribute.drawerArrowStyle = global::HelloworldXamarin.Droid.Resource.Attribute.drawerArrowStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.dropdownListPreferredItemHeight = global::HelloworldXamarin.Droid.Resource.Attribute.dropdownListPreferredItemHeight; + global::Xamarin.Forms.Platform.Resource.Attribute.dropDownListViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.dropDownListViewStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.editTextBackground = global::HelloworldXamarin.Droid.Resource.Attribute.editTextBackground; + global::Xamarin.Forms.Platform.Resource.Attribute.editTextColor = global::HelloworldXamarin.Droid.Resource.Attribute.editTextColor; + global::Xamarin.Forms.Platform.Resource.Attribute.editTextStyle = global::HelloworldXamarin.Droid.Resource.Attribute.editTextStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.elevation = global::HelloworldXamarin.Droid.Resource.Attribute.elevation; + global::Xamarin.Forms.Platform.Resource.Attribute.enforceMaterialTheme = global::HelloworldXamarin.Droid.Resource.Attribute.enforceMaterialTheme; + global::Xamarin.Forms.Platform.Resource.Attribute.enforceTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.enforceTextAppearance; + global::Xamarin.Forms.Platform.Resource.Attribute.errorEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.errorEnabled; + global::Xamarin.Forms.Platform.Resource.Attribute.errorTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.errorTextAppearance; + global::Xamarin.Forms.Platform.Resource.Attribute.expandActivityOverflowButtonDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.expandActivityOverflowButtonDrawable; + global::Xamarin.Forms.Platform.Resource.Attribute.expanded = global::HelloworldXamarin.Droid.Resource.Attribute.expanded; + global::Xamarin.Forms.Platform.Resource.Attribute.expandedTitleGravity = global::HelloworldXamarin.Droid.Resource.Attribute.expandedTitleGravity; + global::Xamarin.Forms.Platform.Resource.Attribute.expandedTitleMargin = global::HelloworldXamarin.Droid.Resource.Attribute.expandedTitleMargin; + global::Xamarin.Forms.Platform.Resource.Attribute.expandedTitleMarginBottom = global::HelloworldXamarin.Droid.Resource.Attribute.expandedTitleMarginBottom; + global::Xamarin.Forms.Platform.Resource.Attribute.expandedTitleMarginEnd = global::HelloworldXamarin.Droid.Resource.Attribute.expandedTitleMarginEnd; + global::Xamarin.Forms.Platform.Resource.Attribute.expandedTitleMarginStart = global::HelloworldXamarin.Droid.Resource.Attribute.expandedTitleMarginStart; + global::Xamarin.Forms.Platform.Resource.Attribute.expandedTitleMarginTop = global::HelloworldXamarin.Droid.Resource.Attribute.expandedTitleMarginTop; + global::Xamarin.Forms.Platform.Resource.Attribute.expandedTitleTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.expandedTitleTextAppearance; + global::Xamarin.Forms.Platform.Resource.Attribute.fabAlignmentMode = global::HelloworldXamarin.Droid.Resource.Attribute.fabAlignmentMode; + global::Xamarin.Forms.Platform.Resource.Attribute.fabCradleMargin = global::HelloworldXamarin.Droid.Resource.Attribute.fabCradleMargin; + global::Xamarin.Forms.Platform.Resource.Attribute.fabCradleRoundedCornerRadius = global::HelloworldXamarin.Droid.Resource.Attribute.fabCradleRoundedCornerRadius; + global::Xamarin.Forms.Platform.Resource.Attribute.fabCradleVerticalOffset = global::HelloworldXamarin.Droid.Resource.Attribute.fabCradleVerticalOffset; + global::Xamarin.Forms.Platform.Resource.Attribute.fabCustomSize = global::HelloworldXamarin.Droid.Resource.Attribute.fabCustomSize; + global::Xamarin.Forms.Platform.Resource.Attribute.fabSize = global::HelloworldXamarin.Droid.Resource.Attribute.fabSize; + global::Xamarin.Forms.Platform.Resource.Attribute.fastScrollEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.fastScrollEnabled; + global::Xamarin.Forms.Platform.Resource.Attribute.fastScrollHorizontalThumbDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.fastScrollHorizontalThumbDrawable; + global::Xamarin.Forms.Platform.Resource.Attribute.fastScrollHorizontalTrackDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.fastScrollHorizontalTrackDrawable; + global::Xamarin.Forms.Platform.Resource.Attribute.fastScrollVerticalThumbDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.fastScrollVerticalThumbDrawable; + global::Xamarin.Forms.Platform.Resource.Attribute.fastScrollVerticalTrackDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.fastScrollVerticalTrackDrawable; + global::Xamarin.Forms.Platform.Resource.Attribute.firstBaselineToTopHeight = global::HelloworldXamarin.Droid.Resource.Attribute.firstBaselineToTopHeight; + global::Xamarin.Forms.Platform.Resource.Attribute.floatingActionButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.floatingActionButtonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.font = global::HelloworldXamarin.Droid.Resource.Attribute.font; + global::Xamarin.Forms.Platform.Resource.Attribute.fontFamily = global::HelloworldXamarin.Droid.Resource.Attribute.fontFamily; + global::Xamarin.Forms.Platform.Resource.Attribute.fontProviderAuthority = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderAuthority; + global::Xamarin.Forms.Platform.Resource.Attribute.fontProviderCerts = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderCerts; + global::Xamarin.Forms.Platform.Resource.Attribute.fontProviderFetchStrategy = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderFetchStrategy; + global::Xamarin.Forms.Platform.Resource.Attribute.fontProviderFetchTimeout = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderFetchTimeout; + global::Xamarin.Forms.Platform.Resource.Attribute.fontProviderPackage = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderPackage; + global::Xamarin.Forms.Platform.Resource.Attribute.fontProviderQuery = global::HelloworldXamarin.Droid.Resource.Attribute.fontProviderQuery; + global::Xamarin.Forms.Platform.Resource.Attribute.fontStyle = global::HelloworldXamarin.Droid.Resource.Attribute.fontStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.fontVariationSettings = global::HelloworldXamarin.Droid.Resource.Attribute.fontVariationSettings; + global::Xamarin.Forms.Platform.Resource.Attribute.fontWeight = global::HelloworldXamarin.Droid.Resource.Attribute.fontWeight; + global::Xamarin.Forms.Platform.Resource.Attribute.foregroundInsidePadding = global::HelloworldXamarin.Droid.Resource.Attribute.foregroundInsidePadding; + global::Xamarin.Forms.Platform.Resource.Attribute.gapBetweenBars = global::HelloworldXamarin.Droid.Resource.Attribute.gapBetweenBars; + global::Xamarin.Forms.Platform.Resource.Attribute.goIcon = global::HelloworldXamarin.Droid.Resource.Attribute.goIcon; + global::Xamarin.Forms.Platform.Resource.Attribute.headerLayout = global::HelloworldXamarin.Droid.Resource.Attribute.headerLayout; + global::Xamarin.Forms.Platform.Resource.Attribute.height = global::HelloworldXamarin.Droid.Resource.Attribute.height; + global::Xamarin.Forms.Platform.Resource.Attribute.helperText = global::HelloworldXamarin.Droid.Resource.Attribute.helperText; + global::Xamarin.Forms.Platform.Resource.Attribute.helperTextEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.helperTextEnabled; + global::Xamarin.Forms.Platform.Resource.Attribute.helperTextTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.helperTextTextAppearance; + global::Xamarin.Forms.Platform.Resource.Attribute.hideMotionSpec = global::HelloworldXamarin.Droid.Resource.Attribute.hideMotionSpec; + global::Xamarin.Forms.Platform.Resource.Attribute.hideOnContentScroll = global::HelloworldXamarin.Droid.Resource.Attribute.hideOnContentScroll; + global::Xamarin.Forms.Platform.Resource.Attribute.hideOnScroll = global::HelloworldXamarin.Droid.Resource.Attribute.hideOnScroll; + global::Xamarin.Forms.Platform.Resource.Attribute.hintAnimationEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.hintAnimationEnabled; + global::Xamarin.Forms.Platform.Resource.Attribute.hintEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.hintEnabled; + global::Xamarin.Forms.Platform.Resource.Attribute.hintTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.hintTextAppearance; + global::Xamarin.Forms.Platform.Resource.Attribute.homeAsUpIndicator = global::HelloworldXamarin.Droid.Resource.Attribute.homeAsUpIndicator; + global::Xamarin.Forms.Platform.Resource.Attribute.homeLayout = global::HelloworldXamarin.Droid.Resource.Attribute.homeLayout; + global::Xamarin.Forms.Platform.Resource.Attribute.hoveredFocusedTranslationZ = global::HelloworldXamarin.Droid.Resource.Attribute.hoveredFocusedTranslationZ; + global::Xamarin.Forms.Platform.Resource.Attribute.icon = global::HelloworldXamarin.Droid.Resource.Attribute.icon; + global::Xamarin.Forms.Platform.Resource.Attribute.iconEndPadding = global::HelloworldXamarin.Droid.Resource.Attribute.iconEndPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.iconGravity = global::HelloworldXamarin.Droid.Resource.Attribute.iconGravity; + global::Xamarin.Forms.Platform.Resource.Attribute.iconifiedByDefault = global::HelloworldXamarin.Droid.Resource.Attribute.iconifiedByDefault; + global::Xamarin.Forms.Platform.Resource.Attribute.iconPadding = global::HelloworldXamarin.Droid.Resource.Attribute.iconPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.iconSize = global::HelloworldXamarin.Droid.Resource.Attribute.iconSize; + global::Xamarin.Forms.Platform.Resource.Attribute.iconStartPadding = global::HelloworldXamarin.Droid.Resource.Attribute.iconStartPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.iconTint = global::HelloworldXamarin.Droid.Resource.Attribute.iconTint; + global::Xamarin.Forms.Platform.Resource.Attribute.iconTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.iconTintMode; + global::Xamarin.Forms.Platform.Resource.Attribute.imageButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.imageButtonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.indeterminateProgressStyle = global::HelloworldXamarin.Droid.Resource.Attribute.indeterminateProgressStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.initialActivityCount = global::HelloworldXamarin.Droid.Resource.Attribute.initialActivityCount; + global::Xamarin.Forms.Platform.Resource.Attribute.insetForeground = global::HelloworldXamarin.Droid.Resource.Attribute.insetForeground; + global::Xamarin.Forms.Platform.Resource.Attribute.isLightTheme = global::HelloworldXamarin.Droid.Resource.Attribute.isLightTheme; + global::Xamarin.Forms.Platform.Resource.Attribute.itemBackground = global::HelloworldXamarin.Droid.Resource.Attribute.itemBackground; + global::Xamarin.Forms.Platform.Resource.Attribute.itemHorizontalPadding = global::HelloworldXamarin.Droid.Resource.Attribute.itemHorizontalPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.itemHorizontalTranslationEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.itemHorizontalTranslationEnabled; + global::Xamarin.Forms.Platform.Resource.Attribute.itemIconPadding = global::HelloworldXamarin.Droid.Resource.Attribute.itemIconPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.itemIconSize = global::HelloworldXamarin.Droid.Resource.Attribute.itemIconSize; + global::Xamarin.Forms.Platform.Resource.Attribute.itemIconTint = global::HelloworldXamarin.Droid.Resource.Attribute.itemIconTint; + global::Xamarin.Forms.Platform.Resource.Attribute.itemPadding = global::HelloworldXamarin.Droid.Resource.Attribute.itemPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.itemSpacing = global::HelloworldXamarin.Droid.Resource.Attribute.itemSpacing; + global::Xamarin.Forms.Platform.Resource.Attribute.itemTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.itemTextAppearance; + global::Xamarin.Forms.Platform.Resource.Attribute.itemTextAppearanceActive = global::HelloworldXamarin.Droid.Resource.Attribute.itemTextAppearanceActive; + global::Xamarin.Forms.Platform.Resource.Attribute.itemTextAppearanceInactive = global::HelloworldXamarin.Droid.Resource.Attribute.itemTextAppearanceInactive; + global::Xamarin.Forms.Platform.Resource.Attribute.itemTextColor = global::HelloworldXamarin.Droid.Resource.Attribute.itemTextColor; + global::Xamarin.Forms.Platform.Resource.Attribute.keylines = global::HelloworldXamarin.Droid.Resource.Attribute.keylines; + global::Xamarin.Forms.Platform.Resource.Attribute.labelVisibilityMode = global::HelloworldXamarin.Droid.Resource.Attribute.labelVisibilityMode; + global::Xamarin.Forms.Platform.Resource.Attribute.lastBaselineToBottomHeight = global::HelloworldXamarin.Droid.Resource.Attribute.lastBaselineToBottomHeight; + global::Xamarin.Forms.Platform.Resource.Attribute.layout = global::HelloworldXamarin.Droid.Resource.Attribute.layout; + global::Xamarin.Forms.Platform.Resource.Attribute.layoutManager = global::HelloworldXamarin.Droid.Resource.Attribute.layoutManager; + global::Xamarin.Forms.Platform.Resource.Attribute.layout_anchor = global::HelloworldXamarin.Droid.Resource.Attribute.layout_anchor; + global::Xamarin.Forms.Platform.Resource.Attribute.layout_anchorGravity = global::HelloworldXamarin.Droid.Resource.Attribute.layout_anchorGravity; + global::Xamarin.Forms.Platform.Resource.Attribute.layout_behavior = global::HelloworldXamarin.Droid.Resource.Attribute.layout_behavior; + global::Xamarin.Forms.Platform.Resource.Attribute.layout_collapseMode = global::HelloworldXamarin.Droid.Resource.Attribute.layout_collapseMode; + global::Xamarin.Forms.Platform.Resource.Attribute.layout_collapseParallaxMultiplier = global::HelloworldXamarin.Droid.Resource.Attribute.layout_collapseParallaxMultiplier; + global::Xamarin.Forms.Platform.Resource.Attribute.layout_dodgeInsetEdges = global::HelloworldXamarin.Droid.Resource.Attribute.layout_dodgeInsetEdges; + global::Xamarin.Forms.Platform.Resource.Attribute.layout_insetEdge = global::HelloworldXamarin.Droid.Resource.Attribute.layout_insetEdge; + global::Xamarin.Forms.Platform.Resource.Attribute.layout_keyline = global::HelloworldXamarin.Droid.Resource.Attribute.layout_keyline; + global::Xamarin.Forms.Platform.Resource.Attribute.layout_scrollFlags = global::HelloworldXamarin.Droid.Resource.Attribute.layout_scrollFlags; + global::Xamarin.Forms.Platform.Resource.Attribute.layout_scrollInterpolator = global::HelloworldXamarin.Droid.Resource.Attribute.layout_scrollInterpolator; + global::Xamarin.Forms.Platform.Resource.Attribute.liftOnScroll = global::HelloworldXamarin.Droid.Resource.Attribute.liftOnScroll; + global::Xamarin.Forms.Platform.Resource.Attribute.lineHeight = global::HelloworldXamarin.Droid.Resource.Attribute.lineHeight; + global::Xamarin.Forms.Platform.Resource.Attribute.lineSpacing = global::HelloworldXamarin.Droid.Resource.Attribute.lineSpacing; + global::Xamarin.Forms.Platform.Resource.Attribute.listChoiceBackgroundIndicator = global::HelloworldXamarin.Droid.Resource.Attribute.listChoiceBackgroundIndicator; + global::Xamarin.Forms.Platform.Resource.Attribute.listDividerAlertDialog = global::HelloworldXamarin.Droid.Resource.Attribute.listDividerAlertDialog; + global::Xamarin.Forms.Platform.Resource.Attribute.listItemLayout = global::HelloworldXamarin.Droid.Resource.Attribute.listItemLayout; + global::Xamarin.Forms.Platform.Resource.Attribute.listLayout = global::HelloworldXamarin.Droid.Resource.Attribute.listLayout; + global::Xamarin.Forms.Platform.Resource.Attribute.listMenuViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.listMenuViewStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.listPopupWindowStyle = global::HelloworldXamarin.Droid.Resource.Attribute.listPopupWindowStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.listPreferredItemHeight = global::HelloworldXamarin.Droid.Resource.Attribute.listPreferredItemHeight; + global::Xamarin.Forms.Platform.Resource.Attribute.listPreferredItemHeightLarge = global::HelloworldXamarin.Droid.Resource.Attribute.listPreferredItemHeightLarge; + global::Xamarin.Forms.Platform.Resource.Attribute.listPreferredItemHeightSmall = global::HelloworldXamarin.Droid.Resource.Attribute.listPreferredItemHeightSmall; + global::Xamarin.Forms.Platform.Resource.Attribute.listPreferredItemPaddingLeft = global::HelloworldXamarin.Droid.Resource.Attribute.listPreferredItemPaddingLeft; + global::Xamarin.Forms.Platform.Resource.Attribute.listPreferredItemPaddingRight = global::HelloworldXamarin.Droid.Resource.Attribute.listPreferredItemPaddingRight; + global::Xamarin.Forms.Platform.Resource.Attribute.logo = global::HelloworldXamarin.Droid.Resource.Attribute.logo; + global::Xamarin.Forms.Platform.Resource.Attribute.logoDescription = global::HelloworldXamarin.Droid.Resource.Attribute.logoDescription; + global::Xamarin.Forms.Platform.Resource.Attribute.materialButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.materialButtonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.materialCardViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.materialCardViewStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.maxActionInlineWidth = global::HelloworldXamarin.Droid.Resource.Attribute.maxActionInlineWidth; + global::Xamarin.Forms.Platform.Resource.Attribute.maxButtonHeight = global::HelloworldXamarin.Droid.Resource.Attribute.maxButtonHeight; + global::Xamarin.Forms.Platform.Resource.Attribute.maxImageSize = global::HelloworldXamarin.Droid.Resource.Attribute.maxImageSize; + global::Xamarin.Forms.Platform.Resource.Attribute.measureWithLargestChild = global::HelloworldXamarin.Droid.Resource.Attribute.measureWithLargestChild; + global::Xamarin.Forms.Platform.Resource.Attribute.menu = global::HelloworldXamarin.Droid.Resource.Attribute.menu; + global::Xamarin.Forms.Platform.Resource.Attribute.multiChoiceItemLayout = global::HelloworldXamarin.Droid.Resource.Attribute.multiChoiceItemLayout; + global::Xamarin.Forms.Platform.Resource.Attribute.navigationContentDescription = global::HelloworldXamarin.Droid.Resource.Attribute.navigationContentDescription; + global::Xamarin.Forms.Platform.Resource.Attribute.navigationIcon = global::HelloworldXamarin.Droid.Resource.Attribute.navigationIcon; + global::Xamarin.Forms.Platform.Resource.Attribute.navigationMode = global::HelloworldXamarin.Droid.Resource.Attribute.navigationMode; + global::Xamarin.Forms.Platform.Resource.Attribute.navigationViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.navigationViewStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.numericModifiers = global::HelloworldXamarin.Droid.Resource.Attribute.numericModifiers; + global::Xamarin.Forms.Platform.Resource.Attribute.overlapAnchor = global::HelloworldXamarin.Droid.Resource.Attribute.overlapAnchor; + global::Xamarin.Forms.Platform.Resource.Attribute.paddingBottomNoButtons = global::HelloworldXamarin.Droid.Resource.Attribute.paddingBottomNoButtons; + global::Xamarin.Forms.Platform.Resource.Attribute.paddingEnd = global::HelloworldXamarin.Droid.Resource.Attribute.paddingEnd; + global::Xamarin.Forms.Platform.Resource.Attribute.paddingStart = global::HelloworldXamarin.Droid.Resource.Attribute.paddingStart; + global::Xamarin.Forms.Platform.Resource.Attribute.paddingTopNoTitle = global::HelloworldXamarin.Droid.Resource.Attribute.paddingTopNoTitle; + global::Xamarin.Forms.Platform.Resource.Attribute.panelBackground = global::HelloworldXamarin.Droid.Resource.Attribute.panelBackground; + global::Xamarin.Forms.Platform.Resource.Attribute.panelMenuListTheme = global::HelloworldXamarin.Droid.Resource.Attribute.panelMenuListTheme; + global::Xamarin.Forms.Platform.Resource.Attribute.panelMenuListWidth = global::HelloworldXamarin.Droid.Resource.Attribute.panelMenuListWidth; + global::Xamarin.Forms.Platform.Resource.Attribute.passwordToggleContentDescription = global::HelloworldXamarin.Droid.Resource.Attribute.passwordToggleContentDescription; + global::Xamarin.Forms.Platform.Resource.Attribute.passwordToggleDrawable = global::HelloworldXamarin.Droid.Resource.Attribute.passwordToggleDrawable; + global::Xamarin.Forms.Platform.Resource.Attribute.passwordToggleEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.passwordToggleEnabled; + global::Xamarin.Forms.Platform.Resource.Attribute.passwordToggleTint = global::HelloworldXamarin.Droid.Resource.Attribute.passwordToggleTint; + global::Xamarin.Forms.Platform.Resource.Attribute.passwordToggleTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.passwordToggleTintMode; + global::Xamarin.Forms.Platform.Resource.Attribute.popupMenuStyle = global::HelloworldXamarin.Droid.Resource.Attribute.popupMenuStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.popupTheme = global::HelloworldXamarin.Droid.Resource.Attribute.popupTheme; + global::Xamarin.Forms.Platform.Resource.Attribute.popupWindowStyle = global::HelloworldXamarin.Droid.Resource.Attribute.popupWindowStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.preserveIconSpacing = global::HelloworldXamarin.Droid.Resource.Attribute.preserveIconSpacing; + global::Xamarin.Forms.Platform.Resource.Attribute.pressedTranslationZ = global::HelloworldXamarin.Droid.Resource.Attribute.pressedTranslationZ; + global::Xamarin.Forms.Platform.Resource.Attribute.progressBarPadding = global::HelloworldXamarin.Droid.Resource.Attribute.progressBarPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.progressBarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.progressBarStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.queryBackground = global::HelloworldXamarin.Droid.Resource.Attribute.queryBackground; + global::Xamarin.Forms.Platform.Resource.Attribute.queryHint = global::HelloworldXamarin.Droid.Resource.Attribute.queryHint; + global::Xamarin.Forms.Platform.Resource.Attribute.radioButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.radioButtonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.ratingBarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.ratingBarStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.ratingBarStyleIndicator = global::HelloworldXamarin.Droid.Resource.Attribute.ratingBarStyleIndicator; + global::Xamarin.Forms.Platform.Resource.Attribute.ratingBarStyleSmall = global::HelloworldXamarin.Droid.Resource.Attribute.ratingBarStyleSmall; + global::Xamarin.Forms.Platform.Resource.Attribute.reverseLayout = global::HelloworldXamarin.Droid.Resource.Attribute.reverseLayout; + global::Xamarin.Forms.Platform.Resource.Attribute.rippleColor = global::HelloworldXamarin.Droid.Resource.Attribute.rippleColor; + global::Xamarin.Forms.Platform.Resource.Attribute.scrimAnimationDuration = global::HelloworldXamarin.Droid.Resource.Attribute.scrimAnimationDuration; + global::Xamarin.Forms.Platform.Resource.Attribute.scrimBackground = global::HelloworldXamarin.Droid.Resource.Attribute.scrimBackground; + global::Xamarin.Forms.Platform.Resource.Attribute.scrimVisibleHeightTrigger = global::HelloworldXamarin.Droid.Resource.Attribute.scrimVisibleHeightTrigger; + global::Xamarin.Forms.Platform.Resource.Attribute.searchHintIcon = global::HelloworldXamarin.Droid.Resource.Attribute.searchHintIcon; + global::Xamarin.Forms.Platform.Resource.Attribute.searchIcon = global::HelloworldXamarin.Droid.Resource.Attribute.searchIcon; + global::Xamarin.Forms.Platform.Resource.Attribute.searchViewStyle = global::HelloworldXamarin.Droid.Resource.Attribute.searchViewStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.seekBarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.seekBarStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.selectableItemBackground = global::HelloworldXamarin.Droid.Resource.Attribute.selectableItemBackground; + global::Xamarin.Forms.Platform.Resource.Attribute.selectableItemBackgroundBorderless = global::HelloworldXamarin.Droid.Resource.Attribute.selectableItemBackgroundBorderless; + global::Xamarin.Forms.Platform.Resource.Attribute.showAsAction = global::HelloworldXamarin.Droid.Resource.Attribute.showAsAction; + global::Xamarin.Forms.Platform.Resource.Attribute.showDividers = global::HelloworldXamarin.Droid.Resource.Attribute.showDividers; + global::Xamarin.Forms.Platform.Resource.Attribute.showMotionSpec = global::HelloworldXamarin.Droid.Resource.Attribute.showMotionSpec; + global::Xamarin.Forms.Platform.Resource.Attribute.showText = global::HelloworldXamarin.Droid.Resource.Attribute.showText; + global::Xamarin.Forms.Platform.Resource.Attribute.showTitle = global::HelloworldXamarin.Droid.Resource.Attribute.showTitle; + global::Xamarin.Forms.Platform.Resource.Attribute.singleChoiceItemLayout = global::HelloworldXamarin.Droid.Resource.Attribute.singleChoiceItemLayout; + global::Xamarin.Forms.Platform.Resource.Attribute.singleLine = global::HelloworldXamarin.Droid.Resource.Attribute.singleLine; + global::Xamarin.Forms.Platform.Resource.Attribute.singleSelection = global::HelloworldXamarin.Droid.Resource.Attribute.singleSelection; + global::Xamarin.Forms.Platform.Resource.Attribute.snackbarButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.snackbarButtonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.snackbarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.snackbarStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.spanCount = global::HelloworldXamarin.Droid.Resource.Attribute.spanCount; + global::Xamarin.Forms.Platform.Resource.Attribute.spinBars = global::HelloworldXamarin.Droid.Resource.Attribute.spinBars; + global::Xamarin.Forms.Platform.Resource.Attribute.spinnerDropDownItemStyle = global::HelloworldXamarin.Droid.Resource.Attribute.spinnerDropDownItemStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.spinnerStyle = global::HelloworldXamarin.Droid.Resource.Attribute.spinnerStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.splitTrack = global::HelloworldXamarin.Droid.Resource.Attribute.splitTrack; + global::Xamarin.Forms.Platform.Resource.Attribute.srcCompat = global::HelloworldXamarin.Droid.Resource.Attribute.srcCompat; + global::Xamarin.Forms.Platform.Resource.Attribute.stackFromEnd = global::HelloworldXamarin.Droid.Resource.Attribute.stackFromEnd; + global::Xamarin.Forms.Platform.Resource.Attribute.state_above_anchor = global::HelloworldXamarin.Droid.Resource.Attribute.state_above_anchor; + global::Xamarin.Forms.Platform.Resource.Attribute.state_collapsed = global::HelloworldXamarin.Droid.Resource.Attribute.state_collapsed; + global::Xamarin.Forms.Platform.Resource.Attribute.state_collapsible = global::HelloworldXamarin.Droid.Resource.Attribute.state_collapsible; + global::Xamarin.Forms.Platform.Resource.Attribute.state_liftable = global::HelloworldXamarin.Droid.Resource.Attribute.state_liftable; + global::Xamarin.Forms.Platform.Resource.Attribute.state_lifted = global::HelloworldXamarin.Droid.Resource.Attribute.state_lifted; + global::Xamarin.Forms.Platform.Resource.Attribute.statusBarBackground = global::HelloworldXamarin.Droid.Resource.Attribute.statusBarBackground; + global::Xamarin.Forms.Platform.Resource.Attribute.statusBarScrim = global::HelloworldXamarin.Droid.Resource.Attribute.statusBarScrim; + global::Xamarin.Forms.Platform.Resource.Attribute.strokeColor = global::HelloworldXamarin.Droid.Resource.Attribute.strokeColor; + global::Xamarin.Forms.Platform.Resource.Attribute.strokeWidth = global::HelloworldXamarin.Droid.Resource.Attribute.strokeWidth; + global::Xamarin.Forms.Platform.Resource.Attribute.subMenuArrow = global::HelloworldXamarin.Droid.Resource.Attribute.subMenuArrow; + global::Xamarin.Forms.Platform.Resource.Attribute.submitBackground = global::HelloworldXamarin.Droid.Resource.Attribute.submitBackground; + global::Xamarin.Forms.Platform.Resource.Attribute.subtitle = global::HelloworldXamarin.Droid.Resource.Attribute.subtitle; + global::Xamarin.Forms.Platform.Resource.Attribute.subtitleTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.subtitleTextAppearance; + global::Xamarin.Forms.Platform.Resource.Attribute.subtitleTextColor = global::HelloworldXamarin.Droid.Resource.Attribute.subtitleTextColor; + global::Xamarin.Forms.Platform.Resource.Attribute.subtitleTextStyle = global::HelloworldXamarin.Droid.Resource.Attribute.subtitleTextStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.suggestionRowLayout = global::HelloworldXamarin.Droid.Resource.Attribute.suggestionRowLayout; + global::Xamarin.Forms.Platform.Resource.Attribute.switchMinWidth = global::HelloworldXamarin.Droid.Resource.Attribute.switchMinWidth; + global::Xamarin.Forms.Platform.Resource.Attribute.switchPadding = global::HelloworldXamarin.Droid.Resource.Attribute.switchPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.switchStyle = global::HelloworldXamarin.Droid.Resource.Attribute.switchStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.switchTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.switchTextAppearance; + global::Xamarin.Forms.Platform.Resource.Attribute.tabBackground = global::HelloworldXamarin.Droid.Resource.Attribute.tabBackground; + global::Xamarin.Forms.Platform.Resource.Attribute.tabContentStart = global::HelloworldXamarin.Droid.Resource.Attribute.tabContentStart; + global::Xamarin.Forms.Platform.Resource.Attribute.tabGravity = global::HelloworldXamarin.Droid.Resource.Attribute.tabGravity; + global::Xamarin.Forms.Platform.Resource.Attribute.tabIconTint = global::HelloworldXamarin.Droid.Resource.Attribute.tabIconTint; + global::Xamarin.Forms.Platform.Resource.Attribute.tabIconTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.tabIconTintMode; + global::Xamarin.Forms.Platform.Resource.Attribute.tabIndicator = global::HelloworldXamarin.Droid.Resource.Attribute.tabIndicator; + global::Xamarin.Forms.Platform.Resource.Attribute.tabIndicatorAnimationDuration = global::HelloworldXamarin.Droid.Resource.Attribute.tabIndicatorAnimationDuration; + global::Xamarin.Forms.Platform.Resource.Attribute.tabIndicatorColor = global::HelloworldXamarin.Droid.Resource.Attribute.tabIndicatorColor; + global::Xamarin.Forms.Platform.Resource.Attribute.tabIndicatorFullWidth = global::HelloworldXamarin.Droid.Resource.Attribute.tabIndicatorFullWidth; + global::Xamarin.Forms.Platform.Resource.Attribute.tabIndicatorGravity = global::HelloworldXamarin.Droid.Resource.Attribute.tabIndicatorGravity; + global::Xamarin.Forms.Platform.Resource.Attribute.tabIndicatorHeight = global::HelloworldXamarin.Droid.Resource.Attribute.tabIndicatorHeight; + global::Xamarin.Forms.Platform.Resource.Attribute.tabInlineLabel = global::HelloworldXamarin.Droid.Resource.Attribute.tabInlineLabel; + global::Xamarin.Forms.Platform.Resource.Attribute.tabMaxWidth = global::HelloworldXamarin.Droid.Resource.Attribute.tabMaxWidth; + global::Xamarin.Forms.Platform.Resource.Attribute.tabMinWidth = global::HelloworldXamarin.Droid.Resource.Attribute.tabMinWidth; + global::Xamarin.Forms.Platform.Resource.Attribute.tabMode = global::HelloworldXamarin.Droid.Resource.Attribute.tabMode; + global::Xamarin.Forms.Platform.Resource.Attribute.tabPadding = global::HelloworldXamarin.Droid.Resource.Attribute.tabPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.tabPaddingBottom = global::HelloworldXamarin.Droid.Resource.Attribute.tabPaddingBottom; + global::Xamarin.Forms.Platform.Resource.Attribute.tabPaddingEnd = global::HelloworldXamarin.Droid.Resource.Attribute.tabPaddingEnd; + global::Xamarin.Forms.Platform.Resource.Attribute.tabPaddingStart = global::HelloworldXamarin.Droid.Resource.Attribute.tabPaddingStart; + global::Xamarin.Forms.Platform.Resource.Attribute.tabPaddingTop = global::HelloworldXamarin.Droid.Resource.Attribute.tabPaddingTop; + global::Xamarin.Forms.Platform.Resource.Attribute.tabRippleColor = global::HelloworldXamarin.Droid.Resource.Attribute.tabRippleColor; + global::Xamarin.Forms.Platform.Resource.Attribute.tabSelectedTextColor = global::HelloworldXamarin.Droid.Resource.Attribute.tabSelectedTextColor; + global::Xamarin.Forms.Platform.Resource.Attribute.tabStyle = global::HelloworldXamarin.Droid.Resource.Attribute.tabStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.tabTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.tabTextAppearance; + global::Xamarin.Forms.Platform.Resource.Attribute.tabTextColor = global::HelloworldXamarin.Droid.Resource.Attribute.tabTextColor; + global::Xamarin.Forms.Platform.Resource.Attribute.tabUnboundedRipple = global::HelloworldXamarin.Droid.Resource.Attribute.tabUnboundedRipple; + global::Xamarin.Forms.Platform.Resource.Attribute.textAllCaps = global::HelloworldXamarin.Droid.Resource.Attribute.textAllCaps; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceBody1 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceBody1; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceBody2 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceBody2; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceButton = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceButton; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceCaption = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceCaption; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceHeadline1 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceHeadline1; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceHeadline2 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceHeadline2; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceHeadline3 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceHeadline3; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceHeadline4 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceHeadline4; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceHeadline5 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceHeadline5; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceHeadline6 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceHeadline6; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceLargePopupMenu = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceLargePopupMenu; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceListItem = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceListItem; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceListItemSecondary = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceListItemSecondary; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceListItemSmall = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceListItemSmall; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceOverline = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceOverline; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearancePopupMenuHeader = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearancePopupMenuHeader; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceSearchResultSubtitle = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceSearchResultSubtitle; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceSearchResultTitle = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceSearchResultTitle; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceSmallPopupMenu = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceSmallPopupMenu; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceSubtitle1 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceSubtitle1; + global::Xamarin.Forms.Platform.Resource.Attribute.textAppearanceSubtitle2 = global::HelloworldXamarin.Droid.Resource.Attribute.textAppearanceSubtitle2; + global::Xamarin.Forms.Platform.Resource.Attribute.textColorAlertDialogListItem = global::HelloworldXamarin.Droid.Resource.Attribute.textColorAlertDialogListItem; + global::Xamarin.Forms.Platform.Resource.Attribute.textColorSearchUrl = global::HelloworldXamarin.Droid.Resource.Attribute.textColorSearchUrl; + global::Xamarin.Forms.Platform.Resource.Attribute.textEndPadding = global::HelloworldXamarin.Droid.Resource.Attribute.textEndPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.textInputStyle = global::HelloworldXamarin.Droid.Resource.Attribute.textInputStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.textStartPadding = global::HelloworldXamarin.Droid.Resource.Attribute.textStartPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.theme = global::HelloworldXamarin.Droid.Resource.Attribute.theme; + global::Xamarin.Forms.Platform.Resource.Attribute.thickness = global::HelloworldXamarin.Droid.Resource.Attribute.thickness; + global::Xamarin.Forms.Platform.Resource.Attribute.thumbTextPadding = global::HelloworldXamarin.Droid.Resource.Attribute.thumbTextPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.thumbTint = global::HelloworldXamarin.Droid.Resource.Attribute.thumbTint; + global::Xamarin.Forms.Platform.Resource.Attribute.thumbTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.thumbTintMode; + global::Xamarin.Forms.Platform.Resource.Attribute.tickMark = global::HelloworldXamarin.Droid.Resource.Attribute.tickMark; + global::Xamarin.Forms.Platform.Resource.Attribute.tickMarkTint = global::HelloworldXamarin.Droid.Resource.Attribute.tickMarkTint; + global::Xamarin.Forms.Platform.Resource.Attribute.tickMarkTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.tickMarkTintMode; + global::Xamarin.Forms.Platform.Resource.Attribute.tint = global::HelloworldXamarin.Droid.Resource.Attribute.tint; + global::Xamarin.Forms.Platform.Resource.Attribute.tintMode = global::HelloworldXamarin.Droid.Resource.Attribute.tintMode; + global::Xamarin.Forms.Platform.Resource.Attribute.title = global::HelloworldXamarin.Droid.Resource.Attribute.title; + global::Xamarin.Forms.Platform.Resource.Attribute.titleEnabled = global::HelloworldXamarin.Droid.Resource.Attribute.titleEnabled; + global::Xamarin.Forms.Platform.Resource.Attribute.titleMargin = global::HelloworldXamarin.Droid.Resource.Attribute.titleMargin; + global::Xamarin.Forms.Platform.Resource.Attribute.titleMarginBottom = global::HelloworldXamarin.Droid.Resource.Attribute.titleMarginBottom; + global::Xamarin.Forms.Platform.Resource.Attribute.titleMarginEnd = global::HelloworldXamarin.Droid.Resource.Attribute.titleMarginEnd; + global::Xamarin.Forms.Platform.Resource.Attribute.titleMargins = global::HelloworldXamarin.Droid.Resource.Attribute.titleMargins; + global::Xamarin.Forms.Platform.Resource.Attribute.titleMarginStart = global::HelloworldXamarin.Droid.Resource.Attribute.titleMarginStart; + global::Xamarin.Forms.Platform.Resource.Attribute.titleMarginTop = global::HelloworldXamarin.Droid.Resource.Attribute.titleMarginTop; + global::Xamarin.Forms.Platform.Resource.Attribute.titleTextAppearance = global::HelloworldXamarin.Droid.Resource.Attribute.titleTextAppearance; + global::Xamarin.Forms.Platform.Resource.Attribute.titleTextColor = global::HelloworldXamarin.Droid.Resource.Attribute.titleTextColor; + global::Xamarin.Forms.Platform.Resource.Attribute.titleTextStyle = global::HelloworldXamarin.Droid.Resource.Attribute.titleTextStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.toolbarId = global::HelloworldXamarin.Droid.Resource.Attribute.toolbarId; + global::Xamarin.Forms.Platform.Resource.Attribute.toolbarNavigationButtonStyle = global::HelloworldXamarin.Droid.Resource.Attribute.toolbarNavigationButtonStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.toolbarStyle = global::HelloworldXamarin.Droid.Resource.Attribute.toolbarStyle; + global::Xamarin.Forms.Platform.Resource.Attribute.tooltipForegroundColor = global::HelloworldXamarin.Droid.Resource.Attribute.tooltipForegroundColor; + global::Xamarin.Forms.Platform.Resource.Attribute.tooltipFrameBackground = global::HelloworldXamarin.Droid.Resource.Attribute.tooltipFrameBackground; + global::Xamarin.Forms.Platform.Resource.Attribute.tooltipText = global::HelloworldXamarin.Droid.Resource.Attribute.tooltipText; + global::Xamarin.Forms.Platform.Resource.Attribute.track = global::HelloworldXamarin.Droid.Resource.Attribute.track; + global::Xamarin.Forms.Platform.Resource.Attribute.trackTint = global::HelloworldXamarin.Droid.Resource.Attribute.trackTint; + global::Xamarin.Forms.Platform.Resource.Attribute.trackTintMode = global::HelloworldXamarin.Droid.Resource.Attribute.trackTintMode; + global::Xamarin.Forms.Platform.Resource.Attribute.ttcIndex = global::HelloworldXamarin.Droid.Resource.Attribute.ttcIndex; + global::Xamarin.Forms.Platform.Resource.Attribute.useCompatPadding = global::HelloworldXamarin.Droid.Resource.Attribute.useCompatPadding; + global::Xamarin.Forms.Platform.Resource.Attribute.viewInflaterClass = global::HelloworldXamarin.Droid.Resource.Attribute.viewInflaterClass; + global::Xamarin.Forms.Platform.Resource.Attribute.voiceIcon = global::HelloworldXamarin.Droid.Resource.Attribute.voiceIcon; + global::Xamarin.Forms.Platform.Resource.Attribute.windowActionBar = global::HelloworldXamarin.Droid.Resource.Attribute.windowActionBar; + global::Xamarin.Forms.Platform.Resource.Attribute.windowActionBarOverlay = global::HelloworldXamarin.Droid.Resource.Attribute.windowActionBarOverlay; + global::Xamarin.Forms.Platform.Resource.Attribute.windowActionModeOverlay = global::HelloworldXamarin.Droid.Resource.Attribute.windowActionModeOverlay; + global::Xamarin.Forms.Platform.Resource.Attribute.windowFixedHeightMajor = global::HelloworldXamarin.Droid.Resource.Attribute.windowFixedHeightMajor; + global::Xamarin.Forms.Platform.Resource.Attribute.windowFixedHeightMinor = global::HelloworldXamarin.Droid.Resource.Attribute.windowFixedHeightMinor; + global::Xamarin.Forms.Platform.Resource.Attribute.windowFixedWidthMajor = global::HelloworldXamarin.Droid.Resource.Attribute.windowFixedWidthMajor; + global::Xamarin.Forms.Platform.Resource.Attribute.windowFixedWidthMinor = global::HelloworldXamarin.Droid.Resource.Attribute.windowFixedWidthMinor; + global::Xamarin.Forms.Platform.Resource.Attribute.windowMinWidthMajor = global::HelloworldXamarin.Droid.Resource.Attribute.windowMinWidthMajor; + global::Xamarin.Forms.Platform.Resource.Attribute.windowMinWidthMinor = global::HelloworldXamarin.Droid.Resource.Attribute.windowMinWidthMinor; + global::Xamarin.Forms.Platform.Resource.Attribute.windowNoTitle = global::HelloworldXamarin.Droid.Resource.Attribute.windowNoTitle; + global::Xamarin.Forms.Platform.Resource.Boolean.abc_action_bar_embed_tabs = global::HelloworldXamarin.Droid.Resource.Boolean.abc_action_bar_embed_tabs; + global::Xamarin.Forms.Platform.Resource.Boolean.abc_allow_stacked_button_bar = global::HelloworldXamarin.Droid.Resource.Boolean.abc_allow_stacked_button_bar; + global::Xamarin.Forms.Platform.Resource.Boolean.abc_config_actionMenuItemAllCaps = global::HelloworldXamarin.Droid.Resource.Boolean.abc_config_actionMenuItemAllCaps; + global::Xamarin.Forms.Platform.Resource.Boolean.mtrl_btn_textappearance_all_caps = global::HelloworldXamarin.Droid.Resource.Boolean.mtrl_btn_textappearance_all_caps; + global::Xamarin.Forms.Platform.Resource.Color.abc_background_cache_hint_selector_material_dark = global::HelloworldXamarin.Droid.Resource.Color.abc_background_cache_hint_selector_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.abc_background_cache_hint_selector_material_light = global::HelloworldXamarin.Droid.Resource.Color.abc_background_cache_hint_selector_material_light; + global::Xamarin.Forms.Platform.Resource.Color.abc_btn_colored_borderless_text_material = global::HelloworldXamarin.Droid.Resource.Color.abc_btn_colored_borderless_text_material; + global::Xamarin.Forms.Platform.Resource.Color.abc_btn_colored_text_material = global::HelloworldXamarin.Droid.Resource.Color.abc_btn_colored_text_material; + global::Xamarin.Forms.Platform.Resource.Color.abc_color_highlight_material = global::HelloworldXamarin.Droid.Resource.Color.abc_color_highlight_material; + global::Xamarin.Forms.Platform.Resource.Color.abc_hint_foreground_material_dark = global::HelloworldXamarin.Droid.Resource.Color.abc_hint_foreground_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.abc_hint_foreground_material_light = global::HelloworldXamarin.Droid.Resource.Color.abc_hint_foreground_material_light; + global::Xamarin.Forms.Platform.Resource.Color.abc_input_method_navigation_guard = global::HelloworldXamarin.Droid.Resource.Color.abc_input_method_navigation_guard; + global::Xamarin.Forms.Platform.Resource.Color.abc_primary_text_disable_only_material_dark = global::HelloworldXamarin.Droid.Resource.Color.abc_primary_text_disable_only_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.abc_primary_text_disable_only_material_light = global::HelloworldXamarin.Droid.Resource.Color.abc_primary_text_disable_only_material_light; + global::Xamarin.Forms.Platform.Resource.Color.abc_primary_text_material_dark = global::HelloworldXamarin.Droid.Resource.Color.abc_primary_text_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.abc_primary_text_material_light = global::HelloworldXamarin.Droid.Resource.Color.abc_primary_text_material_light; + global::Xamarin.Forms.Platform.Resource.Color.abc_search_url_text = global::HelloworldXamarin.Droid.Resource.Color.abc_search_url_text; + global::Xamarin.Forms.Platform.Resource.Color.abc_search_url_text_normal = global::HelloworldXamarin.Droid.Resource.Color.abc_search_url_text_normal; + global::Xamarin.Forms.Platform.Resource.Color.abc_search_url_text_pressed = global::HelloworldXamarin.Droid.Resource.Color.abc_search_url_text_pressed; + global::Xamarin.Forms.Platform.Resource.Color.abc_search_url_text_selected = global::HelloworldXamarin.Droid.Resource.Color.abc_search_url_text_selected; + global::Xamarin.Forms.Platform.Resource.Color.abc_secondary_text_material_dark = global::HelloworldXamarin.Droid.Resource.Color.abc_secondary_text_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.abc_secondary_text_material_light = global::HelloworldXamarin.Droid.Resource.Color.abc_secondary_text_material_light; + global::Xamarin.Forms.Platform.Resource.Color.abc_tint_btn_checkable = global::HelloworldXamarin.Droid.Resource.Color.abc_tint_btn_checkable; + global::Xamarin.Forms.Platform.Resource.Color.abc_tint_default = global::HelloworldXamarin.Droid.Resource.Color.abc_tint_default; + global::Xamarin.Forms.Platform.Resource.Color.abc_tint_edittext = global::HelloworldXamarin.Droid.Resource.Color.abc_tint_edittext; + global::Xamarin.Forms.Platform.Resource.Color.abc_tint_seek_thumb = global::HelloworldXamarin.Droid.Resource.Color.abc_tint_seek_thumb; + global::Xamarin.Forms.Platform.Resource.Color.abc_tint_spinner = global::HelloworldXamarin.Droid.Resource.Color.abc_tint_spinner; + global::Xamarin.Forms.Platform.Resource.Color.abc_tint_switch_track = global::HelloworldXamarin.Droid.Resource.Color.abc_tint_switch_track; + global::Xamarin.Forms.Platform.Resource.Color.accent_material_dark = global::HelloworldXamarin.Droid.Resource.Color.accent_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.accent_material_light = global::HelloworldXamarin.Droid.Resource.Color.accent_material_light; + global::Xamarin.Forms.Platform.Resource.Color.background_floating_material_dark = global::HelloworldXamarin.Droid.Resource.Color.background_floating_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.background_floating_material_light = global::HelloworldXamarin.Droid.Resource.Color.background_floating_material_light; + global::Xamarin.Forms.Platform.Resource.Color.background_material_dark = global::HelloworldXamarin.Droid.Resource.Color.background_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.background_material_light = global::HelloworldXamarin.Droid.Resource.Color.background_material_light; + global::Xamarin.Forms.Platform.Resource.Color.bright_foreground_disabled_material_dark = global::HelloworldXamarin.Droid.Resource.Color.bright_foreground_disabled_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.bright_foreground_disabled_material_light = global::HelloworldXamarin.Droid.Resource.Color.bright_foreground_disabled_material_light; + global::Xamarin.Forms.Platform.Resource.Color.bright_foreground_inverse_material_dark = global::HelloworldXamarin.Droid.Resource.Color.bright_foreground_inverse_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.bright_foreground_inverse_material_light = global::HelloworldXamarin.Droid.Resource.Color.bright_foreground_inverse_material_light; + global::Xamarin.Forms.Platform.Resource.Color.bright_foreground_material_dark = global::HelloworldXamarin.Droid.Resource.Color.bright_foreground_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.bright_foreground_material_light = global::HelloworldXamarin.Droid.Resource.Color.bright_foreground_material_light; + global::Xamarin.Forms.Platform.Resource.Color.button_material_dark = global::HelloworldXamarin.Droid.Resource.Color.button_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.button_material_light = global::HelloworldXamarin.Droid.Resource.Color.button_material_light; + global::Xamarin.Forms.Platform.Resource.Color.cardview_dark_background = global::HelloworldXamarin.Droid.Resource.Color.cardview_dark_background; + global::Xamarin.Forms.Platform.Resource.Color.cardview_light_background = global::HelloworldXamarin.Droid.Resource.Color.cardview_light_background; + global::Xamarin.Forms.Platform.Resource.Color.cardview_shadow_end_color = global::HelloworldXamarin.Droid.Resource.Color.cardview_shadow_end_color; + global::Xamarin.Forms.Platform.Resource.Color.cardview_shadow_start_color = global::HelloworldXamarin.Droid.Resource.Color.cardview_shadow_start_color; + global::Xamarin.Forms.Platform.Resource.Color.design_bottom_navigation_shadow_color = global::HelloworldXamarin.Droid.Resource.Color.design_bottom_navigation_shadow_color; + global::Xamarin.Forms.Platform.Resource.Color.design_default_color_primary = global::HelloworldXamarin.Droid.Resource.Color.design_default_color_primary; + global::Xamarin.Forms.Platform.Resource.Color.design_default_color_primary_dark = global::HelloworldXamarin.Droid.Resource.Color.design_default_color_primary_dark; + global::Xamarin.Forms.Platform.Resource.Color.design_error = global::HelloworldXamarin.Droid.Resource.Color.design_error; + global::Xamarin.Forms.Platform.Resource.Color.design_fab_shadow_end_color = global::HelloworldXamarin.Droid.Resource.Color.design_fab_shadow_end_color; + global::Xamarin.Forms.Platform.Resource.Color.design_fab_shadow_mid_color = global::HelloworldXamarin.Droid.Resource.Color.design_fab_shadow_mid_color; + global::Xamarin.Forms.Platform.Resource.Color.design_fab_shadow_start_color = global::HelloworldXamarin.Droid.Resource.Color.design_fab_shadow_start_color; + global::Xamarin.Forms.Platform.Resource.Color.design_fab_stroke_end_inner_color = global::HelloworldXamarin.Droid.Resource.Color.design_fab_stroke_end_inner_color; + global::Xamarin.Forms.Platform.Resource.Color.design_fab_stroke_end_outer_color = global::HelloworldXamarin.Droid.Resource.Color.design_fab_stroke_end_outer_color; + global::Xamarin.Forms.Platform.Resource.Color.design_fab_stroke_top_inner_color = global::HelloworldXamarin.Droid.Resource.Color.design_fab_stroke_top_inner_color; + global::Xamarin.Forms.Platform.Resource.Color.design_fab_stroke_top_outer_color = global::HelloworldXamarin.Droid.Resource.Color.design_fab_stroke_top_outer_color; + global::Xamarin.Forms.Platform.Resource.Color.design_snackbar_background_color = global::HelloworldXamarin.Droid.Resource.Color.design_snackbar_background_color; + global::Xamarin.Forms.Platform.Resource.Color.design_tint_password_toggle = global::HelloworldXamarin.Droid.Resource.Color.design_tint_password_toggle; + global::Xamarin.Forms.Platform.Resource.Color.dim_foreground_disabled_material_dark = global::HelloworldXamarin.Droid.Resource.Color.dim_foreground_disabled_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.dim_foreground_disabled_material_light = global::HelloworldXamarin.Droid.Resource.Color.dim_foreground_disabled_material_light; + global::Xamarin.Forms.Platform.Resource.Color.dim_foreground_material_dark = global::HelloworldXamarin.Droid.Resource.Color.dim_foreground_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.dim_foreground_material_light = global::HelloworldXamarin.Droid.Resource.Color.dim_foreground_material_light; + global::Xamarin.Forms.Platform.Resource.Color.error_color_material_dark = global::HelloworldXamarin.Droid.Resource.Color.error_color_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.error_color_material_light = global::HelloworldXamarin.Droid.Resource.Color.error_color_material_light; + global::Xamarin.Forms.Platform.Resource.Color.foreground_material_dark = global::HelloworldXamarin.Droid.Resource.Color.foreground_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.foreground_material_light = global::HelloworldXamarin.Droid.Resource.Color.foreground_material_light; + global::Xamarin.Forms.Platform.Resource.Color.highlighted_text_material_dark = global::HelloworldXamarin.Droid.Resource.Color.highlighted_text_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.highlighted_text_material_light = global::HelloworldXamarin.Droid.Resource.Color.highlighted_text_material_light; + global::Xamarin.Forms.Platform.Resource.Color.material_blue_grey_800 = global::HelloworldXamarin.Droid.Resource.Color.material_blue_grey_800; + global::Xamarin.Forms.Platform.Resource.Color.material_blue_grey_900 = global::HelloworldXamarin.Droid.Resource.Color.material_blue_grey_900; + global::Xamarin.Forms.Platform.Resource.Color.material_blue_grey_950 = global::HelloworldXamarin.Droid.Resource.Color.material_blue_grey_950; + global::Xamarin.Forms.Platform.Resource.Color.material_deep_teal_200 = global::HelloworldXamarin.Droid.Resource.Color.material_deep_teal_200; + global::Xamarin.Forms.Platform.Resource.Color.material_deep_teal_500 = global::HelloworldXamarin.Droid.Resource.Color.material_deep_teal_500; + global::Xamarin.Forms.Platform.Resource.Color.material_grey_100 = global::HelloworldXamarin.Droid.Resource.Color.material_grey_100; + global::Xamarin.Forms.Platform.Resource.Color.material_grey_300 = global::HelloworldXamarin.Droid.Resource.Color.material_grey_300; + global::Xamarin.Forms.Platform.Resource.Color.material_grey_50 = global::HelloworldXamarin.Droid.Resource.Color.material_grey_50; + global::Xamarin.Forms.Platform.Resource.Color.material_grey_600 = global::HelloworldXamarin.Droid.Resource.Color.material_grey_600; + global::Xamarin.Forms.Platform.Resource.Color.material_grey_800 = global::HelloworldXamarin.Droid.Resource.Color.material_grey_800; + global::Xamarin.Forms.Platform.Resource.Color.material_grey_850 = global::HelloworldXamarin.Droid.Resource.Color.material_grey_850; + global::Xamarin.Forms.Platform.Resource.Color.material_grey_900 = global::HelloworldXamarin.Droid.Resource.Color.material_grey_900; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_bottom_nav_colored_item_tint = global::HelloworldXamarin.Droid.Resource.Color.mtrl_bottom_nav_colored_item_tint; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_bottom_nav_item_tint = global::HelloworldXamarin.Droid.Resource.Color.mtrl_bottom_nav_item_tint; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_bg_color_disabled = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_bg_color_disabled; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_bg_color_selector = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_bg_color_selector; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_ripple_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_ripple_color; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_stroke_color_selector = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_stroke_color_selector; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_text_btn_ripple_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_text_btn_ripple_color; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_text_color_disabled = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_text_color_disabled; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_text_color_selector = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_text_color_selector; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_btn_transparent_bg_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_btn_transparent_bg_color; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_chip_background_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_chip_background_color; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_chip_close_icon_tint = global::HelloworldXamarin.Droid.Resource.Color.mtrl_chip_close_icon_tint; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_chip_ripple_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_chip_ripple_color; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_chip_text_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_chip_text_color; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_fab_ripple_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_fab_ripple_color; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_scrim_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_scrim_color; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_tabs_colored_ripple_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_tabs_colored_ripple_color; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_tabs_icon_color_selector = global::HelloworldXamarin.Droid.Resource.Color.mtrl_tabs_icon_color_selector; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_tabs_icon_color_selector_colored = global::HelloworldXamarin.Droid.Resource.Color.mtrl_tabs_icon_color_selector_colored; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_tabs_legacy_text_color_selector = global::HelloworldXamarin.Droid.Resource.Color.mtrl_tabs_legacy_text_color_selector; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_tabs_ripple_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_tabs_ripple_color; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_textinput_default_box_stroke_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_textinput_default_box_stroke_color; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_textinput_disabled_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_textinput_disabled_color; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_textinput_filled_box_default_background_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_textinput_filled_box_default_background_color; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_textinput_hovered_box_stroke_color = global::HelloworldXamarin.Droid.Resource.Color.mtrl_textinput_hovered_box_stroke_color; + global::Xamarin.Forms.Platform.Resource.Color.mtrl_text_btn_text_color_selector = global::HelloworldXamarin.Droid.Resource.Color.mtrl_text_btn_text_color_selector; + global::Xamarin.Forms.Platform.Resource.Color.notification_action_color_filter = global::HelloworldXamarin.Droid.Resource.Color.notification_action_color_filter; + global::Xamarin.Forms.Platform.Resource.Color.notification_icon_bg_color = global::HelloworldXamarin.Droid.Resource.Color.notification_icon_bg_color; + global::Xamarin.Forms.Platform.Resource.Color.notification_material_background_media_default_color = global::HelloworldXamarin.Droid.Resource.Color.notification_material_background_media_default_color; + global::Xamarin.Forms.Platform.Resource.Color.primary_dark_material_dark = global::HelloworldXamarin.Droid.Resource.Color.primary_dark_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.primary_dark_material_light = global::HelloworldXamarin.Droid.Resource.Color.primary_dark_material_light; + global::Xamarin.Forms.Platform.Resource.Color.primary_material_dark = global::HelloworldXamarin.Droid.Resource.Color.primary_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.primary_material_light = global::HelloworldXamarin.Droid.Resource.Color.primary_material_light; + global::Xamarin.Forms.Platform.Resource.Color.primary_text_default_material_dark = global::HelloworldXamarin.Droid.Resource.Color.primary_text_default_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.primary_text_default_material_light = global::HelloworldXamarin.Droid.Resource.Color.primary_text_default_material_light; + global::Xamarin.Forms.Platform.Resource.Color.primary_text_disabled_material_dark = global::HelloworldXamarin.Droid.Resource.Color.primary_text_disabled_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.primary_text_disabled_material_light = global::HelloworldXamarin.Droid.Resource.Color.primary_text_disabled_material_light; + global::Xamarin.Forms.Platform.Resource.Color.ripple_material_dark = global::HelloworldXamarin.Droid.Resource.Color.ripple_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.ripple_material_light = global::HelloworldXamarin.Droid.Resource.Color.ripple_material_light; + global::Xamarin.Forms.Platform.Resource.Color.secondary_text_default_material_dark = global::HelloworldXamarin.Droid.Resource.Color.secondary_text_default_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.secondary_text_default_material_light = global::HelloworldXamarin.Droid.Resource.Color.secondary_text_default_material_light; + global::Xamarin.Forms.Platform.Resource.Color.secondary_text_disabled_material_dark = global::HelloworldXamarin.Droid.Resource.Color.secondary_text_disabled_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.secondary_text_disabled_material_light = global::HelloworldXamarin.Droid.Resource.Color.secondary_text_disabled_material_light; + global::Xamarin.Forms.Platform.Resource.Color.switch_thumb_disabled_material_dark = global::HelloworldXamarin.Droid.Resource.Color.switch_thumb_disabled_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.switch_thumb_disabled_material_light = global::HelloworldXamarin.Droid.Resource.Color.switch_thumb_disabled_material_light; + global::Xamarin.Forms.Platform.Resource.Color.switch_thumb_material_dark = global::HelloworldXamarin.Droid.Resource.Color.switch_thumb_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.switch_thumb_material_light = global::HelloworldXamarin.Droid.Resource.Color.switch_thumb_material_light; + global::Xamarin.Forms.Platform.Resource.Color.switch_thumb_normal_material_dark = global::HelloworldXamarin.Droid.Resource.Color.switch_thumb_normal_material_dark; + global::Xamarin.Forms.Platform.Resource.Color.switch_thumb_normal_material_light = global::HelloworldXamarin.Droid.Resource.Color.switch_thumb_normal_material_light; + global::Xamarin.Forms.Platform.Resource.Color.tooltip_background_dark = global::HelloworldXamarin.Droid.Resource.Color.tooltip_background_dark; + global::Xamarin.Forms.Platform.Resource.Color.tooltip_background_light = global::HelloworldXamarin.Droid.Resource.Color.tooltip_background_light; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_content_inset_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_content_inset_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_content_inset_with_nav = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_content_inset_with_nav; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_default_height_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_default_height_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_default_padding_end_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_default_padding_end_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_default_padding_start_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_default_padding_start_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_elevation_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_elevation_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_icon_vertical_padding_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_icon_vertical_padding_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_overflow_padding_end_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_overflow_padding_end_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_overflow_padding_start_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_overflow_padding_start_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_stacked_max_height = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_stacked_max_height; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_stacked_tab_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_stacked_tab_max_width; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_subtitle_bottom_margin_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_subtitle_bottom_margin_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_bar_subtitle_top_margin_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_bar_subtitle_top_margin_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_button_min_height_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_button_min_height_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_button_min_width_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_button_min_width_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_action_button_min_width_overflow_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_action_button_min_width_overflow_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_alert_dialog_button_bar_height = global::HelloworldXamarin.Droid.Resource.Dimension.abc_alert_dialog_button_bar_height; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_alert_dialog_button_dimen = global::HelloworldXamarin.Droid.Resource.Dimension.abc_alert_dialog_button_dimen; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_button_inset_horizontal_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_button_inset_horizontal_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_button_inset_vertical_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_button_inset_vertical_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_button_padding_horizontal_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_button_padding_horizontal_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_button_padding_vertical_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_button_padding_vertical_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_cascading_menus_min_smallest_width = global::HelloworldXamarin.Droid.Resource.Dimension.abc_cascading_menus_min_smallest_width; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_config_prefDialogWidth = global::HelloworldXamarin.Droid.Resource.Dimension.abc_config_prefDialogWidth; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_control_corner_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_control_corner_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_control_inset_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_control_inset_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_control_padding_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_control_padding_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_corner_radius_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_corner_radius_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_fixed_height_major = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_fixed_height_major; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_fixed_height_minor = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_fixed_height_minor; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_fixed_width_major = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_fixed_width_major; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_fixed_width_minor = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_fixed_width_minor; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_list_padding_bottom_no_buttons = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_list_padding_bottom_no_buttons; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_list_padding_top_no_title = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_list_padding_top_no_title; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_min_width_major = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_min_width_major; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_min_width_minor = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_min_width_minor; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_padding_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_padding_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_padding_top_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_padding_top_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dialog_title_divider_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dialog_title_divider_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_disabled_alpha_material_dark = global::HelloworldXamarin.Droid.Resource.Dimension.abc_disabled_alpha_material_dark; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_disabled_alpha_material_light = global::HelloworldXamarin.Droid.Resource.Dimension.abc_disabled_alpha_material_light; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dropdownitem_icon_width = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dropdownitem_icon_width; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dropdownitem_text_padding_left = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dropdownitem_text_padding_left; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_dropdownitem_text_padding_right = global::HelloworldXamarin.Droid.Resource.Dimension.abc_dropdownitem_text_padding_right; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_edit_text_inset_bottom_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_edit_text_inset_bottom_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_edit_text_inset_horizontal_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_edit_text_inset_horizontal_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_edit_text_inset_top_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_edit_text_inset_top_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_floating_window_z = global::HelloworldXamarin.Droid.Resource.Dimension.abc_floating_window_z; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_list_item_padding_horizontal_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_list_item_padding_horizontal_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_panel_menu_list_width = global::HelloworldXamarin.Droid.Resource.Dimension.abc_panel_menu_list_width; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_progress_bar_height_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_progress_bar_height_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_search_view_preferred_height = global::HelloworldXamarin.Droid.Resource.Dimension.abc_search_view_preferred_height; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_search_view_preferred_width = global::HelloworldXamarin.Droid.Resource.Dimension.abc_search_view_preferred_width; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_seekbar_track_background_height_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_seekbar_track_background_height_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_seekbar_track_progress_height_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_seekbar_track_progress_height_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_select_dialog_padding_start_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_select_dialog_padding_start_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_switch_padding = global::HelloworldXamarin.Droid.Resource.Dimension.abc_switch_padding; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_body_1_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_body_1_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_body_2_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_body_2_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_button_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_button_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_caption_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_caption_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_display_1_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_display_1_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_display_2_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_display_2_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_display_3_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_display_3_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_display_4_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_display_4_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_headline_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_headline_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_large_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_large_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_medium_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_medium_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_menu_header_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_menu_header_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_menu_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_menu_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_small_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_small_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_subhead_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_subhead_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_subtitle_material_toolbar = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_subtitle_material_toolbar; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_title_material = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_title_material; + global::Xamarin.Forms.Platform.Resource.Dimension.abc_text_size_title_material_toolbar = global::HelloworldXamarin.Droid.Resource.Dimension.abc_text_size_title_material_toolbar; + global::Xamarin.Forms.Platform.Resource.Dimension.cardview_compat_inset_shadow = global::HelloworldXamarin.Droid.Resource.Dimension.cardview_compat_inset_shadow; + global::Xamarin.Forms.Platform.Resource.Dimension.cardview_default_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.cardview_default_elevation; + global::Xamarin.Forms.Platform.Resource.Dimension.cardview_default_radius = global::HelloworldXamarin.Droid.Resource.Dimension.cardview_default_radius; + global::Xamarin.Forms.Platform.Resource.Dimension.compat_button_inset_horizontal_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_button_inset_horizontal_material; + global::Xamarin.Forms.Platform.Resource.Dimension.compat_button_inset_vertical_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_button_inset_vertical_material; + global::Xamarin.Forms.Platform.Resource.Dimension.compat_button_padding_horizontal_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_button_padding_horizontal_material; + global::Xamarin.Forms.Platform.Resource.Dimension.compat_button_padding_vertical_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_button_padding_vertical_material; + global::Xamarin.Forms.Platform.Resource.Dimension.compat_control_corner_material = global::HelloworldXamarin.Droid.Resource.Dimension.compat_control_corner_material; + global::Xamarin.Forms.Platform.Resource.Dimension.compat_notification_large_icon_max_height = global::HelloworldXamarin.Droid.Resource.Dimension.compat_notification_large_icon_max_height; + global::Xamarin.Forms.Platform.Resource.Dimension.compat_notification_large_icon_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.compat_notification_large_icon_max_width; + global::Xamarin.Forms.Platform.Resource.Dimension.design_appbar_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.design_appbar_elevation; + global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_active_item_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_active_item_max_width; + global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_active_item_min_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_active_item_min_width; + global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_active_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_active_text_size; + global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_elevation; + global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_height = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_height; + global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_icon_size = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_icon_size; + global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_item_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_item_max_width; + global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_item_min_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_item_min_width; + global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_margin = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_margin; + global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_shadow_height = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_shadow_height; + global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_navigation_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_navigation_text_size; + global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_sheet_modal_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_sheet_modal_elevation; + global::Xamarin.Forms.Platform.Resource.Dimension.design_bottom_sheet_peek_height_min = global::HelloworldXamarin.Droid.Resource.Dimension.design_bottom_sheet_peek_height_min; + global::Xamarin.Forms.Platform.Resource.Dimension.design_fab_border_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_fab_border_width; + global::Xamarin.Forms.Platform.Resource.Dimension.design_fab_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.design_fab_elevation; + global::Xamarin.Forms.Platform.Resource.Dimension.design_fab_image_size = global::HelloworldXamarin.Droid.Resource.Dimension.design_fab_image_size; + global::Xamarin.Forms.Platform.Resource.Dimension.design_fab_size_mini = global::HelloworldXamarin.Droid.Resource.Dimension.design_fab_size_mini; + global::Xamarin.Forms.Platform.Resource.Dimension.design_fab_size_normal = global::HelloworldXamarin.Droid.Resource.Dimension.design_fab_size_normal; + global::Xamarin.Forms.Platform.Resource.Dimension.design_fab_translation_z_hovered_focused = global::HelloworldXamarin.Droid.Resource.Dimension.design_fab_translation_z_hovered_focused; + global::Xamarin.Forms.Platform.Resource.Dimension.design_fab_translation_z_pressed = global::HelloworldXamarin.Droid.Resource.Dimension.design_fab_translation_z_pressed; + global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_elevation; + global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_icon_padding = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_icon_padding; + global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_icon_size = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_icon_size; + global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_item_horizontal_padding = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_item_horizontal_padding; + global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_item_icon_padding = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_item_icon_padding; + global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_max_width; + global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_padding_bottom = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_padding_bottom; + global::Xamarin.Forms.Platform.Resource.Dimension.design_navigation_separator_vertical_padding = global::HelloworldXamarin.Droid.Resource.Dimension.design_navigation_separator_vertical_padding; + global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_action_inline_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_action_inline_max_width; + global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_background_corner_radius = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_background_corner_radius; + global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_elevation; + global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_extra_spacing_horizontal = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_extra_spacing_horizontal; + global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_max_width; + global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_min_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_min_width; + global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_padding_horizontal = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_padding_horizontal; + global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_padding_vertical = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_padding_vertical; + global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_padding_vertical_2lines = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_padding_vertical_2lines; + global::Xamarin.Forms.Platform.Resource.Dimension.design_snackbar_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.design_snackbar_text_size; + global::Xamarin.Forms.Platform.Resource.Dimension.design_tab_max_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_tab_max_width; + global::Xamarin.Forms.Platform.Resource.Dimension.design_tab_scrollable_min_width = global::HelloworldXamarin.Droid.Resource.Dimension.design_tab_scrollable_min_width; + global::Xamarin.Forms.Platform.Resource.Dimension.design_tab_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.design_tab_text_size; + global::Xamarin.Forms.Platform.Resource.Dimension.design_tab_text_size_2line = global::HelloworldXamarin.Droid.Resource.Dimension.design_tab_text_size_2line; + global::Xamarin.Forms.Platform.Resource.Dimension.design_textinput_caption_translate_y = global::HelloworldXamarin.Droid.Resource.Dimension.design_textinput_caption_translate_y; + global::Xamarin.Forms.Platform.Resource.Dimension.disabled_alpha_material_dark = global::HelloworldXamarin.Droid.Resource.Dimension.disabled_alpha_material_dark; + global::Xamarin.Forms.Platform.Resource.Dimension.disabled_alpha_material_light = global::HelloworldXamarin.Droid.Resource.Dimension.disabled_alpha_material_light; + global::Xamarin.Forms.Platform.Resource.Dimension.fastscroll_default_thickness = global::HelloworldXamarin.Droid.Resource.Dimension.fastscroll_default_thickness; + global::Xamarin.Forms.Platform.Resource.Dimension.fastscroll_margin = global::HelloworldXamarin.Droid.Resource.Dimension.fastscroll_margin; + global::Xamarin.Forms.Platform.Resource.Dimension.fastscroll_minimum_range = global::HelloworldXamarin.Droid.Resource.Dimension.fastscroll_minimum_range; + global::Xamarin.Forms.Platform.Resource.Dimension.highlight_alpha_material_colored = global::HelloworldXamarin.Droid.Resource.Dimension.highlight_alpha_material_colored; + global::Xamarin.Forms.Platform.Resource.Dimension.highlight_alpha_material_dark = global::HelloworldXamarin.Droid.Resource.Dimension.highlight_alpha_material_dark; + global::Xamarin.Forms.Platform.Resource.Dimension.highlight_alpha_material_light = global::HelloworldXamarin.Droid.Resource.Dimension.highlight_alpha_material_light; + global::Xamarin.Forms.Platform.Resource.Dimension.hint_alpha_material_dark = global::HelloworldXamarin.Droid.Resource.Dimension.hint_alpha_material_dark; + global::Xamarin.Forms.Platform.Resource.Dimension.hint_alpha_material_light = global::HelloworldXamarin.Droid.Resource.Dimension.hint_alpha_material_light; + global::Xamarin.Forms.Platform.Resource.Dimension.hint_pressed_alpha_material_dark = global::HelloworldXamarin.Droid.Resource.Dimension.hint_pressed_alpha_material_dark; + global::Xamarin.Forms.Platform.Resource.Dimension.hint_pressed_alpha_material_light = global::HelloworldXamarin.Droid.Resource.Dimension.hint_pressed_alpha_material_light; + global::Xamarin.Forms.Platform.Resource.Dimension.item_touch_helper_max_drag_scroll_per_frame = global::HelloworldXamarin.Droid.Resource.Dimension.item_touch_helper_max_drag_scroll_per_frame; + global::Xamarin.Forms.Platform.Resource.Dimension.item_touch_helper_swipe_escape_max_velocity = global::HelloworldXamarin.Droid.Resource.Dimension.item_touch_helper_swipe_escape_max_velocity; + global::Xamarin.Forms.Platform.Resource.Dimension.item_touch_helper_swipe_escape_velocity = global::HelloworldXamarin.Droid.Resource.Dimension.item_touch_helper_swipe_escape_velocity; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_bottomappbar_fabOffsetEndMode = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_bottomappbar_fabOffsetEndMode; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_bottomappbar_fab_cradle_margin = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_bottomappbar_fab_cradle_margin; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_bottomappbar_fab_cradle_rounded_corner_radius = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_bottomappbar_fab_cradle_rounded_corner_radius; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_bottomappbar_fab_cradle_vertical_offset = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_bottomappbar_fab_cradle_vertical_offset; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_bottomappbar_height = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_bottomappbar_height; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_corner_radius = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_corner_radius; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_dialog_btn_min_width = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_dialog_btn_min_width; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_disabled_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_disabled_elevation; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_disabled_z = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_disabled_z; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_elevation; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_focused_z = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_focused_z; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_hovered_z = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_hovered_z; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_icon_btn_padding_left = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_icon_btn_padding_left; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_icon_padding = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_icon_padding; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_inset = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_inset; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_letter_spacing = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_letter_spacing; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_padding_bottom = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_padding_bottom; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_padding_left = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_padding_left; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_padding_right = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_padding_right; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_padding_top = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_padding_top; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_pressed_z = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_pressed_z; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_stroke_size = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_stroke_size; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_text_btn_icon_padding = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_text_btn_icon_padding; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_text_btn_padding_left = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_text_btn_padding_left; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_text_btn_padding_right = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_text_btn_padding_right; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_text_size; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_btn_z = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_btn_z; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_card_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_card_elevation; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_card_spacing = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_card_spacing; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_chip_pressed_translation_z = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_chip_pressed_translation_z; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_chip_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_chip_text_size; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_fab_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_fab_elevation; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_fab_translation_z_hovered_focused = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_fab_translation_z_hovered_focused; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_fab_translation_z_pressed = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_fab_translation_z_pressed; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_navigation_elevation = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_navigation_elevation; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_navigation_item_horizontal_padding = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_navigation_item_horizontal_padding; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_navigation_item_icon_padding = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_navigation_item_icon_padding; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_snackbar_background_corner_radius = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_snackbar_background_corner_radius; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_snackbar_margin = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_snackbar_margin; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_box_bottom_offset = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_box_bottom_offset; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_box_corner_radius_medium = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_box_corner_radius_medium; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_box_corner_radius_small = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_box_corner_radius_small; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_box_label_cutout_padding = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_box_label_cutout_padding; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_box_padding_end = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_box_padding_end; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_box_stroke_width_default = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_box_stroke_width_default; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_box_stroke_width_focused = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_box_stroke_width_focused; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_textinput_outline_box_expanded_padding = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_textinput_outline_box_expanded_padding; + global::Xamarin.Forms.Platform.Resource.Dimension.mtrl_toolbar_default_height = global::HelloworldXamarin.Droid.Resource.Dimension.mtrl_toolbar_default_height; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_action_icon_size = global::HelloworldXamarin.Droid.Resource.Dimension.notification_action_icon_size; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_action_text_size = global::HelloworldXamarin.Droid.Resource.Dimension.notification_action_text_size; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_big_circle_margin = global::HelloworldXamarin.Droid.Resource.Dimension.notification_big_circle_margin; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_content_margin_start = global::HelloworldXamarin.Droid.Resource.Dimension.notification_content_margin_start; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_large_icon_height = global::HelloworldXamarin.Droid.Resource.Dimension.notification_large_icon_height; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_large_icon_width = global::HelloworldXamarin.Droid.Resource.Dimension.notification_large_icon_width; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_main_column_padding_top = global::HelloworldXamarin.Droid.Resource.Dimension.notification_main_column_padding_top; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_media_narrow_margin = global::HelloworldXamarin.Droid.Resource.Dimension.notification_media_narrow_margin; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_right_icon_size = global::HelloworldXamarin.Droid.Resource.Dimension.notification_right_icon_size; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_right_side_padding_top = global::HelloworldXamarin.Droid.Resource.Dimension.notification_right_side_padding_top; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_small_icon_background_padding = global::HelloworldXamarin.Droid.Resource.Dimension.notification_small_icon_background_padding; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_small_icon_size_as_large = global::HelloworldXamarin.Droid.Resource.Dimension.notification_small_icon_size_as_large; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_subtext_size = global::HelloworldXamarin.Droid.Resource.Dimension.notification_subtext_size; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_top_pad = global::HelloworldXamarin.Droid.Resource.Dimension.notification_top_pad; + global::Xamarin.Forms.Platform.Resource.Dimension.notification_top_pad_large_text = global::HelloworldXamarin.Droid.Resource.Dimension.notification_top_pad_large_text; + global::Xamarin.Forms.Platform.Resource.Dimension.subtitle_corner_radius = global::HelloworldXamarin.Droid.Resource.Dimension.subtitle_corner_radius; + global::Xamarin.Forms.Platform.Resource.Dimension.subtitle_outline_width = global::HelloworldXamarin.Droid.Resource.Dimension.subtitle_outline_width; + global::Xamarin.Forms.Platform.Resource.Dimension.subtitle_shadow_offset = global::HelloworldXamarin.Droid.Resource.Dimension.subtitle_shadow_offset; + global::Xamarin.Forms.Platform.Resource.Dimension.subtitle_shadow_radius = global::HelloworldXamarin.Droid.Resource.Dimension.subtitle_shadow_radius; + global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_corner_radius = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_corner_radius; + global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_horizontal_padding = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_horizontal_padding; + global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_margin = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_margin; + global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_precise_anchor_extra_offset = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_precise_anchor_extra_offset; + global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_precise_anchor_threshold = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_precise_anchor_threshold; + global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_vertical_padding = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_vertical_padding; + global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_y_offset_non_touch = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_y_offset_non_touch; + global::Xamarin.Forms.Platform.Resource.Dimension.tooltip_y_offset_touch = global::HelloworldXamarin.Droid.Resource.Dimension.tooltip_y_offset_touch; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ab_share_pack_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ab_share_pack_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_action_bar_item_background_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_action_bar_item_background_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_borderless_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_borderless_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_check_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_check_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_check_to_on_mtrl_000 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_check_to_on_mtrl_000; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_check_to_on_mtrl_015 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_check_to_on_mtrl_015; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_colored_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_colored_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_default_mtrl_shape = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_default_mtrl_shape; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_radio_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_radio_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_radio_to_on_mtrl_000 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_radio_to_on_mtrl_000; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_radio_to_on_mtrl_015 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_radio_to_on_mtrl_015; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_switch_to_on_mtrl_00001 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_switch_to_on_mtrl_00001; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_btn_switch_to_on_mtrl_00012 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_btn_switch_to_on_mtrl_00012; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_cab_background_internal_bg = global::HelloworldXamarin.Droid.Resource.Drawable.abc_cab_background_internal_bg; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_cab_background_top_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_cab_background_top_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_cab_background_top_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_cab_background_top_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_control_background_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_control_background_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_dialog_material_background = global::HelloworldXamarin.Droid.Resource.Drawable.abc_dialog_material_background; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_edit_text_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_edit_text_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_ab_back_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_ab_back_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_arrow_drop_right_black_24dp = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_arrow_drop_right_black_24dp; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_clear_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_clear_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_commit_search_api_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_commit_search_api_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_go_search_api_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_go_search_api_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_menu_copy_mtrl_am_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_menu_copy_mtrl_am_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_menu_cut_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_menu_cut_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_menu_overflow_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_menu_overflow_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_menu_paste_mtrl_am_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_menu_paste_mtrl_am_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_menu_selectall_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_menu_selectall_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_menu_share_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_menu_share_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_search_api_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_search_api_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_star_black_16dp = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_star_black_16dp; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_star_black_36dp = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_star_black_36dp; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_star_black_48dp = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_star_black_48dp; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_star_half_black_16dp = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_star_half_black_16dp; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_star_half_black_36dp = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_star_half_black_36dp; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_star_half_black_48dp = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_star_half_black_48dp; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ic_voice_search_api_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ic_voice_search_api_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_item_background_holo_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_item_background_holo_dark; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_item_background_holo_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_item_background_holo_light; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_divider_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_divider_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_divider_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_divider_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_focused_holo = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_focused_holo; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_longpressed_holo = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_longpressed_holo; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_pressed_holo_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_pressed_holo_dark; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_pressed_holo_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_pressed_holo_light; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_selector_background_transition_holo_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_selector_background_transition_holo_dark; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_selector_background_transition_holo_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_selector_background_transition_holo_light; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_selector_disabled_holo_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_selector_disabled_holo_dark; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_selector_disabled_holo_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_selector_disabled_holo_light; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_selector_holo_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_selector_holo_dark; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_list_selector_holo_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_list_selector_holo_light; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_menu_hardkey_panel_mtrl_mult = global::HelloworldXamarin.Droid.Resource.Drawable.abc_menu_hardkey_panel_mtrl_mult; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_popup_background_mtrl_mult = global::HelloworldXamarin.Droid.Resource.Drawable.abc_popup_background_mtrl_mult; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ratingbar_indicator_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ratingbar_indicator_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ratingbar_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ratingbar_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_ratingbar_small_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_ratingbar_small_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_scrubber_control_off_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_scrubber_control_off_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_000 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_000; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_005 = global::HelloworldXamarin.Droid.Resource.Drawable.abc_scrubber_control_to_pressed_mtrl_005; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_scrubber_primary_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_scrubber_primary_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_scrubber_track_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_scrubber_track_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_seekbar_thumb_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_seekbar_thumb_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_seekbar_tick_mark_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_seekbar_tick_mark_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_seekbar_track_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_seekbar_track_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_spinner_mtrl_am_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_spinner_mtrl_am_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_spinner_textfield_background_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_spinner_textfield_background_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_switch_thumb_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_switch_thumb_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_switch_track_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_switch_track_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_tab_indicator_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_tab_indicator_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_tab_indicator_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_tab_indicator_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_textfield_activated_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_textfield_activated_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_textfield_default_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_textfield_default_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_textfield_search_activated_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_textfield_search_activated_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_textfield_search_default_mtrl_alpha = global::HelloworldXamarin.Droid.Resource.Drawable.abc_textfield_search_default_mtrl_alpha; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_textfield_search_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_textfield_search_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_text_cursor_material = global::HelloworldXamarin.Droid.Resource.Drawable.abc_text_cursor_material; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_text_select_handle_left_mtrl_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_text_select_handle_left_mtrl_dark; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_text_select_handle_left_mtrl_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_text_select_handle_left_mtrl_light; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_text_select_handle_middle_mtrl_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_text_select_handle_middle_mtrl_dark; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_text_select_handle_middle_mtrl_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_text_select_handle_middle_mtrl_light; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_text_select_handle_right_mtrl_dark = global::HelloworldXamarin.Droid.Resource.Drawable.abc_text_select_handle_right_mtrl_dark; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_text_select_handle_right_mtrl_light = global::HelloworldXamarin.Droid.Resource.Drawable.abc_text_select_handle_right_mtrl_light; + global::Xamarin.Forms.Platform.Resource.Drawable.abc_vector_test = global::HelloworldXamarin.Droid.Resource.Drawable.abc_vector_test; + global::Xamarin.Forms.Platform.Resource.Drawable.avd_hide_password = global::HelloworldXamarin.Droid.Resource.Drawable.avd_hide_password; + global::Xamarin.Forms.Platform.Resource.Drawable.avd_show_password = global::HelloworldXamarin.Droid.Resource.Drawable.avd_show_password; + global::Xamarin.Forms.Platform.Resource.Drawable.design_bottom_navigation_item_background = global::HelloworldXamarin.Droid.Resource.Drawable.design_bottom_navigation_item_background; + global::Xamarin.Forms.Platform.Resource.Drawable.design_fab_background = global::HelloworldXamarin.Droid.Resource.Drawable.design_fab_background; + global::Xamarin.Forms.Platform.Resource.Drawable.design_ic_visibility = global::HelloworldXamarin.Droid.Resource.Drawable.design_ic_visibility; + global::Xamarin.Forms.Platform.Resource.Drawable.design_ic_visibility_off = global::HelloworldXamarin.Droid.Resource.Drawable.design_ic_visibility_off; + global::Xamarin.Forms.Platform.Resource.Drawable.design_password_eye = global::HelloworldXamarin.Droid.Resource.Drawable.design_password_eye; + global::Xamarin.Forms.Platform.Resource.Drawable.design_snackbar_background = global::HelloworldXamarin.Droid.Resource.Drawable.design_snackbar_background; + global::Xamarin.Forms.Platform.Resource.Drawable.ic_mtrl_chip_checked_black = global::HelloworldXamarin.Droid.Resource.Drawable.ic_mtrl_chip_checked_black; + global::Xamarin.Forms.Platform.Resource.Drawable.ic_mtrl_chip_checked_circle = global::HelloworldXamarin.Droid.Resource.Drawable.ic_mtrl_chip_checked_circle; + global::Xamarin.Forms.Platform.Resource.Drawable.ic_mtrl_chip_close_circle = global::HelloworldXamarin.Droid.Resource.Drawable.ic_mtrl_chip_close_circle; + global::Xamarin.Forms.Platform.Resource.Drawable.mtrl_snackbar_background = global::HelloworldXamarin.Droid.Resource.Drawable.mtrl_snackbar_background; + global::Xamarin.Forms.Platform.Resource.Drawable.mtrl_tabs_default_indicator = global::HelloworldXamarin.Droid.Resource.Drawable.mtrl_tabs_default_indicator; + global::Xamarin.Forms.Platform.Resource.Drawable.navigation_empty_icon = global::HelloworldXamarin.Droid.Resource.Drawable.navigation_empty_icon; + global::Xamarin.Forms.Platform.Resource.Drawable.notification_action_background = global::HelloworldXamarin.Droid.Resource.Drawable.notification_action_background; + global::Xamarin.Forms.Platform.Resource.Drawable.notification_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg; + global::Xamarin.Forms.Platform.Resource.Drawable.notification_bg_low = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_low; + global::Xamarin.Forms.Platform.Resource.Drawable.notification_bg_low_normal = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_low_normal; + global::Xamarin.Forms.Platform.Resource.Drawable.notification_bg_low_pressed = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_low_pressed; + global::Xamarin.Forms.Platform.Resource.Drawable.notification_bg_normal = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_normal; + global::Xamarin.Forms.Platform.Resource.Drawable.notification_bg_normal_pressed = global::HelloworldXamarin.Droid.Resource.Drawable.notification_bg_normal_pressed; + global::Xamarin.Forms.Platform.Resource.Drawable.notification_icon_background = global::HelloworldXamarin.Droid.Resource.Drawable.notification_icon_background; + global::Xamarin.Forms.Platform.Resource.Drawable.notification_template_icon_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notification_template_icon_bg; + global::Xamarin.Forms.Platform.Resource.Drawable.notification_template_icon_low_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notification_template_icon_low_bg; + global::Xamarin.Forms.Platform.Resource.Drawable.notification_tile_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notification_tile_bg; + global::Xamarin.Forms.Platform.Resource.Drawable.notify_panel_notification_icon_bg = global::HelloworldXamarin.Droid.Resource.Drawable.notify_panel_notification_icon_bg; + global::Xamarin.Forms.Platform.Resource.Drawable.tooltip_frame_dark = global::HelloworldXamarin.Droid.Resource.Drawable.tooltip_frame_dark; + global::Xamarin.Forms.Platform.Resource.Drawable.tooltip_frame_light = global::HelloworldXamarin.Droid.Resource.Drawable.tooltip_frame_light; + global::Xamarin.Forms.Platform.Resource.Id.action0 = global::HelloworldXamarin.Droid.Resource.Id.action0; + global::Xamarin.Forms.Platform.Resource.Id.actions = global::HelloworldXamarin.Droid.Resource.Id.actions; + global::Xamarin.Forms.Platform.Resource.Id.action_bar = global::HelloworldXamarin.Droid.Resource.Id.action_bar; + global::Xamarin.Forms.Platform.Resource.Id.action_bar_activity_content = global::HelloworldXamarin.Droid.Resource.Id.action_bar_activity_content; + global::Xamarin.Forms.Platform.Resource.Id.action_bar_container = global::HelloworldXamarin.Droid.Resource.Id.action_bar_container; + global::Xamarin.Forms.Platform.Resource.Id.action_bar_root = global::HelloworldXamarin.Droid.Resource.Id.action_bar_root; + global::Xamarin.Forms.Platform.Resource.Id.action_bar_spinner = global::HelloworldXamarin.Droid.Resource.Id.action_bar_spinner; + global::Xamarin.Forms.Platform.Resource.Id.action_bar_subtitle = global::HelloworldXamarin.Droid.Resource.Id.action_bar_subtitle; + global::Xamarin.Forms.Platform.Resource.Id.action_bar_title = global::HelloworldXamarin.Droid.Resource.Id.action_bar_title; + global::Xamarin.Forms.Platform.Resource.Id.action_container = global::HelloworldXamarin.Droid.Resource.Id.action_container; + global::Xamarin.Forms.Platform.Resource.Id.action_context_bar = global::HelloworldXamarin.Droid.Resource.Id.action_context_bar; + global::Xamarin.Forms.Platform.Resource.Id.action_divider = global::HelloworldXamarin.Droid.Resource.Id.action_divider; + global::Xamarin.Forms.Platform.Resource.Id.action_image = global::HelloworldXamarin.Droid.Resource.Id.action_image; + global::Xamarin.Forms.Platform.Resource.Id.action_menu_divider = global::HelloworldXamarin.Droid.Resource.Id.action_menu_divider; + global::Xamarin.Forms.Platform.Resource.Id.action_menu_presenter = global::HelloworldXamarin.Droid.Resource.Id.action_menu_presenter; + global::Xamarin.Forms.Platform.Resource.Id.action_mode_bar = global::HelloworldXamarin.Droid.Resource.Id.action_mode_bar; + global::Xamarin.Forms.Platform.Resource.Id.action_mode_bar_stub = global::HelloworldXamarin.Droid.Resource.Id.action_mode_bar_stub; + global::Xamarin.Forms.Platform.Resource.Id.action_mode_close_button = global::HelloworldXamarin.Droid.Resource.Id.action_mode_close_button; + global::Xamarin.Forms.Platform.Resource.Id.action_text = global::HelloworldXamarin.Droid.Resource.Id.action_text; + global::Xamarin.Forms.Platform.Resource.Id.activity_chooser_view_content = global::HelloworldXamarin.Droid.Resource.Id.activity_chooser_view_content; + global::Xamarin.Forms.Platform.Resource.Id.add = global::HelloworldXamarin.Droid.Resource.Id.add; + global::Xamarin.Forms.Platform.Resource.Id.alertTitle = global::HelloworldXamarin.Droid.Resource.Id.alertTitle; + global::Xamarin.Forms.Platform.Resource.Id.all = global::HelloworldXamarin.Droid.Resource.Id.all; + global::Xamarin.Forms.Platform.Resource.Id.ALT = global::HelloworldXamarin.Droid.Resource.Id.ALT; + global::Xamarin.Forms.Platform.Resource.Id.always = global::HelloworldXamarin.Droid.Resource.Id.always; + global::Xamarin.Forms.Platform.Resource.Id.async = global::HelloworldXamarin.Droid.Resource.Id.async; + global::Xamarin.Forms.Platform.Resource.Id.auto = global::HelloworldXamarin.Droid.Resource.Id.auto; + global::Xamarin.Forms.Platform.Resource.Id.beginning = global::HelloworldXamarin.Droid.Resource.Id.beginning; + global::Xamarin.Forms.Platform.Resource.Id.blocking = global::HelloworldXamarin.Droid.Resource.Id.blocking; + global::Xamarin.Forms.Platform.Resource.Id.bottom = global::HelloworldXamarin.Droid.Resource.Id.bottom; + global::Xamarin.Forms.Platform.Resource.Id.bottomtab_navarea = global::HelloworldXamarin.Droid.Resource.Id.bottomtab_navarea; + global::Xamarin.Forms.Platform.Resource.Id.bottomtab_tabbar = global::HelloworldXamarin.Droid.Resource.Id.bottomtab_tabbar; + global::Xamarin.Forms.Platform.Resource.Id.buttonPanel = global::HelloworldXamarin.Droid.Resource.Id.buttonPanel; + global::Xamarin.Forms.Platform.Resource.Id.cancel_action = global::HelloworldXamarin.Droid.Resource.Id.cancel_action; + global::Xamarin.Forms.Platform.Resource.Id.center = global::HelloworldXamarin.Droid.Resource.Id.center; + global::Xamarin.Forms.Platform.Resource.Id.center_horizontal = global::HelloworldXamarin.Droid.Resource.Id.center_horizontal; + global::Xamarin.Forms.Platform.Resource.Id.center_vertical = global::HelloworldXamarin.Droid.Resource.Id.center_vertical; + global::Xamarin.Forms.Platform.Resource.Id.checkbox = global::HelloworldXamarin.Droid.Resource.Id.checkbox; + global::Xamarin.Forms.Platform.Resource.Id.chronometer = global::HelloworldXamarin.Droid.Resource.Id.chronometer; + global::Xamarin.Forms.Platform.Resource.Id.clip_horizontal = global::HelloworldXamarin.Droid.Resource.Id.clip_horizontal; + global::Xamarin.Forms.Platform.Resource.Id.clip_vertical = global::HelloworldXamarin.Droid.Resource.Id.clip_vertical; + global::Xamarin.Forms.Platform.Resource.Id.collapseActionView = global::HelloworldXamarin.Droid.Resource.Id.collapseActionView; + global::Xamarin.Forms.Platform.Resource.Id.container = global::HelloworldXamarin.Droid.Resource.Id.container; + global::Xamarin.Forms.Platform.Resource.Id.content = global::HelloworldXamarin.Droid.Resource.Id.content; + global::Xamarin.Forms.Platform.Resource.Id.contentPanel = global::HelloworldXamarin.Droid.Resource.Id.contentPanel; + global::Xamarin.Forms.Platform.Resource.Id.coordinator = global::HelloworldXamarin.Droid.Resource.Id.coordinator; + global::Xamarin.Forms.Platform.Resource.Id.CTRL = global::HelloworldXamarin.Droid.Resource.Id.CTRL; + global::Xamarin.Forms.Platform.Resource.Id.custom = global::HelloworldXamarin.Droid.Resource.Id.custom; + global::Xamarin.Forms.Platform.Resource.Id.customPanel = global::HelloworldXamarin.Droid.Resource.Id.customPanel; + global::Xamarin.Forms.Platform.Resource.Id.decor_content_parent = global::HelloworldXamarin.Droid.Resource.Id.decor_content_parent; + global::Xamarin.Forms.Platform.Resource.Id.default_activity_button = global::HelloworldXamarin.Droid.Resource.Id.default_activity_button; + global::Xamarin.Forms.Platform.Resource.Id.design_bottom_sheet = global::HelloworldXamarin.Droid.Resource.Id.design_bottom_sheet; + global::Xamarin.Forms.Platform.Resource.Id.design_menu_item_action_area = global::HelloworldXamarin.Droid.Resource.Id.design_menu_item_action_area; + global::Xamarin.Forms.Platform.Resource.Id.design_menu_item_action_area_stub = global::HelloworldXamarin.Droid.Resource.Id.design_menu_item_action_area_stub; + global::Xamarin.Forms.Platform.Resource.Id.design_menu_item_text = global::HelloworldXamarin.Droid.Resource.Id.design_menu_item_text; + global::Xamarin.Forms.Platform.Resource.Id.design_navigation_view = global::HelloworldXamarin.Droid.Resource.Id.design_navigation_view; + global::Xamarin.Forms.Platform.Resource.Id.disableHome = global::HelloworldXamarin.Droid.Resource.Id.disableHome; + global::Xamarin.Forms.Platform.Resource.Id.edit_query = global::HelloworldXamarin.Droid.Resource.Id.edit_query; + global::Xamarin.Forms.Platform.Resource.Id.end = global::HelloworldXamarin.Droid.Resource.Id.end; + global::Xamarin.Forms.Platform.Resource.Id.end_padder = global::HelloworldXamarin.Droid.Resource.Id.end_padder; + global::Xamarin.Forms.Platform.Resource.Id.enterAlways = global::HelloworldXamarin.Droid.Resource.Id.enterAlways; + global::Xamarin.Forms.Platform.Resource.Id.enterAlwaysCollapsed = global::HelloworldXamarin.Droid.Resource.Id.enterAlwaysCollapsed; + global::Xamarin.Forms.Platform.Resource.Id.exitUntilCollapsed = global::HelloworldXamarin.Droid.Resource.Id.exitUntilCollapsed; + global::Xamarin.Forms.Platform.Resource.Id.expanded_menu = global::HelloworldXamarin.Droid.Resource.Id.expanded_menu; + global::Xamarin.Forms.Platform.Resource.Id.expand_activities_button = global::HelloworldXamarin.Droid.Resource.Id.expand_activities_button; + global::Xamarin.Forms.Platform.Resource.Id.fill = global::HelloworldXamarin.Droid.Resource.Id.fill; + global::Xamarin.Forms.Platform.Resource.Id.filled = global::HelloworldXamarin.Droid.Resource.Id.filled; + global::Xamarin.Forms.Platform.Resource.Id.fill_horizontal = global::HelloworldXamarin.Droid.Resource.Id.fill_horizontal; + global::Xamarin.Forms.Platform.Resource.Id.fill_vertical = global::HelloworldXamarin.Droid.Resource.Id.fill_vertical; + global::Xamarin.Forms.Platform.Resource.Id.@fixed = global::HelloworldXamarin.Droid.Resource.Id.@fixed; + global::Xamarin.Forms.Platform.Resource.Id.flyoutcontent_appbar = global::HelloworldXamarin.Droid.Resource.Id.flyoutcontent_appbar; + global::Xamarin.Forms.Platform.Resource.Id.flyoutcontent_recycler = global::HelloworldXamarin.Droid.Resource.Id.flyoutcontent_recycler; + global::Xamarin.Forms.Platform.Resource.Id.forever = global::HelloworldXamarin.Droid.Resource.Id.forever; + global::Xamarin.Forms.Platform.Resource.Id.FUNCTION = global::HelloworldXamarin.Droid.Resource.Id.FUNCTION; + global::Xamarin.Forms.Platform.Resource.Id.ghost_view = global::HelloworldXamarin.Droid.Resource.Id.ghost_view; + global::Xamarin.Forms.Platform.Resource.Id.group_divider = global::HelloworldXamarin.Droid.Resource.Id.group_divider; + global::Xamarin.Forms.Platform.Resource.Id.home = global::HelloworldXamarin.Droid.Resource.Id.home; + global::Xamarin.Forms.Platform.Resource.Id.homeAsUp = global::HelloworldXamarin.Droid.Resource.Id.homeAsUp; + global::Xamarin.Forms.Platform.Resource.Id.icon = global::HelloworldXamarin.Droid.Resource.Id.icon; + global::Xamarin.Forms.Platform.Resource.Id.icon_group = global::HelloworldXamarin.Droid.Resource.Id.icon_group; + global::Xamarin.Forms.Platform.Resource.Id.ifRoom = global::HelloworldXamarin.Droid.Resource.Id.ifRoom; + global::Xamarin.Forms.Platform.Resource.Id.image = global::HelloworldXamarin.Droid.Resource.Id.image; + global::Xamarin.Forms.Platform.Resource.Id.info = global::HelloworldXamarin.Droid.Resource.Id.info; + global::Xamarin.Forms.Platform.Resource.Id.italic = global::HelloworldXamarin.Droid.Resource.Id.italic; + global::Xamarin.Forms.Platform.Resource.Id.item_touch_helper_previous_elevation = global::HelloworldXamarin.Droid.Resource.Id.item_touch_helper_previous_elevation; + global::Xamarin.Forms.Platform.Resource.Id.labeled = global::HelloworldXamarin.Droid.Resource.Id.labeled; + global::Xamarin.Forms.Platform.Resource.Id.largeLabel = global::HelloworldXamarin.Droid.Resource.Id.largeLabel; + global::Xamarin.Forms.Platform.Resource.Id.left = global::HelloworldXamarin.Droid.Resource.Id.left; + global::Xamarin.Forms.Platform.Resource.Id.line1 = global::HelloworldXamarin.Droid.Resource.Id.line1; + global::Xamarin.Forms.Platform.Resource.Id.line3 = global::HelloworldXamarin.Droid.Resource.Id.line3; + global::Xamarin.Forms.Platform.Resource.Id.listMode = global::HelloworldXamarin.Droid.Resource.Id.listMode; + global::Xamarin.Forms.Platform.Resource.Id.list_item = global::HelloworldXamarin.Droid.Resource.Id.list_item; + global::Xamarin.Forms.Platform.Resource.Id.main_appbar = global::HelloworldXamarin.Droid.Resource.Id.main_appbar; + global::Xamarin.Forms.Platform.Resource.Id.main_tablayout = global::HelloworldXamarin.Droid.Resource.Id.main_tablayout; + global::Xamarin.Forms.Platform.Resource.Id.main_toolbar = global::HelloworldXamarin.Droid.Resource.Id.main_toolbar; + global::Xamarin.Forms.Platform.Resource.Id.main_viewpager = global::HelloworldXamarin.Droid.Resource.Id.main_viewpager; + global::Xamarin.Forms.Platform.Resource.Id.masked = global::HelloworldXamarin.Droid.Resource.Id.masked; + global::Xamarin.Forms.Platform.Resource.Id.media_actions = global::HelloworldXamarin.Droid.Resource.Id.media_actions; + global::Xamarin.Forms.Platform.Resource.Id.message = global::HelloworldXamarin.Droid.Resource.Id.message; + global::Xamarin.Forms.Platform.Resource.Id.META = global::HelloworldXamarin.Droid.Resource.Id.META; + global::Xamarin.Forms.Platform.Resource.Id.middle = global::HelloworldXamarin.Droid.Resource.Id.middle; + global::Xamarin.Forms.Platform.Resource.Id.mini = global::HelloworldXamarin.Droid.Resource.Id.mini; + global::Xamarin.Forms.Platform.Resource.Id.mtrl_child_content_container = global::HelloworldXamarin.Droid.Resource.Id.mtrl_child_content_container; + global::Xamarin.Forms.Platform.Resource.Id.mtrl_internal_children_alpha_tag = global::HelloworldXamarin.Droid.Resource.Id.mtrl_internal_children_alpha_tag; + global::Xamarin.Forms.Platform.Resource.Id.multiply = global::HelloworldXamarin.Droid.Resource.Id.multiply; + global::Xamarin.Forms.Platform.Resource.Id.navigation_header_container = global::HelloworldXamarin.Droid.Resource.Id.navigation_header_container; + global::Xamarin.Forms.Platform.Resource.Id.never = global::HelloworldXamarin.Droid.Resource.Id.never; + global::Xamarin.Forms.Platform.Resource.Id.none = global::HelloworldXamarin.Droid.Resource.Id.none; + global::Xamarin.Forms.Platform.Resource.Id.normal = global::HelloworldXamarin.Droid.Resource.Id.normal; + global::Xamarin.Forms.Platform.Resource.Id.notification_background = global::HelloworldXamarin.Droid.Resource.Id.notification_background; + global::Xamarin.Forms.Platform.Resource.Id.notification_main_column = global::HelloworldXamarin.Droid.Resource.Id.notification_main_column; + global::Xamarin.Forms.Platform.Resource.Id.notification_main_column_container = global::HelloworldXamarin.Droid.Resource.Id.notification_main_column_container; + global::Xamarin.Forms.Platform.Resource.Id.outline = global::HelloworldXamarin.Droid.Resource.Id.outline; + global::Xamarin.Forms.Platform.Resource.Id.parallax = global::HelloworldXamarin.Droid.Resource.Id.parallax; + global::Xamarin.Forms.Platform.Resource.Id.parentPanel = global::HelloworldXamarin.Droid.Resource.Id.parentPanel; + global::Xamarin.Forms.Platform.Resource.Id.parent_matrix = global::HelloworldXamarin.Droid.Resource.Id.parent_matrix; + global::Xamarin.Forms.Platform.Resource.Id.pin = global::HelloworldXamarin.Droid.Resource.Id.pin; + global::Xamarin.Forms.Platform.Resource.Id.progress_circular = global::HelloworldXamarin.Droid.Resource.Id.progress_circular; + global::Xamarin.Forms.Platform.Resource.Id.progress_horizontal = global::HelloworldXamarin.Droid.Resource.Id.progress_horizontal; + global::Xamarin.Forms.Platform.Resource.Id.radio = global::HelloworldXamarin.Droid.Resource.Id.radio; + global::Xamarin.Forms.Platform.Resource.Id.right = global::HelloworldXamarin.Droid.Resource.Id.right; + global::Xamarin.Forms.Platform.Resource.Id.right_icon = global::HelloworldXamarin.Droid.Resource.Id.right_icon; + global::Xamarin.Forms.Platform.Resource.Id.right_side = global::HelloworldXamarin.Droid.Resource.Id.right_side; + global::Xamarin.Forms.Platform.Resource.Id.save_image_matrix = global::HelloworldXamarin.Droid.Resource.Id.save_image_matrix; + global::Xamarin.Forms.Platform.Resource.Id.save_non_transition_alpha = global::HelloworldXamarin.Droid.Resource.Id.save_non_transition_alpha; + global::Xamarin.Forms.Platform.Resource.Id.save_scale_type = global::HelloworldXamarin.Droid.Resource.Id.save_scale_type; + global::Xamarin.Forms.Platform.Resource.Id.screen = global::HelloworldXamarin.Droid.Resource.Id.screen; + global::Xamarin.Forms.Platform.Resource.Id.scroll = global::HelloworldXamarin.Droid.Resource.Id.scroll; + global::Xamarin.Forms.Platform.Resource.Id.scrollable = global::HelloworldXamarin.Droid.Resource.Id.scrollable; + global::Xamarin.Forms.Platform.Resource.Id.scrollIndicatorDown = global::HelloworldXamarin.Droid.Resource.Id.scrollIndicatorDown; + global::Xamarin.Forms.Platform.Resource.Id.scrollIndicatorUp = global::HelloworldXamarin.Droid.Resource.Id.scrollIndicatorUp; + global::Xamarin.Forms.Platform.Resource.Id.scrollView = global::HelloworldXamarin.Droid.Resource.Id.scrollView; + global::Xamarin.Forms.Platform.Resource.Id.search_badge = global::HelloworldXamarin.Droid.Resource.Id.search_badge; + global::Xamarin.Forms.Platform.Resource.Id.search_bar = global::HelloworldXamarin.Droid.Resource.Id.search_bar; + global::Xamarin.Forms.Platform.Resource.Id.search_button = global::HelloworldXamarin.Droid.Resource.Id.search_button; + global::Xamarin.Forms.Platform.Resource.Id.search_close_btn = global::HelloworldXamarin.Droid.Resource.Id.search_close_btn; + global::Xamarin.Forms.Platform.Resource.Id.search_edit_frame = global::HelloworldXamarin.Droid.Resource.Id.search_edit_frame; + global::Xamarin.Forms.Platform.Resource.Id.search_go_btn = global::HelloworldXamarin.Droid.Resource.Id.search_go_btn; + global::Xamarin.Forms.Platform.Resource.Id.search_mag_icon = global::HelloworldXamarin.Droid.Resource.Id.search_mag_icon; + global::Xamarin.Forms.Platform.Resource.Id.search_plate = global::HelloworldXamarin.Droid.Resource.Id.search_plate; + global::Xamarin.Forms.Platform.Resource.Id.search_src_text = global::HelloworldXamarin.Droid.Resource.Id.search_src_text; + global::Xamarin.Forms.Platform.Resource.Id.search_voice_btn = global::HelloworldXamarin.Droid.Resource.Id.search_voice_btn; + global::Xamarin.Forms.Platform.Resource.Id.selected = global::HelloworldXamarin.Droid.Resource.Id.selected; + global::Xamarin.Forms.Platform.Resource.Id.select_dialog_listview = global::HelloworldXamarin.Droid.Resource.Id.select_dialog_listview; + global::Xamarin.Forms.Platform.Resource.Id.shellcontent_appbar = global::HelloworldXamarin.Droid.Resource.Id.shellcontent_appbar; + global::Xamarin.Forms.Platform.Resource.Id.shellcontent_toolbar = global::HelloworldXamarin.Droid.Resource.Id.shellcontent_toolbar; + global::Xamarin.Forms.Platform.Resource.Id.SHIFT = global::HelloworldXamarin.Droid.Resource.Id.SHIFT; + global::Xamarin.Forms.Platform.Resource.Id.shortcut = global::HelloworldXamarin.Droid.Resource.Id.shortcut; + global::Xamarin.Forms.Platform.Resource.Id.showCustom = global::HelloworldXamarin.Droid.Resource.Id.showCustom; + global::Xamarin.Forms.Platform.Resource.Id.showHome = global::HelloworldXamarin.Droid.Resource.Id.showHome; + global::Xamarin.Forms.Platform.Resource.Id.showTitle = global::HelloworldXamarin.Droid.Resource.Id.showTitle; + global::Xamarin.Forms.Platform.Resource.Id.smallLabel = global::HelloworldXamarin.Droid.Resource.Id.smallLabel; + global::Xamarin.Forms.Platform.Resource.Id.snackbar_action = global::HelloworldXamarin.Droid.Resource.Id.snackbar_action; + global::Xamarin.Forms.Platform.Resource.Id.snackbar_text = global::HelloworldXamarin.Droid.Resource.Id.snackbar_text; + global::Xamarin.Forms.Platform.Resource.Id.snap = global::HelloworldXamarin.Droid.Resource.Id.snap; + global::Xamarin.Forms.Platform.Resource.Id.snapMargins = global::HelloworldXamarin.Droid.Resource.Id.snapMargins; + global::Xamarin.Forms.Platform.Resource.Id.spacer = global::HelloworldXamarin.Droid.Resource.Id.spacer; + global::Xamarin.Forms.Platform.Resource.Id.split_action_bar = global::HelloworldXamarin.Droid.Resource.Id.split_action_bar; + global::Xamarin.Forms.Platform.Resource.Id.src_atop = global::HelloworldXamarin.Droid.Resource.Id.src_atop; + global::Xamarin.Forms.Platform.Resource.Id.src_in = global::HelloworldXamarin.Droid.Resource.Id.src_in; + global::Xamarin.Forms.Platform.Resource.Id.src_over = global::HelloworldXamarin.Droid.Resource.Id.src_over; + global::Xamarin.Forms.Platform.Resource.Id.start = global::HelloworldXamarin.Droid.Resource.Id.start; + global::Xamarin.Forms.Platform.Resource.Id.status_bar_latest_event_content = global::HelloworldXamarin.Droid.Resource.Id.status_bar_latest_event_content; + global::Xamarin.Forms.Platform.Resource.Id.stretch = global::HelloworldXamarin.Droid.Resource.Id.stretch; + global::Xamarin.Forms.Platform.Resource.Id.submenuarrow = global::HelloworldXamarin.Droid.Resource.Id.submenuarrow; + global::Xamarin.Forms.Platform.Resource.Id.submit_area = global::HelloworldXamarin.Droid.Resource.Id.submit_area; + global::Xamarin.Forms.Platform.Resource.Id.SYM = global::HelloworldXamarin.Droid.Resource.Id.SYM; + global::Xamarin.Forms.Platform.Resource.Id.tabMode = global::HelloworldXamarin.Droid.Resource.Id.tabMode; + global::Xamarin.Forms.Platform.Resource.Id.tag_transition_group = global::HelloworldXamarin.Droid.Resource.Id.tag_transition_group; + global::Xamarin.Forms.Platform.Resource.Id.tag_unhandled_key_event_manager = global::HelloworldXamarin.Droid.Resource.Id.tag_unhandled_key_event_manager; + global::Xamarin.Forms.Platform.Resource.Id.tag_unhandled_key_listeners = global::HelloworldXamarin.Droid.Resource.Id.tag_unhandled_key_listeners; + global::Xamarin.Forms.Platform.Resource.Id.text = global::HelloworldXamarin.Droid.Resource.Id.text; + global::Xamarin.Forms.Platform.Resource.Id.text2 = global::HelloworldXamarin.Droid.Resource.Id.text2; + global::Xamarin.Forms.Platform.Resource.Id.textinput_counter = global::HelloworldXamarin.Droid.Resource.Id.textinput_counter; + global::Xamarin.Forms.Platform.Resource.Id.textinput_error = global::HelloworldXamarin.Droid.Resource.Id.textinput_error; + global::Xamarin.Forms.Platform.Resource.Id.textinput_helper_text = global::HelloworldXamarin.Droid.Resource.Id.textinput_helper_text; + global::Xamarin.Forms.Platform.Resource.Id.textSpacerNoButtons = global::HelloworldXamarin.Droid.Resource.Id.textSpacerNoButtons; + global::Xamarin.Forms.Platform.Resource.Id.textSpacerNoTitle = global::HelloworldXamarin.Droid.Resource.Id.textSpacerNoTitle; + global::Xamarin.Forms.Platform.Resource.Id.textStart = global::HelloworldXamarin.Droid.Resource.Id.textStart; + global::Xamarin.Forms.Platform.Resource.Id.text_input_password_toggle = global::HelloworldXamarin.Droid.Resource.Id.text_input_password_toggle; + global::Xamarin.Forms.Platform.Resource.Id.time = global::HelloworldXamarin.Droid.Resource.Id.time; + global::Xamarin.Forms.Platform.Resource.Id.title = global::HelloworldXamarin.Droid.Resource.Id.title; + global::Xamarin.Forms.Platform.Resource.Id.titleDividerNoCustom = global::HelloworldXamarin.Droid.Resource.Id.titleDividerNoCustom; + global::Xamarin.Forms.Platform.Resource.Id.title_template = global::HelloworldXamarin.Droid.Resource.Id.title_template; + global::Xamarin.Forms.Platform.Resource.Id.top = global::HelloworldXamarin.Droid.Resource.Id.top; + global::Xamarin.Forms.Platform.Resource.Id.topPanel = global::HelloworldXamarin.Droid.Resource.Id.topPanel; + global::Xamarin.Forms.Platform.Resource.Id.touch_outside = global::HelloworldXamarin.Droid.Resource.Id.touch_outside; + global::Xamarin.Forms.Platform.Resource.Id.transition_current_scene = global::HelloworldXamarin.Droid.Resource.Id.transition_current_scene; + global::Xamarin.Forms.Platform.Resource.Id.transition_layout_save = global::HelloworldXamarin.Droid.Resource.Id.transition_layout_save; + global::Xamarin.Forms.Platform.Resource.Id.transition_position = global::HelloworldXamarin.Droid.Resource.Id.transition_position; + global::Xamarin.Forms.Platform.Resource.Id.transition_scene_layoutid_cache = global::HelloworldXamarin.Droid.Resource.Id.transition_scene_layoutid_cache; + global::Xamarin.Forms.Platform.Resource.Id.transition_transform = global::HelloworldXamarin.Droid.Resource.Id.transition_transform; + global::Xamarin.Forms.Platform.Resource.Id.uniform = global::HelloworldXamarin.Droid.Resource.Id.uniform; + global::Xamarin.Forms.Platform.Resource.Id.unlabeled = global::HelloworldXamarin.Droid.Resource.Id.unlabeled; + global::Xamarin.Forms.Platform.Resource.Id.up = global::HelloworldXamarin.Droid.Resource.Id.up; + global::Xamarin.Forms.Platform.Resource.Id.useLogo = global::HelloworldXamarin.Droid.Resource.Id.useLogo; + global::Xamarin.Forms.Platform.Resource.Id.view_offset_helper = global::HelloworldXamarin.Droid.Resource.Id.view_offset_helper; + global::Xamarin.Forms.Platform.Resource.Id.visible = global::HelloworldXamarin.Droid.Resource.Id.visible; + global::Xamarin.Forms.Platform.Resource.Id.withText = global::HelloworldXamarin.Droid.Resource.Id.withText; + global::Xamarin.Forms.Platform.Resource.Id.wrap_content = global::HelloworldXamarin.Droid.Resource.Id.wrap_content; + global::Xamarin.Forms.Platform.Resource.Integer.abc_config_activityDefaultDur = global::HelloworldXamarin.Droid.Resource.Integer.abc_config_activityDefaultDur; + global::Xamarin.Forms.Platform.Resource.Integer.abc_config_activityShortDur = global::HelloworldXamarin.Droid.Resource.Integer.abc_config_activityShortDur; + global::Xamarin.Forms.Platform.Resource.Integer.app_bar_elevation_anim_duration = global::HelloworldXamarin.Droid.Resource.Integer.app_bar_elevation_anim_duration; + global::Xamarin.Forms.Platform.Resource.Integer.bottom_sheet_slide_duration = global::HelloworldXamarin.Droid.Resource.Integer.bottom_sheet_slide_duration; + global::Xamarin.Forms.Platform.Resource.Integer.cancel_button_image_alpha = global::HelloworldXamarin.Droid.Resource.Integer.cancel_button_image_alpha; + global::Xamarin.Forms.Platform.Resource.Integer.config_tooltipAnimTime = global::HelloworldXamarin.Droid.Resource.Integer.config_tooltipAnimTime; + global::Xamarin.Forms.Platform.Resource.Integer.design_snackbar_text_max_lines = global::HelloworldXamarin.Droid.Resource.Integer.design_snackbar_text_max_lines; + global::Xamarin.Forms.Platform.Resource.Integer.design_tab_indicator_anim_duration_ms = global::HelloworldXamarin.Droid.Resource.Integer.design_tab_indicator_anim_duration_ms; + global::Xamarin.Forms.Platform.Resource.Integer.hide_password_duration = global::HelloworldXamarin.Droid.Resource.Integer.hide_password_duration; + global::Xamarin.Forms.Platform.Resource.Integer.mtrl_btn_anim_delay_ms = global::HelloworldXamarin.Droid.Resource.Integer.mtrl_btn_anim_delay_ms; + global::Xamarin.Forms.Platform.Resource.Integer.mtrl_btn_anim_duration_ms = global::HelloworldXamarin.Droid.Resource.Integer.mtrl_btn_anim_duration_ms; + global::Xamarin.Forms.Platform.Resource.Integer.mtrl_chip_anim_duration = global::HelloworldXamarin.Droid.Resource.Integer.mtrl_chip_anim_duration; + global::Xamarin.Forms.Platform.Resource.Integer.mtrl_tab_indicator_anim_duration_ms = global::HelloworldXamarin.Droid.Resource.Integer.mtrl_tab_indicator_anim_duration_ms; + global::Xamarin.Forms.Platform.Resource.Integer.show_password_duration = global::HelloworldXamarin.Droid.Resource.Integer.show_password_duration; + global::Xamarin.Forms.Platform.Resource.Integer.status_bar_notification_info_maxnum = global::HelloworldXamarin.Droid.Resource.Integer.status_bar_notification_info_maxnum; + global::Xamarin.Forms.Platform.Resource.Interpolator.mtrl_fast_out_linear_in = global::HelloworldXamarin.Droid.Resource.Interpolator.mtrl_fast_out_linear_in; + global::Xamarin.Forms.Platform.Resource.Interpolator.mtrl_fast_out_slow_in = global::HelloworldXamarin.Droid.Resource.Interpolator.mtrl_fast_out_slow_in; + global::Xamarin.Forms.Platform.Resource.Interpolator.mtrl_linear = global::HelloworldXamarin.Droid.Resource.Interpolator.mtrl_linear; + global::Xamarin.Forms.Platform.Resource.Interpolator.mtrl_linear_out_slow_in = global::HelloworldXamarin.Droid.Resource.Interpolator.mtrl_linear_out_slow_in; + global::Xamarin.Forms.Platform.Resource.Layout.abc_action_bar_title_item = global::HelloworldXamarin.Droid.Resource.Layout.abc_action_bar_title_item; + global::Xamarin.Forms.Platform.Resource.Layout.abc_action_bar_up_container = global::HelloworldXamarin.Droid.Resource.Layout.abc_action_bar_up_container; + global::Xamarin.Forms.Platform.Resource.Layout.abc_action_menu_item_layout = global::HelloworldXamarin.Droid.Resource.Layout.abc_action_menu_item_layout; + global::Xamarin.Forms.Platform.Resource.Layout.abc_action_menu_layout = global::HelloworldXamarin.Droid.Resource.Layout.abc_action_menu_layout; + global::Xamarin.Forms.Platform.Resource.Layout.abc_action_mode_bar = global::HelloworldXamarin.Droid.Resource.Layout.abc_action_mode_bar; + global::Xamarin.Forms.Platform.Resource.Layout.abc_action_mode_close_item_material = global::HelloworldXamarin.Droid.Resource.Layout.abc_action_mode_close_item_material; + global::Xamarin.Forms.Platform.Resource.Layout.abc_activity_chooser_view = global::HelloworldXamarin.Droid.Resource.Layout.abc_activity_chooser_view; + global::Xamarin.Forms.Platform.Resource.Layout.abc_activity_chooser_view_list_item = global::HelloworldXamarin.Droid.Resource.Layout.abc_activity_chooser_view_list_item; + global::Xamarin.Forms.Platform.Resource.Layout.abc_alert_dialog_button_bar_material = global::HelloworldXamarin.Droid.Resource.Layout.abc_alert_dialog_button_bar_material; + global::Xamarin.Forms.Platform.Resource.Layout.abc_alert_dialog_material = global::HelloworldXamarin.Droid.Resource.Layout.abc_alert_dialog_material; + global::Xamarin.Forms.Platform.Resource.Layout.abc_alert_dialog_title_material = global::HelloworldXamarin.Droid.Resource.Layout.abc_alert_dialog_title_material; + global::Xamarin.Forms.Platform.Resource.Layout.abc_cascading_menu_item_layout = global::HelloworldXamarin.Droid.Resource.Layout.abc_cascading_menu_item_layout; + global::Xamarin.Forms.Platform.Resource.Layout.abc_dialog_title_material = global::HelloworldXamarin.Droid.Resource.Layout.abc_dialog_title_material; + global::Xamarin.Forms.Platform.Resource.Layout.abc_expanded_menu_layout = global::HelloworldXamarin.Droid.Resource.Layout.abc_expanded_menu_layout; + global::Xamarin.Forms.Platform.Resource.Layout.abc_list_menu_item_checkbox = global::HelloworldXamarin.Droid.Resource.Layout.abc_list_menu_item_checkbox; + global::Xamarin.Forms.Platform.Resource.Layout.abc_list_menu_item_icon = global::HelloworldXamarin.Droid.Resource.Layout.abc_list_menu_item_icon; + global::Xamarin.Forms.Platform.Resource.Layout.abc_list_menu_item_layout = global::HelloworldXamarin.Droid.Resource.Layout.abc_list_menu_item_layout; + global::Xamarin.Forms.Platform.Resource.Layout.abc_list_menu_item_radio = global::HelloworldXamarin.Droid.Resource.Layout.abc_list_menu_item_radio; + global::Xamarin.Forms.Platform.Resource.Layout.abc_popup_menu_header_item_layout = global::HelloworldXamarin.Droid.Resource.Layout.abc_popup_menu_header_item_layout; + global::Xamarin.Forms.Platform.Resource.Layout.abc_popup_menu_item_layout = global::HelloworldXamarin.Droid.Resource.Layout.abc_popup_menu_item_layout; + global::Xamarin.Forms.Platform.Resource.Layout.abc_screen_content_include = global::HelloworldXamarin.Droid.Resource.Layout.abc_screen_content_include; + global::Xamarin.Forms.Platform.Resource.Layout.abc_screen_simple = global::HelloworldXamarin.Droid.Resource.Layout.abc_screen_simple; + global::Xamarin.Forms.Platform.Resource.Layout.abc_screen_simple_overlay_action_mode = global::HelloworldXamarin.Droid.Resource.Layout.abc_screen_simple_overlay_action_mode; + global::Xamarin.Forms.Platform.Resource.Layout.abc_screen_toolbar = global::HelloworldXamarin.Droid.Resource.Layout.abc_screen_toolbar; + global::Xamarin.Forms.Platform.Resource.Layout.abc_search_dropdown_item_icons_2line = global::HelloworldXamarin.Droid.Resource.Layout.abc_search_dropdown_item_icons_2line; + global::Xamarin.Forms.Platform.Resource.Layout.abc_search_view = global::HelloworldXamarin.Droid.Resource.Layout.abc_search_view; + global::Xamarin.Forms.Platform.Resource.Layout.abc_select_dialog_material = global::HelloworldXamarin.Droid.Resource.Layout.abc_select_dialog_material; + global::Xamarin.Forms.Platform.Resource.Layout.abc_tooltip = global::HelloworldXamarin.Droid.Resource.Layout.abc_tooltip; + global::Xamarin.Forms.Platform.Resource.Layout.BottomTabLayout = global::HelloworldXamarin.Droid.Resource.Layout.BottomTabLayout; + global::Xamarin.Forms.Platform.Resource.Layout.design_bottom_navigation_item = global::HelloworldXamarin.Droid.Resource.Layout.design_bottom_navigation_item; + global::Xamarin.Forms.Platform.Resource.Layout.design_bottom_sheet_dialog = global::HelloworldXamarin.Droid.Resource.Layout.design_bottom_sheet_dialog; + global::Xamarin.Forms.Platform.Resource.Layout.design_layout_snackbar = global::HelloworldXamarin.Droid.Resource.Layout.design_layout_snackbar; + global::Xamarin.Forms.Platform.Resource.Layout.design_layout_snackbar_include = global::HelloworldXamarin.Droid.Resource.Layout.design_layout_snackbar_include; + global::Xamarin.Forms.Platform.Resource.Layout.design_layout_tab_icon = global::HelloworldXamarin.Droid.Resource.Layout.design_layout_tab_icon; + global::Xamarin.Forms.Platform.Resource.Layout.design_layout_tab_text = global::HelloworldXamarin.Droid.Resource.Layout.design_layout_tab_text; + global::Xamarin.Forms.Platform.Resource.Layout.design_menu_item_action_area = global::HelloworldXamarin.Droid.Resource.Layout.design_menu_item_action_area; + global::Xamarin.Forms.Platform.Resource.Layout.design_navigation_item = global::HelloworldXamarin.Droid.Resource.Layout.design_navigation_item; + global::Xamarin.Forms.Platform.Resource.Layout.design_navigation_item_header = global::HelloworldXamarin.Droid.Resource.Layout.design_navigation_item_header; + global::Xamarin.Forms.Platform.Resource.Layout.design_navigation_item_separator = global::HelloworldXamarin.Droid.Resource.Layout.design_navigation_item_separator; + global::Xamarin.Forms.Platform.Resource.Layout.design_navigation_item_subheader = global::HelloworldXamarin.Droid.Resource.Layout.design_navigation_item_subheader; + global::Xamarin.Forms.Platform.Resource.Layout.design_navigation_menu = global::HelloworldXamarin.Droid.Resource.Layout.design_navigation_menu; + global::Xamarin.Forms.Platform.Resource.Layout.design_navigation_menu_item = global::HelloworldXamarin.Droid.Resource.Layout.design_navigation_menu_item; + global::Xamarin.Forms.Platform.Resource.Layout.design_text_input_password_icon = global::HelloworldXamarin.Droid.Resource.Layout.design_text_input_password_icon; + global::Xamarin.Forms.Platform.Resource.Layout.FlyoutContent = global::HelloworldXamarin.Droid.Resource.Layout.FlyoutContent; + global::Xamarin.Forms.Platform.Resource.Layout.mtrl_layout_snackbar = global::HelloworldXamarin.Droid.Resource.Layout.mtrl_layout_snackbar; + global::Xamarin.Forms.Platform.Resource.Layout.mtrl_layout_snackbar_include = global::HelloworldXamarin.Droid.Resource.Layout.mtrl_layout_snackbar_include; + global::Xamarin.Forms.Platform.Resource.Layout.notification_action = global::HelloworldXamarin.Droid.Resource.Layout.notification_action; + global::Xamarin.Forms.Platform.Resource.Layout.notification_action_tombstone = global::HelloworldXamarin.Droid.Resource.Layout.notification_action_tombstone; + global::Xamarin.Forms.Platform.Resource.Layout.notification_media_action = global::HelloworldXamarin.Droid.Resource.Layout.notification_media_action; + global::Xamarin.Forms.Platform.Resource.Layout.notification_media_cancel_action = global::HelloworldXamarin.Droid.Resource.Layout.notification_media_cancel_action; + global::Xamarin.Forms.Platform.Resource.Layout.notification_template_big_media = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_big_media; + global::Xamarin.Forms.Platform.Resource.Layout.notification_template_big_media_custom = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_big_media_custom; + global::Xamarin.Forms.Platform.Resource.Layout.notification_template_big_media_narrow = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_big_media_narrow; + global::Xamarin.Forms.Platform.Resource.Layout.notification_template_big_media_narrow_custom = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_big_media_narrow_custom; + global::Xamarin.Forms.Platform.Resource.Layout.notification_template_custom_big = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_custom_big; + global::Xamarin.Forms.Platform.Resource.Layout.notification_template_icon_group = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_icon_group; + global::Xamarin.Forms.Platform.Resource.Layout.notification_template_lines_media = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_lines_media; + global::Xamarin.Forms.Platform.Resource.Layout.notification_template_media = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_media; + global::Xamarin.Forms.Platform.Resource.Layout.notification_template_media_custom = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_media_custom; + global::Xamarin.Forms.Platform.Resource.Layout.notification_template_part_chronometer = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_part_chronometer; + global::Xamarin.Forms.Platform.Resource.Layout.notification_template_part_time = global::HelloworldXamarin.Droid.Resource.Layout.notification_template_part_time; + global::Xamarin.Forms.Platform.Resource.Layout.RootLayout = global::HelloworldXamarin.Droid.Resource.Layout.RootLayout; + global::Xamarin.Forms.Platform.Resource.Layout.select_dialog_item_material = global::HelloworldXamarin.Droid.Resource.Layout.select_dialog_item_material; + global::Xamarin.Forms.Platform.Resource.Layout.select_dialog_multichoice_material = global::HelloworldXamarin.Droid.Resource.Layout.select_dialog_multichoice_material; + global::Xamarin.Forms.Platform.Resource.Layout.select_dialog_singlechoice_material = global::HelloworldXamarin.Droid.Resource.Layout.select_dialog_singlechoice_material; + global::Xamarin.Forms.Platform.Resource.Layout.ShellContent = global::HelloworldXamarin.Droid.Resource.Layout.ShellContent; + global::Xamarin.Forms.Platform.Resource.Layout.support_simple_spinner_dropdown_item = global::HelloworldXamarin.Droid.Resource.Layout.support_simple_spinner_dropdown_item; + global::Xamarin.Forms.Platform.Resource.String.abc_action_bar_home_description = global::HelloworldXamarin.Droid.Resource.String.abc_action_bar_home_description; + global::Xamarin.Forms.Platform.Resource.String.abc_action_bar_up_description = global::HelloworldXamarin.Droid.Resource.String.abc_action_bar_up_description; + global::Xamarin.Forms.Platform.Resource.String.abc_action_menu_overflow_description = global::HelloworldXamarin.Droid.Resource.String.abc_action_menu_overflow_description; + global::Xamarin.Forms.Platform.Resource.String.abc_action_mode_done = global::HelloworldXamarin.Droid.Resource.String.abc_action_mode_done; + global::Xamarin.Forms.Platform.Resource.String.abc_activitychooserview_choose_application = global::HelloworldXamarin.Droid.Resource.String.abc_activitychooserview_choose_application; + global::Xamarin.Forms.Platform.Resource.String.abc_activity_chooser_view_see_all = global::HelloworldXamarin.Droid.Resource.String.abc_activity_chooser_view_see_all; + global::Xamarin.Forms.Platform.Resource.String.abc_capital_off = global::HelloworldXamarin.Droid.Resource.String.abc_capital_off; + global::Xamarin.Forms.Platform.Resource.String.abc_capital_on = global::HelloworldXamarin.Droid.Resource.String.abc_capital_on; + global::Xamarin.Forms.Platform.Resource.String.abc_font_family_body_1_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_body_1_material; + global::Xamarin.Forms.Platform.Resource.String.abc_font_family_body_2_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_body_2_material; + global::Xamarin.Forms.Platform.Resource.String.abc_font_family_button_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_button_material; + global::Xamarin.Forms.Platform.Resource.String.abc_font_family_caption_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_caption_material; + global::Xamarin.Forms.Platform.Resource.String.abc_font_family_display_1_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_display_1_material; + global::Xamarin.Forms.Platform.Resource.String.abc_font_family_display_2_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_display_2_material; + global::Xamarin.Forms.Platform.Resource.String.abc_font_family_display_3_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_display_3_material; + global::Xamarin.Forms.Platform.Resource.String.abc_font_family_display_4_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_display_4_material; + global::Xamarin.Forms.Platform.Resource.String.abc_font_family_headline_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_headline_material; + global::Xamarin.Forms.Platform.Resource.String.abc_font_family_menu_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_menu_material; + global::Xamarin.Forms.Platform.Resource.String.abc_font_family_subhead_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_subhead_material; + global::Xamarin.Forms.Platform.Resource.String.abc_font_family_title_material = global::HelloworldXamarin.Droid.Resource.String.abc_font_family_title_material; + global::Xamarin.Forms.Platform.Resource.String.abc_menu_alt_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_alt_shortcut_label; + global::Xamarin.Forms.Platform.Resource.String.abc_menu_ctrl_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_ctrl_shortcut_label; + global::Xamarin.Forms.Platform.Resource.String.abc_menu_delete_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_delete_shortcut_label; + global::Xamarin.Forms.Platform.Resource.String.abc_menu_enter_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_enter_shortcut_label; + global::Xamarin.Forms.Platform.Resource.String.abc_menu_function_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_function_shortcut_label; + global::Xamarin.Forms.Platform.Resource.String.abc_menu_meta_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_meta_shortcut_label; + global::Xamarin.Forms.Platform.Resource.String.abc_menu_shift_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_shift_shortcut_label; + global::Xamarin.Forms.Platform.Resource.String.abc_menu_space_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_space_shortcut_label; + global::Xamarin.Forms.Platform.Resource.String.abc_menu_sym_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_menu_sym_shortcut_label; + global::Xamarin.Forms.Platform.Resource.String.abc_prepend_shortcut_label = global::HelloworldXamarin.Droid.Resource.String.abc_prepend_shortcut_label; + global::Xamarin.Forms.Platform.Resource.String.abc_searchview_description_clear = global::HelloworldXamarin.Droid.Resource.String.abc_searchview_description_clear; + global::Xamarin.Forms.Platform.Resource.String.abc_searchview_description_query = global::HelloworldXamarin.Droid.Resource.String.abc_searchview_description_query; + global::Xamarin.Forms.Platform.Resource.String.abc_searchview_description_search = global::HelloworldXamarin.Droid.Resource.String.abc_searchview_description_search; + global::Xamarin.Forms.Platform.Resource.String.abc_searchview_description_submit = global::HelloworldXamarin.Droid.Resource.String.abc_searchview_description_submit; + global::Xamarin.Forms.Platform.Resource.String.abc_searchview_description_voice = global::HelloworldXamarin.Droid.Resource.String.abc_searchview_description_voice; + global::Xamarin.Forms.Platform.Resource.String.abc_search_hint = global::HelloworldXamarin.Droid.Resource.String.abc_search_hint; + global::Xamarin.Forms.Platform.Resource.String.abc_shareactionprovider_share_with = global::HelloworldXamarin.Droid.Resource.String.abc_shareactionprovider_share_with; + global::Xamarin.Forms.Platform.Resource.String.abc_shareactionprovider_share_with_application = global::HelloworldXamarin.Droid.Resource.String.abc_shareactionprovider_share_with_application; + global::Xamarin.Forms.Platform.Resource.String.abc_toolbar_collapse_description = global::HelloworldXamarin.Droid.Resource.String.abc_toolbar_collapse_description; + global::Xamarin.Forms.Platform.Resource.String.appbar_scrolling_view_behavior = global::HelloworldXamarin.Droid.Resource.String.appbar_scrolling_view_behavior; + global::Xamarin.Forms.Platform.Resource.String.bottom_sheet_behavior = global::HelloworldXamarin.Droid.Resource.String.bottom_sheet_behavior; + global::Xamarin.Forms.Platform.Resource.String.character_counter_content_description = global::HelloworldXamarin.Droid.Resource.String.character_counter_content_description; + global::Xamarin.Forms.Platform.Resource.String.character_counter_pattern = global::HelloworldXamarin.Droid.Resource.String.character_counter_pattern; + global::Xamarin.Forms.Platform.Resource.String.fab_transformation_scrim_behavior = global::HelloworldXamarin.Droid.Resource.String.fab_transformation_scrim_behavior; + global::Xamarin.Forms.Platform.Resource.String.fab_transformation_sheet_behavior = global::HelloworldXamarin.Droid.Resource.String.fab_transformation_sheet_behavior; + global::Xamarin.Forms.Platform.Resource.String.hide_bottom_view_on_scroll_behavior = global::HelloworldXamarin.Droid.Resource.String.hide_bottom_view_on_scroll_behavior; + global::Xamarin.Forms.Platform.Resource.String.mtrl_chip_close_icon_content_description = global::HelloworldXamarin.Droid.Resource.String.mtrl_chip_close_icon_content_description; + global::Xamarin.Forms.Platform.Resource.String.password_toggle_content_description = global::HelloworldXamarin.Droid.Resource.String.password_toggle_content_description; + global::Xamarin.Forms.Platform.Resource.String.path_password_eye = global::HelloworldXamarin.Droid.Resource.String.path_password_eye; + global::Xamarin.Forms.Platform.Resource.String.path_password_eye_mask_strike_through = global::HelloworldXamarin.Droid.Resource.String.path_password_eye_mask_strike_through; + global::Xamarin.Forms.Platform.Resource.String.path_password_eye_mask_visible = global::HelloworldXamarin.Droid.Resource.String.path_password_eye_mask_visible; + global::Xamarin.Forms.Platform.Resource.String.path_password_strike_through = global::HelloworldXamarin.Droid.Resource.String.path_password_strike_through; + global::Xamarin.Forms.Platform.Resource.String.search_menu_title = global::HelloworldXamarin.Droid.Resource.String.search_menu_title; + global::Xamarin.Forms.Platform.Resource.String.status_bar_notification_info_overflow = global::HelloworldXamarin.Droid.Resource.String.status_bar_notification_info_overflow; + global::Xamarin.Forms.Platform.Resource.Style.AlertDialog_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.AlertDialog_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.AlertDialog_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.AlertDialog_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Animation_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Animation_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Animation_AppCompat_DropDownUp = global::HelloworldXamarin.Droid.Resource.Style.Animation_AppCompat_DropDownUp; + global::Xamarin.Forms.Platform.Resource.Style.Animation_AppCompat_Tooltip = global::HelloworldXamarin.Droid.Resource.Style.Animation_AppCompat_Tooltip; + global::Xamarin.Forms.Platform.Resource.Style.Animation_Design_BottomSheetDialog = global::HelloworldXamarin.Droid.Resource.Style.Animation_Design_BottomSheetDialog; + global::Xamarin.Forms.Platform.Resource.Style.AppCompatDialogStyle = global::HelloworldXamarin.Droid.Resource.Style.AppCompatDialogStyle; + global::Xamarin.Forms.Platform.Resource.Style.Base_AlertDialog_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_AlertDialog_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Base_AlertDialog_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_AlertDialog_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Base_Animation_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_Animation_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_Animation_AppCompat_DropDownUp = global::HelloworldXamarin.Droid.Resource.Style.Base_Animation_AppCompat_DropDownUp; + global::Xamarin.Forms.Platform.Resource.Style.Base_Animation_AppCompat_Tooltip = global::HelloworldXamarin.Droid.Resource.Style.Base_Animation_AppCompat_Tooltip; + global::Xamarin.Forms.Platform.Resource.Style.Base_CardView = global::HelloworldXamarin.Droid.Resource.Style.Base_CardView; + global::Xamarin.Forms.Platform.Resource.Style.Base_DialogWindowTitleBackground_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_DialogWindowTitleBackground_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Base_DialogWindowTitle_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_DialogWindowTitle_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Body1 = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Body1; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Body2 = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Body2; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Button = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Button; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Caption = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Caption; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Display1 = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display1; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Display2 = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display2; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Display3 = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display3; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Display4 = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Display4; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Headline = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Headline; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Large = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Large; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Large_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Large_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Large; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Small; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Medium = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Medium; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Medium_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Medium_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Menu = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Menu; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_SearchResult = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_SearchResult; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Subtitle; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Title = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_SearchResult_Title; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Small = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Small; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Small_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Small_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Subhead = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Subhead; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Subhead_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Subhead_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Title = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Title; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Title_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Title_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Tooltip = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Tooltip; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Menu = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Menu; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Subtitle; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Title = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_ActionMode_Title; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Borderless_Colored = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Borderless_Colored; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Colored = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Colored; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Button_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_DropDownItem = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_DropDownItem; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Header = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Header; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Large = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Large; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Small = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_PopupMenu_Small; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_Switch = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_Switch; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_AppCompat_Widget_TextView_SpinnerItem = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_AppCompat_Widget_TextView_SpinnerItem; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_Widget_AppCompat_ExpandedMenu_Item = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_Widget_AppCompat_ExpandedMenu_Item; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Subtitle; + global::Xamarin.Forms.Platform.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Title = global::HelloworldXamarin.Droid.Resource.Style.Base_TextAppearance_Widget_AppCompat_Toolbar_Title; + global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_AppCompat_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_ActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_AppCompat_Dark = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dark; + global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_AppCompat_Dark_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dark_ActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Dialog_Alert; + global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Base_ThemeOverlay_MaterialComponents_Dialog_Alert; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_CompactMenu = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_CompactMenu; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_DialogWhenLarge; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Dialog_Alert; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Dialog_FixedSize = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Dialog_FixedSize; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Light_DarkActionBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Light_DarkActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Light_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Light_DialogWhenLarge; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Light_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog_Alert; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Light_Dialog_FixedSize = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog_FixedSize; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_AppCompat_Light_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_AppCompat_Light_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Bridge; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_CompactMenu = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_CompactMenu; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_DialogWhenLarge; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog_Alert; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Dialog_FixedSize = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog_FixedSize; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Bridge; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_DarkActionBar_Bridge; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_DialogWhenLarge; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_Alert; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_FixedSize = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_FixedSize; + global::Xamarin.Forms.Platform.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Base_Theme_MaterialComponents_Light_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_ThemeOverlay_MaterialComponents_Dialog_Alert; + global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_Theme_MaterialComponents; + global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Bridge; + global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light; + global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Bridge; + global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents_Light_DarkActionBar_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light_DarkActionBar_Bridge; + global::Xamarin.Forms.Platform.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V14_Theme_MaterialComponents_Light_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_V21_ThemeOverlay_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V21_ThemeOverlay_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_V21_Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_V21_Theme_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Base_V21_Theme_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V21_Theme_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_V21_Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_V21_Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Base_V21_Theme_AppCompat_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V21_Theme_AppCompat_Light_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_V22_Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_V22_Theme_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Base_V22_Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_V22_Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Base_V23_Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_V23_Theme_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Base_V23_Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_V23_Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Base_V26_Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_V26_Theme_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Base_V26_Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_V26_Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Base_V26_Widget_AppCompat_Toolbar = global::HelloworldXamarin.Droid.Resource.Style.Base_V26_Widget_AppCompat_Toolbar; + global::Xamarin.Forms.Platform.Resource.Style.Base_V28_Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_V28_Theme_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Base_V28_Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_V28_Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Base_V7_ThemeOverlay_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_ThemeOverlay_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_V7_Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_Theme_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Base_V7_Theme_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_Theme_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_V7_Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Base_V7_Theme_AppCompat_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_Theme_AppCompat_Light_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_V7_Widget_AppCompat_AutoCompleteTextView = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_Widget_AppCompat_AutoCompleteTextView; + global::Xamarin.Forms.Platform.Resource.Style.Base_V7_Widget_AppCompat_EditText = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_Widget_AppCompat_EditText; + global::Xamarin.Forms.Platform.Resource.Style.Base_V7_Widget_AppCompat_Toolbar = global::HelloworldXamarin.Droid.Resource.Style.Base_V7_Widget_AppCompat_Toolbar; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionBar_Solid = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_Solid; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionBar_TabBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_TabBar; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionBar_TabText = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_TabText; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionBar_TabView = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionBar_TabView; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionButton = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionButton; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionButton_CloseMode = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionButton_CloseMode; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionButton_Overflow = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionButton_Overflow; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActionMode = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActionMode; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ActivityChooserView = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ActivityChooserView; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_AutoCompleteTextView = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_AutoCompleteTextView; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Button = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Button; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ButtonBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ButtonBar; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ButtonBar_AlertDialog = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ButtonBar_AlertDialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Button_Borderless = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Button_Borderless; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Button_Borderless_Colored = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Button_Borderless_Colored; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Button_ButtonBar_AlertDialog = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Button_ButtonBar_AlertDialog; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Button_Colored = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Button_Colored; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Button_Small = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Button_Small; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_CompoundButton_CheckBox = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_CompoundButton_CheckBox; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_CompoundButton_RadioButton = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_CompoundButton_RadioButton; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_CompoundButton_Switch = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_CompoundButton_Switch; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle_Common = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_DrawerArrowToggle_Common; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_DropDownItem_Spinner = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_DropDownItem_Spinner; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_EditText = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_EditText; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ImageButton = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ImageButton; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_Solid = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_Solid; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabBar; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabText_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabView = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_ActionBar_TabView; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu_Overflow = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Light_PopupMenu_Overflow; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ListMenuView = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ListMenuView; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ListPopupWindow = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ListPopupWindow; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ListView = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ListView; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ListView_DropDown = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ListView_DropDown; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ListView_Menu = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ListView_Menu; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_PopupMenu = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_PopupMenu; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_PopupMenu_Overflow = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_PopupMenu_Overflow; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_PopupWindow = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_PopupWindow; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ProgressBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ProgressBar; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_ProgressBar_Horizontal = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_ProgressBar_Horizontal; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_RatingBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_RatingBar; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_RatingBar_Indicator = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_RatingBar_Indicator; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_RatingBar_Small = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_RatingBar_Small; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_SearchView = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_SearchView; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_SearchView_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_SearchView_ActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_SeekBar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_SeekBar; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_SeekBar_Discrete = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_SeekBar_Discrete; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Spinner = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Spinner; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Spinner_Underlined = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Spinner_Underlined; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_TextView_SpinnerItem = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_TextView_SpinnerItem; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Toolbar = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Toolbar; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_AppCompat_Toolbar_Button_Navigation = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_AppCompat_Toolbar_Button_Navigation; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_Design_TabLayout = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_Design_TabLayout; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_MaterialComponents_Chip = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_MaterialComponents_Chip; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_MaterialComponents_TextInputEditText = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_MaterialComponents_TextInputEditText; + global::Xamarin.Forms.Platform.Resource.Style.Base_Widget_MaterialComponents_TextInputLayout = global::HelloworldXamarin.Droid.Resource.Style.Base_Widget_MaterialComponents_TextInputLayout; + global::Xamarin.Forms.Platform.Resource.Style.CardView = global::HelloworldXamarin.Droid.Resource.Style.CardView; + global::Xamarin.Forms.Platform.Resource.Style.CardView_Dark = global::HelloworldXamarin.Droid.Resource.Style.CardView_Dark; + global::Xamarin.Forms.Platform.Resource.Style.CardView_Light = global::HelloworldXamarin.Droid.Resource.Style.CardView_Light; + global::Xamarin.Forms.Platform.Resource.Style.collectionViewStyle = global::HelloworldXamarin.Droid.Resource.Style.collectionViewStyle; + global::Xamarin.Forms.Platform.Resource.Style.MainTheme = global::HelloworldXamarin.Droid.Resource.Style.MainTheme; + global::Xamarin.Forms.Platform.Resource.Style.MainTheme_Base = global::HelloworldXamarin.Droid.Resource.Style.MainTheme_Base; + global::Xamarin.Forms.Platform.Resource.Style.Platform_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Platform_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Platform_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Platform_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Platform_MaterialComponents = global::HelloworldXamarin.Droid.Resource.Style.Platform_MaterialComponents; + global::Xamarin.Forms.Platform.Resource.Style.Platform_MaterialComponents_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Platform_MaterialComponents_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Platform_MaterialComponents_Light = global::HelloworldXamarin.Droid.Resource.Style.Platform_MaterialComponents_Light; + global::Xamarin.Forms.Platform.Resource.Style.Platform_MaterialComponents_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Platform_MaterialComponents_Light_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Platform_ThemeOverlay_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Platform_ThemeOverlay_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Platform_ThemeOverlay_AppCompat_Dark = global::HelloworldXamarin.Droid.Resource.Style.Platform_ThemeOverlay_AppCompat_Dark; + global::Xamarin.Forms.Platform.Resource.Style.Platform_ThemeOverlay_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Platform_ThemeOverlay_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Platform_V21_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Platform_V21_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Platform_V21_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Platform_V21_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Platform_V25_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Platform_V25_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Platform_V25_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Platform_V25_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Platform_Widget_AppCompat_Spinner = global::HelloworldXamarin.Droid.Resource.Style.Platform_Widget_AppCompat_Spinner; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_DialogWindowTitle_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_DialogWindowTitle_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_ActionBar_TitleItem = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_ActionBar_TitleItem; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_DialogTitle_Icon = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_DialogTitle_Icon; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_InternalGroup = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_InternalGroup; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Shortcut = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Shortcut; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_SubmenuArrow = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_SubmenuArrow; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Text = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Text; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Title = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_PopupMenuItem_Title; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_SearchView_MagIcon = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_SearchView_MagIcon; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon1 = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon1; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon2 = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Icon2; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Query = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Query; + global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text = global::HelloworldXamarin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text; + global::Xamarin.Forms.Platform.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton = global::HelloworldXamarin.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton; + global::Xamarin.Forms.Platform.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow = global::HelloworldXamarin.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Body1 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Body1; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Body2 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Body2; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Button = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Button; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Caption = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Caption; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Display1 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Display1; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Display2 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Display2; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Display3 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Display3; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Display4 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Display4; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Headline = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Headline; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Large = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Large; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Large_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Large_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Subtitle; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Light_SearchResult_Title; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Large; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Light_Widget_PopupMenu_Small; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Medium = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Medium; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Medium_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Medium_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Menu = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Menu; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_SearchResult_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_SearchResult_Subtitle; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_SearchResult_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_SearchResult_Title; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Small = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Small; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Small_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Small_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Subhead = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Subhead; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Subhead_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Subhead_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Title; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Title_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Title_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Tooltip = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Tooltip; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Menu = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Menu; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Subtitle_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_ActionMode_Title_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_Button = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_Button_Borderless_Colored = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button_Borderless_Colored; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_Button_Colored = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button_Colored; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_Button_Inverse = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Button_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_DropDownItem = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_DropDownItem; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Header = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Header; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Large = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Large; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Small = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_PopupMenu_Small; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_Switch = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_Switch; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Widget_TextView_SpinnerItem = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_AppCompat_Widget_TextView_SpinnerItem; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Info = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Info; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Info_Media = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Info_Media; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Line2 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Line2; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Line2_Media = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Line2_Media; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Media = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Media; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Time = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Time; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Time_Media = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Time_Media; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Title; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Compat_Notification_Title_Media = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Compat_Notification_Title_Media; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_CollapsingToolbar_Expanded = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_CollapsingToolbar_Expanded; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Counter = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_Counter; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Counter_Overflow = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_Counter_Overflow; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Error = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_Error; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_HelperText = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_HelperText; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Hint = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_Hint; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Snackbar_Message = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_Snackbar_Message; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Design_Tab = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Design_Tab; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Body1 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Body1; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Body2 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Body2; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Button = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Button; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Caption = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Caption; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Chip = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Chip; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Headline1 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline1; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Headline2 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline2; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Headline3 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline3; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Headline4 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline4; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Headline5 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline5; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Headline6 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Headline6; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Overline = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Overline; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Subtitle1 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Subtitle1; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Subtitle2 = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Subtitle2; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_MaterialComponents_Tab = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_MaterialComponents_Tab; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Widget_AppCompat_ExpandedMenu_Item = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Widget_AppCompat_ExpandedMenu_Item; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Subtitle = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Subtitle; + global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Title = global::HelloworldXamarin.Droid.Resource.Style.TextAppearance_Widget_AppCompat_Toolbar_Title; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_AppCompat_ActionBar; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat_Dark = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_AppCompat_Dark; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat_Dark_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_AppCompat_Dark_ActionBar; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_AppCompat_Dialog_Alert; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_ActionBar; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Dark = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dark; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Dark_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dark_ActionBar; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Dialog = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Dialog_Alert; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_Light = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_Light; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox_Dense = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox_Dense; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox; + global::Xamarin.Forms.Platform.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox_Dense = global::HelloworldXamarin.Droid.Resource.Style.ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox_Dense; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_CompactMenu = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_CompactMenu; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DayNight = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DayNight; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DayNight_DarkActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DayNight_DarkActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DayNight_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DayNight_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DayNight_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DayNight_DialogWhenLarge; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DayNight_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DayNight_Dialog_Alert; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DayNight_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DayNight_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DayNight_NoActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DayNight_NoActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_DialogWhenLarge; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Dialog_Alert; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Light = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Light; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Light_DarkActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Light_DarkActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Light_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Light_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Light_DialogWhenLarge; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Light_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Light_Dialog_Alert; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Light_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Light_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_Light_NoActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_Light_NoActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Theme_AppCompat_NoActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_AppCompat_NoActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Theme_Design = global::HelloworldXamarin.Droid.Resource.Style.Theme_Design; + global::Xamarin.Forms.Platform.Resource.Style.Theme_Design_BottomSheetDialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_Design_BottomSheetDialog; + global::Xamarin.Forms.Platform.Resource.Style.Theme_Design_Light = global::HelloworldXamarin.Droid.Resource.Style.Theme_Design_Light; + global::Xamarin.Forms.Platform.Resource.Style.Theme_Design_Light_BottomSheetDialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_Design_Light_BottomSheetDialog; + global::Xamarin.Forms.Platform.Resource.Style.Theme_Design_Light_NoActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_Design_Light_NoActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Theme_Design_NoActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_Design_NoActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_BottomSheetDialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_BottomSheetDialog; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Bridge; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_CompactMenu = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_CompactMenu; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_DialogWhenLarge; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Dialog_Alert; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_BottomSheetDialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_BottomSheetDialog; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_Bridge; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_DarkActionBar_Bridge; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_DialogWhenLarge = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_DialogWhenLarge; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_Dialog_Alert = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_Alert; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_Dialog_MinWidth = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_Dialog_MinWidth; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_NoActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_NoActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_Light_NoActionBar_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_Light_NoActionBar_Bridge; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_NoActionBar = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_NoActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Theme_MaterialComponents_NoActionBar_Bridge = global::HelloworldXamarin.Droid.Resource.Style.Theme_MaterialComponents_NoActionBar_Bridge; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionBar_Solid = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionBar_Solid; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionBar_TabBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionBar_TabBar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionBar_TabText = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionBar_TabText; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionBar_TabView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionBar_TabView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionButton; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionButton_CloseMode = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionButton_CloseMode; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionButton_Overflow = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionButton_Overflow; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActionMode = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActionMode; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ActivityChooserView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ActivityChooserView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_AutoCompleteTextView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_AutoCompleteTextView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Button = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Button; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ButtonBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ButtonBar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ButtonBar_AlertDialog = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ButtonBar_AlertDialog; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Button_Borderless = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Button_Borderless; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Button_Borderless_Colored = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Button_Borderless_Colored; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Button_ButtonBar_AlertDialog = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Button_ButtonBar_AlertDialog; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Button_Colored = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Button_Colored; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Button_Small = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Button_Small; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_CompoundButton_CheckBox = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_CompoundButton_CheckBox; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_CompoundButton_RadioButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_CompoundButton_RadioButton; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_CompoundButton_Switch = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_CompoundButton_Switch; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_DrawerArrowToggle = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_DrawerArrowToggle; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_DropDownItem_Spinner = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_DropDownItem_Spinner; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_EditText = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_EditText; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ImageButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ImageButton; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_Solid_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabBar_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabText_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionBar_TabView_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionButton; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionButton_CloseMode = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionButton_CloseMode; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionButton_Overflow = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionButton_Overflow; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActionMode_Inverse = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActionMode_Inverse; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ActivityChooserView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ActivityChooserView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_AutoCompleteTextView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_AutoCompleteTextView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_DropDownItem_Spinner = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_DropDownItem_Spinner; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ListPopupWindow = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ListPopupWindow; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_ListView_DropDown = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_ListView_DropDown; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_PopupMenu = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_PopupMenu; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_PopupMenu_Overflow = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_PopupMenu_Overflow; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_SearchView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_SearchView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Light_Spinner_DropDown_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Light_Spinner_DropDown_ActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ListMenuView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ListMenuView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ListPopupWindow = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ListPopupWindow; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ListView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ListView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ListView_DropDown = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ListView_DropDown; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ListView_Menu = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ListView_Menu; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_PopupMenu = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_PopupMenu; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_PopupMenu_Overflow = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_PopupMenu_Overflow; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_PopupWindow = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_PopupWindow; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ProgressBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ProgressBar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_ProgressBar_Horizontal = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_ProgressBar_Horizontal; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_RatingBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_RatingBar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_RatingBar_Indicator = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_RatingBar_Indicator; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_RatingBar_Small = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_RatingBar_Small; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_SearchView = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_SearchView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_SearchView_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_SearchView_ActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_SeekBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_SeekBar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_SeekBar_Discrete = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_SeekBar_Discrete; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Spinner = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Spinner; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Spinner_DropDown = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Spinner_DropDown; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Spinner_DropDown_ActionBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Spinner_DropDown_ActionBar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Spinner_Underlined = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Spinner_Underlined; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_TextView_SpinnerItem = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_TextView_SpinnerItem; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Toolbar = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Toolbar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_AppCompat_Toolbar_Button_Navigation = global::HelloworldXamarin.Droid.Resource.Style.Widget_AppCompat_Toolbar_Button_Navigation; + global::Xamarin.Forms.Platform.Resource.Style.Widget_Compat_NotificationActionContainer = global::HelloworldXamarin.Droid.Resource.Style.Widget_Compat_NotificationActionContainer; + global::Xamarin.Forms.Platform.Resource.Style.Widget_Compat_NotificationActionText = global::HelloworldXamarin.Droid.Resource.Style.Widget_Compat_NotificationActionText; + global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_AppBarLayout = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_AppBarLayout; + global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_BottomNavigationView = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_BottomNavigationView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_BottomSheet_Modal = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_BottomSheet_Modal; + global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_CollapsingToolbar = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_CollapsingToolbar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_FloatingActionButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_FloatingActionButton; + global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_NavigationView = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_NavigationView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_ScrimInsetsFrameLayout = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_ScrimInsetsFrameLayout; + global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_Snackbar = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_Snackbar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_TabLayout = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_TabLayout; + global::Xamarin.Forms.Platform.Resource.Style.Widget_Design_TextInputLayout = global::HelloworldXamarin.Droid.Resource.Style.Widget_Design_TextInputLayout; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_BottomAppBar = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_BottomAppBar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_BottomAppBar_Colored = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_BottomAppBar_Colored; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_BottomNavigationView = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_BottomNavigationView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_BottomNavigationView_Colored = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_BottomNavigationView_Colored; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_BottomSheet_Modal = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_BottomSheet_Modal; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_Icon = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_Icon; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton_Icon = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_OutlinedButton_Icon; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_TextButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog_Icon = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Dialog_Icon; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_TextButton_Icon = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_TextButton_Icon; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton_Icon = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Button_UnelevatedButton_Icon; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_CardView = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_CardView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_ChipGroup = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_ChipGroup; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Chip_Action = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Chip_Action; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Chip_Choice = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Chip_Choice; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Chip_Entry = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Chip_Entry; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Chip_Filter = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Chip_Filter; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_FloatingActionButton = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_FloatingActionButton; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_NavigationView = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_NavigationView; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Snackbar = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Snackbar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Snackbar_FullWidth = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Snackbar_FullWidth; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TabLayout = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TabLayout; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TabLayout_Colored = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TabLayout_Colored; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox_Dense = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_FilledBox_Dense; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox_Dense = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputEditText_OutlinedBox_Dense; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_Dense = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_FilledBox_Dense; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense; + global::Xamarin.Forms.Platform.Resource.Style.Widget_MaterialComponents_Toolbar = global::HelloworldXamarin.Droid.Resource.Style.Widget_MaterialComponents_Toolbar; + global::Xamarin.Forms.Platform.Resource.Style.Widget_Support_CoordinatorLayout = global::HelloworldXamarin.Droid.Resource.Style.Widget_Support_CoordinatorLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBarLayout = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBarLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBarLayout_android_layout_gravity = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBarLayout_android_layout_gravity; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_background = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_background; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_backgroundSplit = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_backgroundSplit; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_backgroundStacked = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_backgroundStacked; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_contentInsetEnd = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_contentInsetEnd; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_contentInsetEndWithActions = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_contentInsetEndWithActions; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_contentInsetLeft = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_contentInsetLeft; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_contentInsetRight = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_contentInsetRight; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_contentInsetStart = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_contentInsetStart; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_contentInsetStartWithNavigation = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_contentInsetStartWithNavigation; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_customNavigationLayout = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_customNavigationLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_displayOptions = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_displayOptions; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_divider = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_divider; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_elevation = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_elevation; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_height = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_height; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_hideOnContentScroll = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_hideOnContentScroll; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_homeAsUpIndicator = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_homeAsUpIndicator; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_homeLayout = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_homeLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_icon = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_icon; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_indeterminateProgressStyle = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_indeterminateProgressStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_itemPadding = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_itemPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_logo = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_logo; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_navigationMode = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_navigationMode; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_popupTheme = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_popupTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_progressBarPadding = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_progressBarPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_progressBarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_progressBarStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_subtitle = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_subtitle; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_subtitleTextStyle = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_subtitleTextStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_title = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_title; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionBar_titleTextStyle = global::HelloworldXamarin.Droid.Resource.Styleable.ActionBar_titleTextStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionMenuItemView = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMenuItemView; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionMenuItemView_android_minWidth = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMenuItemView_android_minWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionMenuView = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMenuView; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionMode = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMode; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionMode_background = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMode_background; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionMode_backgroundSplit = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMode_backgroundSplit; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionMode_closeItemLayout = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMode_closeItemLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionMode_height = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMode_height; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionMode_subtitleTextStyle = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMode_subtitleTextStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.ActionMode_titleTextStyle = global::HelloworldXamarin.Droid.Resource.Styleable.ActionMode_titleTextStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.ActivityChooserView = global::HelloworldXamarin.Droid.Resource.Styleable.ActivityChooserView; + global::Xamarin.Forms.Platform.Resource.Styleable.ActivityChooserView_expandActivityOverflowButtonDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.ActivityChooserView_expandActivityOverflowButtonDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.ActivityChooserView_initialActivityCount = global::HelloworldXamarin.Droid.Resource.Styleable.ActivityChooserView_initialActivityCount; + global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog; + global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_android_layout = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_android_layout; + global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_buttonIconDimen = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_buttonIconDimen; + global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_buttonPanelSideLayout = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_buttonPanelSideLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_listItemLayout = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_listItemLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_listLayout = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_listLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_multiChoiceItemLayout = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_multiChoiceItemLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_showTitle = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_showTitle; + global::Xamarin.Forms.Platform.Resource.Styleable.AlertDialog_singleChoiceItemLayout = global::HelloworldXamarin.Droid.Resource.Styleable.AlertDialog_singleChoiceItemLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableCompat = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableCompat; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableCompat_android_constantSize = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_constantSize; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableCompat_android_dither = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_dither; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableCompat_android_enterFadeDuration = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_enterFadeDuration; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableCompat_android_exitFadeDuration = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_exitFadeDuration; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableCompat_android_variablePadding = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_variablePadding; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableCompat_android_visible = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableCompat_android_visible; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableItem = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableItem; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableItem_android_drawable = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableItem_android_drawable; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableItem_android_id = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableItem_android_id; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableTransition = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableTransition; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableTransition_android_drawable = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_drawable; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableTransition_android_fromId = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_fromId; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableTransition_android_reversible = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_reversible; + global::Xamarin.Forms.Platform.Resource.Styleable.AnimatedStateListDrawableTransition_android_toId = global::HelloworldXamarin.Droid.Resource.Styleable.AnimatedStateListDrawableTransition_android_toId; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayoutStates = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayoutStates; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayoutStates_state_collapsed = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayoutStates_state_collapsed; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayoutStates_state_collapsible = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayoutStates_state_collapsible; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayoutStates_state_liftable = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayoutStates_state_liftable; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayoutStates_state_lifted = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayoutStates_state_lifted; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_android_background = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_android_background; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_android_keyboardNavigationCluster = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_android_keyboardNavigationCluster; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_android_touchscreenBlocksFocus = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_android_touchscreenBlocksFocus; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_elevation = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_elevation; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_expanded = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_expanded; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_Layout; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_Layout_layout_scrollFlags = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_Layout_layout_scrollFlags; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_Layout_layout_scrollInterpolator = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_Layout_layout_scrollInterpolator; + global::Xamarin.Forms.Platform.Resource.Styleable.AppBarLayout_liftOnScroll = global::HelloworldXamarin.Droid.Resource.Styleable.AppBarLayout_liftOnScroll; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatImageView = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatImageView; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatImageView_android_src = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatImageView_android_src; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatImageView_srcCompat = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatImageView_srcCompat; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatImageView_tint = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatImageView_tint; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatImageView_tintMode = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatImageView_tintMode; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatSeekBar = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatSeekBar; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatSeekBar_android_thumb = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatSeekBar_android_thumb; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatSeekBar_tickMark = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatSeekBar_tickMark; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatSeekBar_tickMarkTint = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatSeekBar_tickMarkTint; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatSeekBar_tickMarkTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatSeekBar_tickMarkTintMode; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper_android_drawableBottom = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableBottom; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper_android_drawableEnd = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableEnd; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper_android_drawableLeft = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableLeft; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper_android_drawableRight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableRight; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper_android_drawableStart = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableStart; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper_android_drawableTop = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper_android_drawableTop; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextHelper_android_textAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextHelper_android_textAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_android_textAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_android_textAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_autoSizeMaxTextSize = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_autoSizeMaxTextSize; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_autoSizeMinTextSize = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_autoSizeMinTextSize; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_autoSizePresetSizes = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_autoSizePresetSizes; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_autoSizeStepGranularity = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_autoSizeStepGranularity; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_autoSizeTextType = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_autoSizeTextType; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_firstBaselineToTopHeight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_firstBaselineToTopHeight; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_fontFamily = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_fontFamily; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_lastBaselineToBottomHeight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_lastBaselineToBottomHeight; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_lineHeight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_lineHeight; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTextView_textAllCaps = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTextView_textAllCaps; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarDivider = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarDivider; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarItemBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarItemBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarPopupTheme = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarPopupTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarSize = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarSize; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarSplitStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarSplitStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarTabBarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarTabBarStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarTabStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarTabStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarTabTextStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarTabTextStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarTheme = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionBarWidgetTheme = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionBarWidgetTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionDropDownStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionDropDownStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionMenuTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionMenuTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionMenuTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionMenuTextColor; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeCloseButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeCloseButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeCloseDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeCloseDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeCopyDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeCopyDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeCutDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeCutDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeFindDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeFindDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModePasteDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModePasteDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModePopupWindowStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModePopupWindowStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeSelectAllDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeSelectAllDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeShareDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeShareDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeSplitBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeSplitBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionModeWebSearchDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionModeWebSearchDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionOverflowButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionOverflowButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_actionOverflowMenuStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_actionOverflowMenuStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_activityChooserViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_activityChooserViewStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_alertDialogButtonGroupStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_alertDialogButtonGroupStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_alertDialogCenterButtons = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_alertDialogCenterButtons; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_alertDialogStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_alertDialogStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_alertDialogTheme = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_alertDialogTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_android_windowAnimationStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_android_windowAnimationStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_android_windowIsFloating = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_android_windowIsFloating; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_autoCompleteTextViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_autoCompleteTextViewStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_borderlessButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_borderlessButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_buttonBarButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_buttonBarButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_buttonBarNegativeButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_buttonBarNegativeButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_buttonBarNeutralButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_buttonBarNeutralButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_buttonBarPositiveButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_buttonBarPositiveButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_buttonBarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_buttonBarStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_buttonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_buttonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_buttonStyleSmall = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_buttonStyleSmall; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_checkboxStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_checkboxStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_checkedTextViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_checkedTextViewStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorAccent = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorAccent; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorBackgroundFloating = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorBackgroundFloating; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorButtonNormal = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorButtonNormal; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorControlActivated = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorControlActivated; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorControlHighlight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorControlHighlight; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorControlNormal = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorControlNormal; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorError = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorError; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorPrimary = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorPrimary; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorPrimaryDark = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorPrimaryDark; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_colorSwitchThumbNormal = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_colorSwitchThumbNormal; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_controlBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_controlBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_dialogCornerRadius = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_dialogCornerRadius; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_dialogPreferredPadding = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_dialogPreferredPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_dialogTheme = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_dialogTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_dividerHorizontal = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_dividerHorizontal; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_dividerVertical = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_dividerVertical; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_dropdownListPreferredItemHeight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_dropdownListPreferredItemHeight; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_dropDownListViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_dropDownListViewStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_editTextBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_editTextBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_editTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_editTextColor; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_editTextStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_editTextStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_homeAsUpIndicator = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_homeAsUpIndicator; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_imageButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_imageButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listChoiceBackgroundIndicator = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listChoiceBackgroundIndicator; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listDividerAlertDialog = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listDividerAlertDialog; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listMenuViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listMenuViewStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listPopupWindowStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listPopupWindowStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listPreferredItemHeight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemHeight; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listPreferredItemHeightLarge = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemHeightLarge; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listPreferredItemHeightSmall = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemHeightSmall; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingLeft = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingLeft; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingRight = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_listPreferredItemPaddingRight; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_panelBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_panelBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_panelMenuListTheme = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_panelMenuListTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_panelMenuListWidth = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_panelMenuListWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_popupMenuStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_popupMenuStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_popupWindowStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_popupWindowStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_radioButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_radioButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_ratingBarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_ratingBarStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_ratingBarStyleIndicator = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_ratingBarStyleIndicator; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_ratingBarStyleSmall = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_ratingBarStyleSmall; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_searchViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_searchViewStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_seekBarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_seekBarStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_selectableItemBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_selectableItemBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_selectableItemBackgroundBorderless = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_selectableItemBackgroundBorderless; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_spinnerDropDownItemStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_spinnerDropDownItemStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_spinnerStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_spinnerStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_switchStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_switchStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearanceLargePopupMenu = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearanceLargePopupMenu; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearanceListItem = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearanceListItem; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearanceListItemSecondary = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearanceListItemSecondary; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearanceListItemSmall = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearanceListItemSmall; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearancePopupMenuHeader = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearancePopupMenuHeader; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultSubtitle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultSubtitle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultTitle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearanceSearchResultTitle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textAppearanceSmallPopupMenu = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textAppearanceSmallPopupMenu; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textColorAlertDialogListItem = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textColorAlertDialogListItem; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_textColorSearchUrl = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_textColorSearchUrl; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_toolbarNavigationButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_toolbarNavigationButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_toolbarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_toolbarStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_tooltipForegroundColor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_tooltipForegroundColor; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_tooltipFrameBackground = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_tooltipFrameBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_viewInflaterClass = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_viewInflaterClass; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowActionBar = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowActionBar; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowActionBarOverlay = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowActionBarOverlay; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowActionModeOverlay = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowActionModeOverlay; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowFixedHeightMajor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowFixedHeightMajor; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowFixedHeightMinor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowFixedHeightMinor; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowFixedWidthMajor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowFixedWidthMajor; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowFixedWidthMinor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowFixedWidthMinor; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowMinWidthMajor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowMinWidthMajor; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowMinWidthMinor = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowMinWidthMinor; + global::Xamarin.Forms.Platform.Resource.Styleable.AppCompatTheme_windowNoTitle = global::HelloworldXamarin.Droid.Resource.Styleable.AppCompatTheme_windowNoTitle; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar = global::HelloworldXamarin.Droid.Resource.Styleable.BottomAppBar; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_backgroundTint = global::HelloworldXamarin.Droid.Resource.Styleable.BottomAppBar_backgroundTint; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_fabAlignmentMode = global::HelloworldXamarin.Droid.Resource.Styleable.BottomAppBar_fabAlignmentMode; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_fabCradleMargin = global::HelloworldXamarin.Droid.Resource.Styleable.BottomAppBar_fabCradleMargin; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_fabCradleRoundedCornerRadius = global::HelloworldXamarin.Droid.Resource.Styleable.BottomAppBar_fabCradleRoundedCornerRadius; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_fabCradleVerticalOffset = global::HelloworldXamarin.Droid.Resource.Styleable.BottomAppBar_fabCradleVerticalOffset; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomAppBar_hideOnScroll = global::HelloworldXamarin.Droid.Resource.Styleable.BottomAppBar_hideOnScroll; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_elevation = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_elevation; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemBackground = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_itemBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemHorizontalTranslationEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_itemHorizontalTranslationEnabled; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemIconSize = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_itemIconSize; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemIconTint = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_itemIconTint; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemTextAppearanceActive = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_itemTextAppearanceActive; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemTextAppearanceInactive = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_itemTextAppearanceInactive; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_itemTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_itemTextColor; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_labelVisibilityMode = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_labelVisibilityMode; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomNavigationView_menu = global::HelloworldXamarin.Droid.Resource.Styleable.BottomNavigationView_menu; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.BottomSheetBehavior_Layout; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_behavior_fitToContents = global::HelloworldXamarin.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_fitToContents; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_behavior_hideable = global::HelloworldXamarin.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_hideable; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_behavior_peekHeight = global::HelloworldXamarin.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_peekHeight; + global::Xamarin.Forms.Platform.Resource.Styleable.BottomSheetBehavior_Layout_behavior_skipCollapsed = global::HelloworldXamarin.Droid.Resource.Styleable.BottomSheetBehavior_Layout_behavior_skipCollapsed; + global::Xamarin.Forms.Platform.Resource.Styleable.ButtonBarLayout = global::HelloworldXamarin.Droid.Resource.Styleable.ButtonBarLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.ButtonBarLayout_allowStacking = global::HelloworldXamarin.Droid.Resource.Styleable.ButtonBarLayout_allowStacking; + global::Xamarin.Forms.Platform.Resource.Styleable.CardView = global::HelloworldXamarin.Droid.Resource.Styleable.CardView; + global::Xamarin.Forms.Platform.Resource.Styleable.CardView_android_minHeight = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_android_minHeight; + global::Xamarin.Forms.Platform.Resource.Styleable.CardView_android_minWidth = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_android_minWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.CardView_cardBackgroundColor = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_cardBackgroundColor; + global::Xamarin.Forms.Platform.Resource.Styleable.CardView_cardCornerRadius = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_cardCornerRadius; + global::Xamarin.Forms.Platform.Resource.Styleable.CardView_cardElevation = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_cardElevation; + global::Xamarin.Forms.Platform.Resource.Styleable.CardView_cardMaxElevation = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_cardMaxElevation; + global::Xamarin.Forms.Platform.Resource.Styleable.CardView_cardPreventCornerOverlap = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_cardPreventCornerOverlap; + global::Xamarin.Forms.Platform.Resource.Styleable.CardView_cardUseCompatPadding = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_cardUseCompatPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.CardView_contentPadding = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_contentPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.CardView_contentPaddingBottom = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_contentPaddingBottom; + global::Xamarin.Forms.Platform.Resource.Styleable.CardView_contentPaddingLeft = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_contentPaddingLeft; + global::Xamarin.Forms.Platform.Resource.Styleable.CardView_contentPaddingRight = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_contentPaddingRight; + global::Xamarin.Forms.Platform.Resource.Styleable.CardView_contentPaddingTop = global::HelloworldXamarin.Droid.Resource.Styleable.CardView_contentPaddingTop; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip = global::HelloworldXamarin.Droid.Resource.Styleable.Chip; + global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup = global::HelloworldXamarin.Droid.Resource.Styleable.ChipGroup; + global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup_checkedChip = global::HelloworldXamarin.Droid.Resource.Styleable.ChipGroup_checkedChip; + global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup_chipSpacing = global::HelloworldXamarin.Droid.Resource.Styleable.ChipGroup_chipSpacing; + global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup_chipSpacingHorizontal = global::HelloworldXamarin.Droid.Resource.Styleable.ChipGroup_chipSpacingHorizontal; + global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup_chipSpacingVertical = global::HelloworldXamarin.Droid.Resource.Styleable.ChipGroup_chipSpacingVertical; + global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup_singleLine = global::HelloworldXamarin.Droid.Resource.Styleable.ChipGroup_singleLine; + global::Xamarin.Forms.Platform.Resource.Styleable.ChipGroup_singleSelection = global::HelloworldXamarin.Droid.Resource.Styleable.ChipGroup_singleSelection; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_android_checkable = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_android_checkable; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_android_ellipsize = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_android_ellipsize; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_android_maxWidth = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_android_maxWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_android_text = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_android_text; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_android_textAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_android_textAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_checkedIcon = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_checkedIcon; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_checkedIconEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_checkedIconEnabled; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_checkedIconVisible = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_checkedIconVisible; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipBackgroundColor = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipBackgroundColor; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipCornerRadius = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipCornerRadius; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipEndPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipEndPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipIcon = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipIcon; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipIconEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipIconEnabled; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipIconSize = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipIconSize; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipIconTint = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipIconTint; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipIconVisible = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipIconVisible; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipMinHeight = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipMinHeight; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipStartPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipStartPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipStrokeColor = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipStrokeColor; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_chipStrokeWidth = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_chipStrokeWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_closeIcon = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_closeIcon; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_closeIconEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_closeIconEnabled; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_closeIconEndPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_closeIconEndPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_closeIconSize = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_closeIconSize; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_closeIconStartPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_closeIconStartPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_closeIconTint = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_closeIconTint; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_closeIconVisible = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_closeIconVisible; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_hideMotionSpec = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_hideMotionSpec; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_iconEndPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_iconEndPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_iconStartPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_iconStartPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_rippleColor = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_rippleColor; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_showMotionSpec = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_showMotionSpec; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_textEndPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_textEndPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.Chip_textStartPadding = global::HelloworldXamarin.Droid.Resource.Styleable.Chip_textStartPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleGravity = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleGravity; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_collapsedTitleTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_contentScrim = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_contentScrim; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_expandedTitleGravity = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleGravity; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMargin = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMargin; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginBottom = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginBottom; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginEnd = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginEnd; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginStart = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginStart; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginTop = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleMarginTop; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_expandedTitleTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_expandedTitleTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_Layout; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseMode = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseMode; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseParallaxMultiplier = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_Layout_layout_collapseParallaxMultiplier; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_scrimAnimationDuration = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_scrimAnimationDuration; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_scrimVisibleHeightTrigger = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_scrimVisibleHeightTrigger; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_statusBarScrim = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_statusBarScrim; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_title = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_title; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_titleEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_titleEnabled; + global::Xamarin.Forms.Platform.Resource.Styleable.CollapsingToolbarLayout_toolbarId = global::HelloworldXamarin.Droid.Resource.Styleable.CollapsingToolbarLayout_toolbarId; + global::Xamarin.Forms.Platform.Resource.Styleable.ColorStateListItem = global::HelloworldXamarin.Droid.Resource.Styleable.ColorStateListItem; + global::Xamarin.Forms.Platform.Resource.Styleable.ColorStateListItem_alpha = global::HelloworldXamarin.Droid.Resource.Styleable.ColorStateListItem_alpha; + global::Xamarin.Forms.Platform.Resource.Styleable.ColorStateListItem_android_alpha = global::HelloworldXamarin.Droid.Resource.Styleable.ColorStateListItem_android_alpha; + global::Xamarin.Forms.Platform.Resource.Styleable.ColorStateListItem_android_color = global::HelloworldXamarin.Droid.Resource.Styleable.ColorStateListItem_android_color; + global::Xamarin.Forms.Platform.Resource.Styleable.CompoundButton = global::HelloworldXamarin.Droid.Resource.Styleable.CompoundButton; + global::Xamarin.Forms.Platform.Resource.Styleable.CompoundButton_android_button = global::HelloworldXamarin.Droid.Resource.Styleable.CompoundButton_android_button; + global::Xamarin.Forms.Platform.Resource.Styleable.CompoundButton_buttonTint = global::HelloworldXamarin.Droid.Resource.Styleable.CompoundButton_buttonTint; + global::Xamarin.Forms.Platform.Resource.Styleable.CompoundButton_buttonTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.CompoundButton_buttonTintMode; + global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_keylines = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_keylines; + global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout; + global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_android_layout_gravity; + global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_anchor; + global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_anchorGravity; + global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_behavior; + global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_dodgeInsetEdges; + global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_insetEdge; + global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_Layout_layout_keyline; + global::Xamarin.Forms.Platform.Resource.Styleable.CoordinatorLayout_statusBarBackground = global::HelloworldXamarin.Droid.Resource.Styleable.CoordinatorLayout_statusBarBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.DesignTheme = global::HelloworldXamarin.Droid.Resource.Styleable.DesignTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.DesignTheme_bottomSheetDialogTheme = global::HelloworldXamarin.Droid.Resource.Styleable.DesignTheme_bottomSheetDialogTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.DesignTheme_bottomSheetStyle = global::HelloworldXamarin.Droid.Resource.Styleable.DesignTheme_bottomSheetStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle; + global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_arrowHeadLength = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_arrowHeadLength; + global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_arrowShaftLength = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_arrowShaftLength; + global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_barLength = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_barLength; + global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_color = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_color; + global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_drawableSize = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_drawableSize; + global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_gapBetweenBars = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_gapBetweenBars; + global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_spinBars = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_spinBars; + global::Xamarin.Forms.Platform.Resource.Styleable.DrawerArrowToggle_thickness = global::HelloworldXamarin.Droid.Resource.Styleable.DrawerArrowToggle_thickness; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_backgroundTint = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_backgroundTint; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_backgroundTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_backgroundTintMode; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_Behavior_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_Behavior_Layout; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_Behavior_Layout_behavior_autoHide = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_Behavior_Layout_behavior_autoHide; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_borderWidth = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_borderWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_elevation = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_elevation; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_fabCustomSize = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_fabCustomSize; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_fabSize = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_fabSize; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_hideMotionSpec = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_hideMotionSpec; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_hoveredFocusedTranslationZ = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_hoveredFocusedTranslationZ; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_maxImageSize = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_maxImageSize; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_pressedTranslationZ = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_pressedTranslationZ; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_rippleColor = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_rippleColor; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_showMotionSpec = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_showMotionSpec; + global::Xamarin.Forms.Platform.Resource.Styleable.FloatingActionButton_useCompatPadding = global::HelloworldXamarin.Droid.Resource.Styleable.FloatingActionButton_useCompatPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.FlowLayout = global::HelloworldXamarin.Droid.Resource.Styleable.FlowLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.FlowLayout_itemSpacing = global::HelloworldXamarin.Droid.Resource.Styleable.FlowLayout_itemSpacing; + global::Xamarin.Forms.Platform.Resource.Styleable.FlowLayout_lineSpacing = global::HelloworldXamarin.Droid.Resource.Styleable.FlowLayout_lineSpacing; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamily = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_android_font = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_font; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_android_fontStyle = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_fontStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_android_fontVariationSettings = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_fontVariationSettings; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_android_fontWeight = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_fontWeight; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_android_ttcIndex = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_android_ttcIndex; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_font = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_font; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_fontStyle = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_fontStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_fontVariationSettings = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_fontVariationSettings; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_fontWeight = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_fontWeight; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamilyFont_ttcIndex = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamilyFont_ttcIndex; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamily_fontProviderAuthority = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderAuthority; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamily_fontProviderCerts = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderCerts; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamily_fontProviderFetchStrategy = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderFetchStrategy; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamily_fontProviderFetchTimeout = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderFetchTimeout; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamily_fontProviderPackage = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderPackage; + global::Xamarin.Forms.Platform.Resource.Styleable.FontFamily_fontProviderQuery = global::HelloworldXamarin.Droid.Resource.Styleable.FontFamily_fontProviderQuery; + global::Xamarin.Forms.Platform.Resource.Styleable.ForegroundLinearLayout = global::HelloworldXamarin.Droid.Resource.Styleable.ForegroundLinearLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.ForegroundLinearLayout_android_foreground = global::HelloworldXamarin.Droid.Resource.Styleable.ForegroundLinearLayout_android_foreground; + global::Xamarin.Forms.Platform.Resource.Styleable.ForegroundLinearLayout_android_foregroundGravity = global::HelloworldXamarin.Droid.Resource.Styleable.ForegroundLinearLayout_android_foregroundGravity; + global::Xamarin.Forms.Platform.Resource.Styleable.ForegroundLinearLayout_foregroundInsidePadding = global::HelloworldXamarin.Droid.Resource.Styleable.ForegroundLinearLayout_foregroundInsidePadding; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColorItem = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColorItem; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColorItem_android_color = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColorItem_android_color; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColorItem_android_offset = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColorItem_android_offset; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_centerColor = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_centerColor; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_centerX = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_centerX; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_centerY = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_centerY; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_endColor = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_endColor; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_endX = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_endX; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_endY = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_endY; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_gradientRadius = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_gradientRadius; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_startColor = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_startColor; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_startX = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_startX; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_startY = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_startY; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_tileMode = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_tileMode; + global::Xamarin.Forms.Platform.Resource.Styleable.GradientColor_android_type = global::HelloworldXamarin.Droid.Resource.Styleable.GradientColor_android_type; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_android_baselineAligned = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_android_baselineAligned; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_android_baselineAlignedChildIndex = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_android_baselineAlignedChildIndex; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_android_gravity = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_android_gravity; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_android_orientation = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_android_orientation; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_android_weightSum = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_android_weightSum; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_divider = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_divider; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_dividerPadding = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_dividerPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_Layout; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_gravity = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_gravity; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_height = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_height; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_weight = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_weight; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_width = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_Layout_android_layout_width; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_measureWithLargestChild = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_measureWithLargestChild; + global::Xamarin.Forms.Platform.Resource.Styleable.LinearLayoutCompat_showDividers = global::HelloworldXamarin.Droid.Resource.Styleable.LinearLayoutCompat_showDividers; + global::Xamarin.Forms.Platform.Resource.Styleable.ListPopupWindow = global::HelloworldXamarin.Droid.Resource.Styleable.ListPopupWindow; + global::Xamarin.Forms.Platform.Resource.Styleable.ListPopupWindow_android_dropDownHorizontalOffset = global::HelloworldXamarin.Droid.Resource.Styleable.ListPopupWindow_android_dropDownHorizontalOffset; + global::Xamarin.Forms.Platform.Resource.Styleable.ListPopupWindow_android_dropDownVerticalOffset = global::HelloworldXamarin.Droid.Resource.Styleable.ListPopupWindow_android_dropDownVerticalOffset; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_android_insetBottom = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_android_insetBottom; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_android_insetLeft = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_android_insetLeft; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_android_insetRight = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_android_insetRight; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_android_insetTop = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_android_insetTop; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_backgroundTint = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_backgroundTint; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_backgroundTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_backgroundTintMode; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_cornerRadius = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_cornerRadius; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_icon = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_icon; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_iconGravity = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_iconGravity; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_iconPadding = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_iconPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_iconSize = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_iconSize; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_iconTint = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_iconTint; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_iconTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_iconTintMode; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_rippleColor = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_rippleColor; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_strokeColor = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_strokeColor; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialButton_strokeWidth = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialButton_strokeWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCardView = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialCardView; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCardView_strokeColor = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialCardView_strokeColor; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialCardView_strokeWidth = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialCardView_strokeWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_bottomSheetDialogTheme = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_bottomSheetDialogTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_bottomSheetStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_bottomSheetStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_chipGroupStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_chipGroupStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_chipStandaloneStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_chipStandaloneStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_chipStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_chipStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_colorAccent = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_colorAccent; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_colorBackgroundFloating = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_colorBackgroundFloating; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_colorPrimary = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_colorPrimary; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_colorPrimaryDark = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_colorPrimaryDark; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_colorSecondary = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_colorSecondary; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_editTextStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_editTextStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_floatingActionButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_floatingActionButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_materialButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_materialButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_materialCardViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_materialCardViewStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_navigationViewStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_navigationViewStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_scrimBackground = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_scrimBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_snackbarButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_snackbarButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_tabStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_tabStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_textAppearanceBody1 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceBody1; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_textAppearanceBody2 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceBody2; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_textAppearanceButton = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceButton; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_textAppearanceCaption = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceCaption; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline1 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline1; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline2 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline2; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline3 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline3; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline4 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline4; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline5 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline5; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline6 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceHeadline6; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_textAppearanceOverline = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceOverline; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_textAppearanceSubtitle1 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceSubtitle1; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_textAppearanceSubtitle2 = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textAppearanceSubtitle2; + global::Xamarin.Forms.Platform.Resource.Styleable.MaterialComponentsTheme_textInputStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MaterialComponentsTheme_textInputStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuGroup = global::HelloworldXamarin.Droid.Resource.Styleable.MenuGroup; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuGroup_android_checkableBehavior = global::HelloworldXamarin.Droid.Resource.Styleable.MenuGroup_android_checkableBehavior; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuGroup_android_enabled = global::HelloworldXamarin.Droid.Resource.Styleable.MenuGroup_android_enabled; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuGroup_android_id = global::HelloworldXamarin.Droid.Resource.Styleable.MenuGroup_android_id; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuGroup_android_menuCategory = global::HelloworldXamarin.Droid.Resource.Styleable.MenuGroup_android_menuCategory; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuGroup_android_orderInCategory = global::HelloworldXamarin.Droid.Resource.Styleable.MenuGroup_android_orderInCategory; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuGroup_android_visible = global::HelloworldXamarin.Droid.Resource.Styleable.MenuGroup_android_visible; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_actionLayout = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_actionLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_actionProviderClass = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_actionProviderClass; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_actionViewClass = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_actionViewClass; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_alphabeticModifiers = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_alphabeticModifiers; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_alphabeticShortcut = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_alphabeticShortcut; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_checkable = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_checkable; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_checked = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_checked; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_enabled = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_enabled; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_icon = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_icon; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_id = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_id; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_menuCategory = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_menuCategory; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_numericShortcut = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_numericShortcut; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_onClick = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_onClick; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_orderInCategory = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_orderInCategory; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_title = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_title; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_titleCondensed = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_titleCondensed; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_android_visible = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_android_visible; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_contentDescription = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_contentDescription; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_iconTint = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_iconTint; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_iconTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_iconTintMode; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_numericModifiers = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_numericModifiers; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_showAsAction = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_showAsAction; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuItem_tooltipText = global::HelloworldXamarin.Droid.Resource.Styleable.MenuItem_tooltipText; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuView = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_android_headerBackground = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_android_headerBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_android_horizontalDivider = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_android_horizontalDivider; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_android_itemBackground = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_android_itemBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_android_itemIconDisabledAlpha = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_android_itemIconDisabledAlpha; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_android_itemTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_android_itemTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_android_verticalDivider = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_android_verticalDivider; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_android_windowAnimationStyle = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_android_windowAnimationStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_preserveIconSpacing = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_preserveIconSpacing; + global::Xamarin.Forms.Platform.Resource.Styleable.MenuView_subMenuArrow = global::HelloworldXamarin.Droid.Resource.Styleable.MenuView_subMenuArrow; + global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView; + global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_android_background = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_android_background; + global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_android_fitsSystemWindows = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_android_fitsSystemWindows; + global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_android_maxWidth = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_android_maxWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_elevation = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_elevation; + global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_headerLayout = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_headerLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemBackground = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_itemBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemHorizontalPadding = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_itemHorizontalPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemIconPadding = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_itemIconPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemIconTint = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_itemIconTint; + global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_itemTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_itemTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_itemTextColor; + global::Xamarin.Forms.Platform.Resource.Styleable.NavigationView_menu = global::HelloworldXamarin.Droid.Resource.Styleable.NavigationView_menu; + global::Xamarin.Forms.Platform.Resource.Styleable.PopupWindow = global::HelloworldXamarin.Droid.Resource.Styleable.PopupWindow; + global::Xamarin.Forms.Platform.Resource.Styleable.PopupWindowBackgroundState = global::HelloworldXamarin.Droid.Resource.Styleable.PopupWindowBackgroundState; + global::Xamarin.Forms.Platform.Resource.Styleable.PopupWindowBackgroundState_state_above_anchor = global::HelloworldXamarin.Droid.Resource.Styleable.PopupWindowBackgroundState_state_above_anchor; + global::Xamarin.Forms.Platform.Resource.Styleable.PopupWindow_android_popupAnimationStyle = global::HelloworldXamarin.Droid.Resource.Styleable.PopupWindow_android_popupAnimationStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.PopupWindow_android_popupBackground = global::HelloworldXamarin.Droid.Resource.Styleable.PopupWindow_android_popupBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.PopupWindow_overlapAnchor = global::HelloworldXamarin.Droid.Resource.Styleable.PopupWindow_overlapAnchor; + global::Xamarin.Forms.Platform.Resource.Styleable.RecycleListView = global::HelloworldXamarin.Droid.Resource.Styleable.RecycleListView; + global::Xamarin.Forms.Platform.Resource.Styleable.RecycleListView_paddingBottomNoButtons = global::HelloworldXamarin.Droid.Resource.Styleable.RecycleListView_paddingBottomNoButtons; + global::Xamarin.Forms.Platform.Resource.Styleable.RecycleListView_paddingTopNoTitle = global::HelloworldXamarin.Droid.Resource.Styleable.RecycleListView_paddingTopNoTitle; + global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView; + global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_android_descendantFocusability = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_android_descendantFocusability; + global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_android_orientation = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_android_orientation; + global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_fastScrollEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_fastScrollEnabled; + global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_fastScrollHorizontalThumbDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_fastScrollHorizontalThumbDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_fastScrollHorizontalTrackDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_fastScrollHorizontalTrackDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_fastScrollVerticalThumbDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_fastScrollVerticalThumbDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_fastScrollVerticalTrackDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_fastScrollVerticalTrackDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_layoutManager = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_layoutManager; + global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_reverseLayout = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_reverseLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_spanCount = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_spanCount; + global::Xamarin.Forms.Platform.Resource.Styleable.RecyclerView_stackFromEnd = global::HelloworldXamarin.Droid.Resource.Styleable.RecyclerView_stackFromEnd; + global::Xamarin.Forms.Platform.Resource.Styleable.ScrimInsetsFrameLayout = global::HelloworldXamarin.Droid.Resource.Styleable.ScrimInsetsFrameLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground = global::HelloworldXamarin.Droid.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground; + global::Xamarin.Forms.Platform.Resource.Styleable.ScrollingViewBehavior_Layout = global::HelloworldXamarin.Droid.Resource.Styleable.ScrollingViewBehavior_Layout; + global::Xamarin.Forms.Platform.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop = global::HelloworldXamarin.Droid.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_android_focusable = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_android_focusable; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_android_imeOptions = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_android_imeOptions; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_android_inputType = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_android_inputType; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_android_maxWidth = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_android_maxWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_closeIcon = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_closeIcon; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_commitIcon = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_commitIcon; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_defaultQueryHint = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_defaultQueryHint; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_goIcon = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_goIcon; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_iconifiedByDefault = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_iconifiedByDefault; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_layout = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_layout; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_queryBackground = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_queryBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_queryHint = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_queryHint; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_searchHintIcon = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_searchHintIcon; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_searchIcon = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_searchIcon; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_submitBackground = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_submitBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_suggestionRowLayout = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_suggestionRowLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_voiceIcon = global::HelloworldXamarin.Droid.Resource.Styleable.SearchView_voiceIcon; + global::Xamarin.Forms.Platform.Resource.Styleable.Snackbar = global::HelloworldXamarin.Droid.Resource.Styleable.Snackbar; + global::Xamarin.Forms.Platform.Resource.Styleable.SnackbarLayout = global::HelloworldXamarin.Droid.Resource.Styleable.SnackbarLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.SnackbarLayout_android_maxWidth = global::HelloworldXamarin.Droid.Resource.Styleable.SnackbarLayout_android_maxWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.SnackbarLayout_elevation = global::HelloworldXamarin.Droid.Resource.Styleable.SnackbarLayout_elevation; + global::Xamarin.Forms.Platform.Resource.Styleable.SnackbarLayout_maxActionInlineWidth = global::HelloworldXamarin.Droid.Resource.Styleable.SnackbarLayout_maxActionInlineWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.Snackbar_snackbarButtonStyle = global::HelloworldXamarin.Droid.Resource.Styleable.Snackbar_snackbarButtonStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.Snackbar_snackbarStyle = global::HelloworldXamarin.Droid.Resource.Styleable.Snackbar_snackbarStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.Spinner = global::HelloworldXamarin.Droid.Resource.Styleable.Spinner; + global::Xamarin.Forms.Platform.Resource.Styleable.Spinner_android_dropDownWidth = global::HelloworldXamarin.Droid.Resource.Styleable.Spinner_android_dropDownWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.Spinner_android_entries = global::HelloworldXamarin.Droid.Resource.Styleable.Spinner_android_entries; + global::Xamarin.Forms.Platform.Resource.Styleable.Spinner_android_popupBackground = global::HelloworldXamarin.Droid.Resource.Styleable.Spinner_android_popupBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.Spinner_android_prompt = global::HelloworldXamarin.Droid.Resource.Styleable.Spinner_android_prompt; + global::Xamarin.Forms.Platform.Resource.Styleable.Spinner_popupTheme = global::HelloworldXamarin.Droid.Resource.Styleable.Spinner_popupTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawableItem = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawableItem; + global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawableItem_android_drawable = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawableItem_android_drawable; + global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawable_android_constantSize = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawable_android_constantSize; + global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawable_android_dither = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawable_android_dither; + global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawable_android_enterFadeDuration = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawable_android_enterFadeDuration; + global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawable_android_exitFadeDuration = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawable_android_exitFadeDuration; + global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawable_android_variablePadding = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawable_android_variablePadding; + global::Xamarin.Forms.Platform.Resource.Styleable.StateListDrawable_android_visible = global::HelloworldXamarin.Droid.Resource.Styleable.StateListDrawable_android_visible; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_android_textOff = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_android_textOff; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_android_textOn = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_android_textOn; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_android_thumb = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_android_thumb; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_showText = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_showText; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_splitTrack = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_splitTrack; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_switchMinWidth = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_switchMinWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_switchPadding = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_switchPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_switchTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_switchTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_thumbTextPadding = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_thumbTextPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_thumbTint = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_thumbTint; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_thumbTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_thumbTintMode; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_track = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_track; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_trackTint = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_trackTint; + global::Xamarin.Forms.Platform.Resource.Styleable.SwitchCompat_trackTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.SwitchCompat_trackTintMode; + global::Xamarin.Forms.Platform.Resource.Styleable.TabItem = global::HelloworldXamarin.Droid.Resource.Styleable.TabItem; + global::Xamarin.Forms.Platform.Resource.Styleable.TabItem_android_icon = global::HelloworldXamarin.Droid.Resource.Styleable.TabItem_android_icon; + global::Xamarin.Forms.Platform.Resource.Styleable.TabItem_android_layout = global::HelloworldXamarin.Droid.Resource.Styleable.TabItem_android_layout; + global::Xamarin.Forms.Platform.Resource.Styleable.TabItem_android_text = global::HelloworldXamarin.Droid.Resource.Styleable.TabItem_android_text; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabBackground = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabBackground; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabContentStart = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabContentStart; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabGravity = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabGravity; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIconTint = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIconTint; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIconTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIconTintMode; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIndicator = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIndicator; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIndicatorAnimationDuration = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIndicatorAnimationDuration; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIndicatorColor = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIndicatorColor; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIndicatorFullWidth = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIndicatorFullWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIndicatorGravity = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIndicatorGravity; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabIndicatorHeight = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabIndicatorHeight; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabInlineLabel = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabInlineLabel; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabMaxWidth = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabMaxWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabMinWidth = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabMinWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabMode = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabMode; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabPadding = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabPadding; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabPaddingBottom = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabPaddingBottom; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabPaddingEnd = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabPaddingEnd; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabPaddingStart = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabPaddingStart; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabPaddingTop = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabPaddingTop; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabRippleColor = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabRippleColor; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabSelectedTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabSelectedTextColor; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabTextColor; + global::Xamarin.Forms.Platform.Resource.Styleable.TabLayout_tabUnboundedRipple = global::HelloworldXamarin.Droid.Resource.Styleable.TabLayout_tabUnboundedRipple; + global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_fontFamily = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_fontFamily; + global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_shadowColor = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_shadowColor; + global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_shadowDx = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_shadowDx; + global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_shadowDy = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_shadowDy; + global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_shadowRadius = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_shadowRadius; + global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_textColor = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_textColor; + global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_textColorHint = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_textColorHint; + global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_textColorLink = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_textColorLink; + global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_textSize = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_textSize; + global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_textStyle = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_textStyle; + global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_android_typeface = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_android_typeface; + global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_fontFamily = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_fontFamily; + global::Xamarin.Forms.Platform.Resource.Styleable.TextAppearance_textAllCaps = global::HelloworldXamarin.Droid.Resource.Styleable.TextAppearance_textAllCaps; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_android_hint = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_android_hint; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_android_textColorHint = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_android_textColorHint; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxBackgroundColor = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxBackgroundColor; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxBackgroundMode = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxBackgroundMode; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxCollapsedPaddingTop = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxCollapsedPaddingTop; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomEnd = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomEnd; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomStart = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusBottomStart; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxCornerRadiusTopEnd = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusTopEnd; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxCornerRadiusTopStart = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxCornerRadiusTopStart; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxStrokeColor = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxStrokeColor; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_boxStrokeWidth = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_boxStrokeWidth; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_counterEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_counterEnabled; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_counterMaxLength = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_counterMaxLength; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_counterOverflowTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_counterOverflowTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_counterTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_counterTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_errorEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_errorEnabled; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_errorTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_errorTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_helperText = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_helperText; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_helperTextEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_helperTextEnabled; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_helperTextTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_helperTextTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_hintAnimationEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_hintAnimationEnabled; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_hintEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_hintEnabled; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_hintTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_hintTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_passwordToggleContentDescription = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_passwordToggleContentDescription; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_passwordToggleDrawable = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_passwordToggleDrawable; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_passwordToggleEnabled = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_passwordToggleEnabled; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_passwordToggleTint = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_passwordToggleTint; + global::Xamarin.Forms.Platform.Resource.Styleable.TextInputLayout_passwordToggleTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.TextInputLayout_passwordToggleTintMode; + global::Xamarin.Forms.Platform.Resource.Styleable.ThemeEnforcement = global::HelloworldXamarin.Droid.Resource.Styleable.ThemeEnforcement; + global::Xamarin.Forms.Platform.Resource.Styleable.ThemeEnforcement_android_textAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.ThemeEnforcement_android_textAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.ThemeEnforcement_enforceMaterialTheme = global::HelloworldXamarin.Droid.Resource.Styleable.ThemeEnforcement_enforceMaterialTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.ThemeEnforcement_enforceTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.ThemeEnforcement_enforceTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_android_gravity = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_android_gravity; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_android_minHeight = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_android_minHeight; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_buttonGravity = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_buttonGravity; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_collapseContentDescription = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_collapseContentDescription; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_collapseIcon = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_collapseIcon; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_contentInsetEnd = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_contentInsetEnd; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_contentInsetEndWithActions = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_contentInsetEndWithActions; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_contentInsetLeft = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_contentInsetLeft; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_contentInsetRight = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_contentInsetRight; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_contentInsetStart = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_contentInsetStart; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_contentInsetStartWithNavigation = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_contentInsetStartWithNavigation; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_logo = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_logo; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_logoDescription = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_logoDescription; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_maxButtonHeight = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_maxButtonHeight; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_navigationContentDescription = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_navigationContentDescription; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_navigationIcon = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_navigationIcon; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_popupTheme = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_popupTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_subtitle = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_subtitle; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_subtitleTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_subtitleTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_subtitleTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_subtitleTextColor; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_title = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_title; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleMargin = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleMargin; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleMarginBottom = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleMarginBottom; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleMarginEnd = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleMarginEnd; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleMargins = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleMargins; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleMarginStart = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleMarginStart; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleMarginTop = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleMarginTop; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleTextAppearance = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleTextAppearance; + global::Xamarin.Forms.Platform.Resource.Styleable.Toolbar_titleTextColor = global::HelloworldXamarin.Droid.Resource.Styleable.Toolbar_titleTextColor; + global::Xamarin.Forms.Platform.Resource.Styleable.View = global::HelloworldXamarin.Droid.Resource.Styleable.View; + global::Xamarin.Forms.Platform.Resource.Styleable.ViewBackgroundHelper = global::HelloworldXamarin.Droid.Resource.Styleable.ViewBackgroundHelper; + global::Xamarin.Forms.Platform.Resource.Styleable.ViewBackgroundHelper_android_background = global::HelloworldXamarin.Droid.Resource.Styleable.ViewBackgroundHelper_android_background; + global::Xamarin.Forms.Platform.Resource.Styleable.ViewBackgroundHelper_backgroundTint = global::HelloworldXamarin.Droid.Resource.Styleable.ViewBackgroundHelper_backgroundTint; + global::Xamarin.Forms.Platform.Resource.Styleable.ViewBackgroundHelper_backgroundTintMode = global::HelloworldXamarin.Droid.Resource.Styleable.ViewBackgroundHelper_backgroundTintMode; + global::Xamarin.Forms.Platform.Resource.Styleable.ViewStubCompat = global::HelloworldXamarin.Droid.Resource.Styleable.ViewStubCompat; + global::Xamarin.Forms.Platform.Resource.Styleable.ViewStubCompat_android_id = global::HelloworldXamarin.Droid.Resource.Styleable.ViewStubCompat_android_id; + global::Xamarin.Forms.Platform.Resource.Styleable.ViewStubCompat_android_inflatedId = global::HelloworldXamarin.Droid.Resource.Styleable.ViewStubCompat_android_inflatedId; + global::Xamarin.Forms.Platform.Resource.Styleable.ViewStubCompat_android_layout = global::HelloworldXamarin.Droid.Resource.Styleable.ViewStubCompat_android_layout; + global::Xamarin.Forms.Platform.Resource.Styleable.View_android_focusable = global::HelloworldXamarin.Droid.Resource.Styleable.View_android_focusable; + global::Xamarin.Forms.Platform.Resource.Styleable.View_android_theme = global::HelloworldXamarin.Droid.Resource.Styleable.View_android_theme; + global::Xamarin.Forms.Platform.Resource.Styleable.View_paddingEnd = global::HelloworldXamarin.Droid.Resource.Styleable.View_paddingEnd; + global::Xamarin.Forms.Platform.Resource.Styleable.View_paddingStart = global::HelloworldXamarin.Droid.Resource.Styleable.View_paddingStart; + global::Xamarin.Forms.Platform.Resource.Styleable.View_theme = global::HelloworldXamarin.Droid.Resource.Styleable.View_theme; + } + + public partial class Animation + { + + // aapt resource value: 0x7F010000 + public const int abc_fade_in = 2130771968; + + // aapt resource value: 0x7F010001 + public const int abc_fade_out = 2130771969; + + // aapt resource value: 0x7F010002 + public const int abc_grow_fade_in_from_bottom = 2130771970; + + // aapt resource value: 0x7F010003 + public const int abc_popup_enter = 2130771971; + + // aapt resource value: 0x7F010004 + public const int abc_popup_exit = 2130771972; + + // aapt resource value: 0x7F010005 + public const int abc_shrink_fade_out_from_bottom = 2130771973; + + // aapt resource value: 0x7F010006 + public const int abc_slide_in_bottom = 2130771974; + + // aapt resource value: 0x7F010007 + public const int abc_slide_in_top = 2130771975; + + // aapt resource value: 0x7F010008 + public const int abc_slide_out_bottom = 2130771976; + + // aapt resource value: 0x7F010009 + public const int abc_slide_out_top = 2130771977; + + // aapt resource value: 0x7F01000A + public const int abc_tooltip_enter = 2130771978; + + // aapt resource value: 0x7F01000B + public const int abc_tooltip_exit = 2130771979; + + // aapt resource value: 0x7F01000C + public const int design_bottom_sheet_slide_in = 2130771980; + + // aapt resource value: 0x7F01000D + public const int design_bottom_sheet_slide_out = 2130771981; + + // aapt resource value: 0x7F01000E + public const int design_snackbar_in = 2130771982; + + // aapt resource value: 0x7F01000F + public const int design_snackbar_out = 2130771983; + + // aapt resource value: 0x7F010010 + public const int EnterFromLeft = 2130771984; + + // aapt resource value: 0x7F010011 + public const int EnterFromRight = 2130771985; + + // aapt resource value: 0x7F010012 + public const int ExitToLeft = 2130771986; + + // aapt resource value: 0x7F010013 + public const int ExitToRight = 2130771987; + + static Animation() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Animation() + { + } + } + + public partial class Animator + { + + // aapt resource value: 0x7F020000 + public const int design_appbar_state_list_animator = 2130837504; + + // aapt resource value: 0x7F020001 + public const int design_fab_hide_motion_spec = 2130837505; + + // aapt resource value: 0x7F020002 + public const int design_fab_show_motion_spec = 2130837506; + + // aapt resource value: 0x7F020003 + public const int mtrl_btn_state_list_anim = 2130837507; + + // aapt resource value: 0x7F020004 + public const int mtrl_btn_unelevated_state_list_anim = 2130837508; + + // aapt resource value: 0x7F020005 + public const int mtrl_chip_state_list_anim = 2130837509; + + // aapt resource value: 0x7F020006 + public const int mtrl_fab_hide_motion_spec = 2130837510; + + // aapt resource value: 0x7F020007 + public const int mtrl_fab_show_motion_spec = 2130837511; + + // aapt resource value: 0x7F020008 + public const int mtrl_fab_transformation_sheet_collapse_spec = 2130837512; + + // aapt resource value: 0x7F020009 + public const int mtrl_fab_transformation_sheet_expand_spec = 2130837513; + + static Animator() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Animator() + { + } + } + + public partial class Attribute + { + + // aapt resource value: 0x7F030000 + public const int actionBarDivider = 2130903040; + + // aapt resource value: 0x7F030001 + public const int actionBarItemBackground = 2130903041; + + // aapt resource value: 0x7F030002 + public const int actionBarPopupTheme = 2130903042; + + // aapt resource value: 0x7F030003 + public const int actionBarSize = 2130903043; + + // aapt resource value: 0x7F030004 + public const int actionBarSplitStyle = 2130903044; + + // aapt resource value: 0x7F030005 + public const int actionBarStyle = 2130903045; + + // aapt resource value: 0x7F030006 + public const int actionBarTabBarStyle = 2130903046; + + // aapt resource value: 0x7F030007 + public const int actionBarTabStyle = 2130903047; + + // aapt resource value: 0x7F030008 + public const int actionBarTabTextStyle = 2130903048; + + // aapt resource value: 0x7F030009 + public const int actionBarTheme = 2130903049; + + // aapt resource value: 0x7F03000A + public const int actionBarWidgetTheme = 2130903050; + + // aapt resource value: 0x7F03000B + public const int actionButtonStyle = 2130903051; + + // aapt resource value: 0x7F03000C + public const int actionDropDownStyle = 2130903052; + + // aapt resource value: 0x7F03000D + public const int actionLayout = 2130903053; + + // aapt resource value: 0x7F03000E + public const int actionMenuTextAppearance = 2130903054; + + // aapt resource value: 0x7F03000F + public const int actionMenuTextColor = 2130903055; + + // aapt resource value: 0x7F030010 + public const int actionModeBackground = 2130903056; + + // aapt resource value: 0x7F030011 + public const int actionModeCloseButtonStyle = 2130903057; + + // aapt resource value: 0x7F030012 + public const int actionModeCloseDrawable = 2130903058; + + // aapt resource value: 0x7F030013 + public const int actionModeCopyDrawable = 2130903059; + + // aapt resource value: 0x7F030014 + public const int actionModeCutDrawable = 2130903060; + + // aapt resource value: 0x7F030015 + public const int actionModeFindDrawable = 2130903061; + + // aapt resource value: 0x7F030016 + public const int actionModePasteDrawable = 2130903062; + + // aapt resource value: 0x7F030017 + public const int actionModePopupWindowStyle = 2130903063; + + // aapt resource value: 0x7F030018 + public const int actionModeSelectAllDrawable = 2130903064; + + // aapt resource value: 0x7F030019 + public const int actionModeShareDrawable = 2130903065; + + // aapt resource value: 0x7F03001A + public const int actionModeSplitBackground = 2130903066; + + // aapt resource value: 0x7F03001B + public const int actionModeStyle = 2130903067; + + // aapt resource value: 0x7F03001C + public const int actionModeWebSearchDrawable = 2130903068; + + // aapt resource value: 0x7F03001D + public const int actionOverflowButtonStyle = 2130903069; + + // aapt resource value: 0x7F03001E + public const int actionOverflowMenuStyle = 2130903070; + + // aapt resource value: 0x7F03001F + public const int actionProviderClass = 2130903071; + + // aapt resource value: 0x7F030020 + public const int actionViewClass = 2130903072; + + // aapt resource value: 0x7F030021 + public const int activityChooserViewStyle = 2130903073; + + // aapt resource value: 0x7F030022 + public const int alertDialogButtonGroupStyle = 2130903074; + + // aapt resource value: 0x7F030023 + public const int alertDialogCenterButtons = 2130903075; + + // aapt resource value: 0x7F030024 + public const int alertDialogStyle = 2130903076; + + // aapt resource value: 0x7F030025 + public const int alertDialogTheme = 2130903077; + + // aapt resource value: 0x7F030026 + public const int allowStacking = 2130903078; + + // aapt resource value: 0x7F030027 + public const int alpha = 2130903079; + + // aapt resource value: 0x7F030028 + public const int alphabeticModifiers = 2130903080; + + // aapt resource value: 0x7F030029 + public const int arrowHeadLength = 2130903081; + + // aapt resource value: 0x7F03002A + public const int arrowShaftLength = 2130903082; + + // aapt resource value: 0x7F03002B + public const int autoCompleteTextViewStyle = 2130903083; + + // aapt resource value: 0x7F03002C + public const int autoSizeMaxTextSize = 2130903084; + + // aapt resource value: 0x7F03002D + public const int autoSizeMinTextSize = 2130903085; + + // aapt resource value: 0x7F03002E + public const int autoSizePresetSizes = 2130903086; + + // aapt resource value: 0x7F03002F + public const int autoSizeStepGranularity = 2130903087; + + // aapt resource value: 0x7F030030 + public const int autoSizeTextType = 2130903088; + + // aapt resource value: 0x7F030031 + public const int background = 2130903089; + + // aapt resource value: 0x7F030032 + public const int backgroundSplit = 2130903090; + + // aapt resource value: 0x7F030033 + public const int backgroundStacked = 2130903091; + + // aapt resource value: 0x7F030034 + public const int backgroundTint = 2130903092; + + // aapt resource value: 0x7F030035 + public const int backgroundTintMode = 2130903093; + + // aapt resource value: 0x7F030036 + public const int barLength = 2130903094; + + // aapt resource value: 0x7F030037 + public const int behavior_autoHide = 2130903095; + + // aapt resource value: 0x7F030038 + public const int behavior_fitToContents = 2130903096; + + // aapt resource value: 0x7F030039 + public const int behavior_hideable = 2130903097; + + // aapt resource value: 0x7F03003A + public const int behavior_overlapTop = 2130903098; + + // aapt resource value: 0x7F03003B + public const int behavior_peekHeight = 2130903099; + + // aapt resource value: 0x7F03003C + public const int behavior_skipCollapsed = 2130903100; + + // aapt resource value: 0x7F03003E + public const int borderlessButtonStyle = 2130903102; + + // aapt resource value: 0x7F03003D + public const int borderWidth = 2130903101; + + // aapt resource value: 0x7F03003F + public const int bottomAppBarStyle = 2130903103; + + // aapt resource value: 0x7F030040 + public const int bottomNavigationStyle = 2130903104; + + // aapt resource value: 0x7F030041 + public const int bottomSheetDialogTheme = 2130903105; + + // aapt resource value: 0x7F030042 + public const int bottomSheetStyle = 2130903106; + + // aapt resource value: 0x7F030043 + public const int boxBackgroundColor = 2130903107; + + // aapt resource value: 0x7F030044 + public const int boxBackgroundMode = 2130903108; + + // aapt resource value: 0x7F030045 + public const int boxCollapsedPaddingTop = 2130903109; + + // aapt resource value: 0x7F030046 + public const int boxCornerRadiusBottomEnd = 2130903110; + + // aapt resource value: 0x7F030047 + public const int boxCornerRadiusBottomStart = 2130903111; + + // aapt resource value: 0x7F030048 + public const int boxCornerRadiusTopEnd = 2130903112; + + // aapt resource value: 0x7F030049 + public const int boxCornerRadiusTopStart = 2130903113; + + // aapt resource value: 0x7F03004A + public const int boxStrokeColor = 2130903114; + + // aapt resource value: 0x7F03004B + public const int boxStrokeWidth = 2130903115; + + // aapt resource value: 0x7F03004C + public const int buttonBarButtonStyle = 2130903116; + + // aapt resource value: 0x7F03004D + public const int buttonBarNegativeButtonStyle = 2130903117; + + // aapt resource value: 0x7F03004E + public const int buttonBarNeutralButtonStyle = 2130903118; + + // aapt resource value: 0x7F03004F + public const int buttonBarPositiveButtonStyle = 2130903119; + + // aapt resource value: 0x7F030050 + public const int buttonBarStyle = 2130903120; + + // aapt resource value: 0x7F030051 + public const int buttonGravity = 2130903121; + + // aapt resource value: 0x7F030052 + public const int buttonIconDimen = 2130903122; + + // aapt resource value: 0x7F030053 + public const int buttonPanelSideLayout = 2130903123; + + // aapt resource value: 0x7F030054 + public const int buttonStyle = 2130903124; + + // aapt resource value: 0x7F030055 + public const int buttonStyleSmall = 2130903125; + + // aapt resource value: 0x7F030056 + public const int buttonTint = 2130903126; + + // aapt resource value: 0x7F030057 + public const int buttonTintMode = 2130903127; + + // aapt resource value: 0x7F030058 + public const int cardBackgroundColor = 2130903128; + + // aapt resource value: 0x7F030059 + public const int cardCornerRadius = 2130903129; + + // aapt resource value: 0x7F03005A + public const int cardElevation = 2130903130; + + // aapt resource value: 0x7F03005B + public const int cardMaxElevation = 2130903131; + + // aapt resource value: 0x7F03005C + public const int cardPreventCornerOverlap = 2130903132; + + // aapt resource value: 0x7F03005D + public const int cardUseCompatPadding = 2130903133; + + // aapt resource value: 0x7F03005E + public const int cardViewStyle = 2130903134; + + // aapt resource value: 0x7F03005F + public const int checkboxStyle = 2130903135; + + // aapt resource value: 0x7F030060 + public const int checkedChip = 2130903136; + + // aapt resource value: 0x7F030061 + public const int checkedIcon = 2130903137; + + // aapt resource value: 0x7F030062 + public const int checkedIconEnabled = 2130903138; + + // aapt resource value: 0x7F030063 + public const int checkedIconVisible = 2130903139; + + // aapt resource value: 0x7F030064 + public const int checkedTextViewStyle = 2130903140; + + // aapt resource value: 0x7F030065 + public const int chipBackgroundColor = 2130903141; + + // aapt resource value: 0x7F030066 + public const int chipCornerRadius = 2130903142; + + // aapt resource value: 0x7F030067 + public const int chipEndPadding = 2130903143; + + // aapt resource value: 0x7F030068 + public const int chipGroupStyle = 2130903144; + + // aapt resource value: 0x7F030069 + public const int chipIcon = 2130903145; + + // aapt resource value: 0x7F03006A + public const int chipIconEnabled = 2130903146; + + // aapt resource value: 0x7F03006B + public const int chipIconSize = 2130903147; + + // aapt resource value: 0x7F03006C + public const int chipIconTint = 2130903148; + + // aapt resource value: 0x7F03006D + public const int chipIconVisible = 2130903149; + + // aapt resource value: 0x7F03006E + public const int chipMinHeight = 2130903150; + + // aapt resource value: 0x7F03006F + public const int chipSpacing = 2130903151; + + // aapt resource value: 0x7F030070 + public const int chipSpacingHorizontal = 2130903152; + + // aapt resource value: 0x7F030071 + public const int chipSpacingVertical = 2130903153; + + // aapt resource value: 0x7F030072 + public const int chipStandaloneStyle = 2130903154; + + // aapt resource value: 0x7F030073 + public const int chipStartPadding = 2130903155; + + // aapt resource value: 0x7F030074 + public const int chipStrokeColor = 2130903156; + + // aapt resource value: 0x7F030075 + public const int chipStrokeWidth = 2130903157; + + // aapt resource value: 0x7F030076 + public const int chipStyle = 2130903158; + + // aapt resource value: 0x7F030077 + public const int closeIcon = 2130903159; + + // aapt resource value: 0x7F030078 + public const int closeIconEnabled = 2130903160; + + // aapt resource value: 0x7F030079 + public const int closeIconEndPadding = 2130903161; + + // aapt resource value: 0x7F03007A + public const int closeIconSize = 2130903162; + + // aapt resource value: 0x7F03007B + public const int closeIconStartPadding = 2130903163; + + // aapt resource value: 0x7F03007C + public const int closeIconTint = 2130903164; + + // aapt resource value: 0x7F03007D + public const int closeIconVisible = 2130903165; + + // aapt resource value: 0x7F03007E + public const int closeItemLayout = 2130903166; + + // aapt resource value: 0x7F03007F + public const int collapseContentDescription = 2130903167; + + // aapt resource value: 0x7F030081 + public const int collapsedTitleGravity = 2130903169; + + // aapt resource value: 0x7F030082 + public const int collapsedTitleTextAppearance = 2130903170; + + // aapt resource value: 0x7F030080 + public const int collapseIcon = 2130903168; + + // aapt resource value: 0x7F030083 + public const int color = 2130903171; + + // aapt resource value: 0x7F030084 + public const int colorAccent = 2130903172; + + // aapt resource value: 0x7F030085 + public const int colorBackgroundFloating = 2130903173; + + // aapt resource value: 0x7F030086 + public const int colorButtonNormal = 2130903174; + + // aapt resource value: 0x7F030087 + public const int colorControlActivated = 2130903175; + + // aapt resource value: 0x7F030088 + public const int colorControlHighlight = 2130903176; + + // aapt resource value: 0x7F030089 + public const int colorControlNormal = 2130903177; + + // aapt resource value: 0x7F03008A + public const int colorError = 2130903178; + + // aapt resource value: 0x7F03008B + public const int colorPrimary = 2130903179; + + // aapt resource value: 0x7F03008C + public const int colorPrimaryDark = 2130903180; + + // aapt resource value: 0x7F03008D + public const int colorSecondary = 2130903181; + + // aapt resource value: 0x7F03008E + public const int colorSwitchThumbNormal = 2130903182; + + // aapt resource value: 0x7F03008F + public const int commitIcon = 2130903183; + + // aapt resource value: 0x7F030090 + public const int contentDescription = 2130903184; + + // aapt resource value: 0x7F030091 + public const int contentInsetEnd = 2130903185; + + // aapt resource value: 0x7F030092 + public const int contentInsetEndWithActions = 2130903186; + + // aapt resource value: 0x7F030093 + public const int contentInsetLeft = 2130903187; + + // aapt resource value: 0x7F030094 + public const int contentInsetRight = 2130903188; + + // aapt resource value: 0x7F030095 + public const int contentInsetStart = 2130903189; + + // aapt resource value: 0x7F030096 + public const int contentInsetStartWithNavigation = 2130903190; + + // aapt resource value: 0x7F030097 + public const int contentPadding = 2130903191; + + // aapt resource value: 0x7F030098 + public const int contentPaddingBottom = 2130903192; + + // aapt resource value: 0x7F030099 + public const int contentPaddingLeft = 2130903193; + + // aapt resource value: 0x7F03009A + public const int contentPaddingRight = 2130903194; + + // aapt resource value: 0x7F03009B + public const int contentPaddingTop = 2130903195; + + // aapt resource value: 0x7F03009C + public const int contentScrim = 2130903196; + + // aapt resource value: 0x7F03009D + public const int controlBackground = 2130903197; + + // aapt resource value: 0x7F03009E + public const int coordinatorLayoutStyle = 2130903198; + + // aapt resource value: 0x7F03009F + public const int cornerRadius = 2130903199; + + // aapt resource value: 0x7F0300A0 + public const int counterEnabled = 2130903200; + + // aapt resource value: 0x7F0300A1 + public const int counterMaxLength = 2130903201; + + // aapt resource value: 0x7F0300A2 + public const int counterOverflowTextAppearance = 2130903202; + + // aapt resource value: 0x7F0300A3 + public const int counterTextAppearance = 2130903203; + + // aapt resource value: 0x7F0300A4 + public const int customNavigationLayout = 2130903204; + + // aapt resource value: 0x7F0300A5 + public const int defaultQueryHint = 2130903205; + + // aapt resource value: 0x7F0300A6 + public const int dialogCornerRadius = 2130903206; + + // aapt resource value: 0x7F0300A7 + public const int dialogPreferredPadding = 2130903207; + + // aapt resource value: 0x7F0300A8 + public const int dialogTheme = 2130903208; + + // aapt resource value: 0x7F0300A9 + public const int displayOptions = 2130903209; + + // aapt resource value: 0x7F0300AA + public const int divider = 2130903210; + + // aapt resource value: 0x7F0300AB + public const int dividerHorizontal = 2130903211; + + // aapt resource value: 0x7F0300AC + public const int dividerPadding = 2130903212; + + // aapt resource value: 0x7F0300AD + public const int dividerVertical = 2130903213; + + // aapt resource value: 0x7F0300AE + public const int drawableSize = 2130903214; + + // aapt resource value: 0x7F0300AF + public const int drawerArrowStyle = 2130903215; + + // aapt resource value: 0x7F0300B1 + public const int dropdownListPreferredItemHeight = 2130903217; + + // aapt resource value: 0x7F0300B0 + public const int dropDownListViewStyle = 2130903216; + + // aapt resource value: 0x7F0300B2 + public const int editTextBackground = 2130903218; + + // aapt resource value: 0x7F0300B3 + public const int editTextColor = 2130903219; + + // aapt resource value: 0x7F0300B4 + public const int editTextStyle = 2130903220; + + // aapt resource value: 0x7F0300B5 + public const int elevation = 2130903221; + + // aapt resource value: 0x7F0300B6 + public const int enforceMaterialTheme = 2130903222; + + // aapt resource value: 0x7F0300B7 + public const int enforceTextAppearance = 2130903223; + + // aapt resource value: 0x7F0300B8 + public const int errorEnabled = 2130903224; + + // aapt resource value: 0x7F0300B9 + public const int errorTextAppearance = 2130903225; + + // aapt resource value: 0x7F0300BA + public const int expandActivityOverflowButtonDrawable = 2130903226; + + // aapt resource value: 0x7F0300BB + public const int expanded = 2130903227; + + // aapt resource value: 0x7F0300BC + public const int expandedTitleGravity = 2130903228; + + // aapt resource value: 0x7F0300BD + public const int expandedTitleMargin = 2130903229; + + // aapt resource value: 0x7F0300BE + public const int expandedTitleMarginBottom = 2130903230; + + // aapt resource value: 0x7F0300BF + public const int expandedTitleMarginEnd = 2130903231; + + // aapt resource value: 0x7F0300C0 + public const int expandedTitleMarginStart = 2130903232; + + // aapt resource value: 0x7F0300C1 + public const int expandedTitleMarginTop = 2130903233; + + // aapt resource value: 0x7F0300C2 + public const int expandedTitleTextAppearance = 2130903234; + + // aapt resource value: 0x7F0300C3 + public const int fabAlignmentMode = 2130903235; + + // aapt resource value: 0x7F0300C4 + public const int fabCradleMargin = 2130903236; + + // aapt resource value: 0x7F0300C5 + public const int fabCradleRoundedCornerRadius = 2130903237; + + // aapt resource value: 0x7F0300C6 + public const int fabCradleVerticalOffset = 2130903238; + + // aapt resource value: 0x7F0300C7 + public const int fabCustomSize = 2130903239; + + // aapt resource value: 0x7F0300C8 + public const int fabSize = 2130903240; + + // aapt resource value: 0x7F0300C9 + public const int fastScrollEnabled = 2130903241; + + // aapt resource value: 0x7F0300CA + public const int fastScrollHorizontalThumbDrawable = 2130903242; + + // aapt resource value: 0x7F0300CB + public const int fastScrollHorizontalTrackDrawable = 2130903243; + + // aapt resource value: 0x7F0300CC + public const int fastScrollVerticalThumbDrawable = 2130903244; + + // aapt resource value: 0x7F0300CD + public const int fastScrollVerticalTrackDrawable = 2130903245; + + // aapt resource value: 0x7F0300CE + public const int firstBaselineToTopHeight = 2130903246; + + // aapt resource value: 0x7F0300CF + public const int floatingActionButtonStyle = 2130903247; + + // aapt resource value: 0x7F0300D0 + public const int font = 2130903248; + + // aapt resource value: 0x7F0300D1 + public const int fontFamily = 2130903249; + + // aapt resource value: 0x7F0300D2 + public const int fontProviderAuthority = 2130903250; + + // aapt resource value: 0x7F0300D3 + public const int fontProviderCerts = 2130903251; + + // aapt resource value: 0x7F0300D4 + public const int fontProviderFetchStrategy = 2130903252; + + // aapt resource value: 0x7F0300D5 + public const int fontProviderFetchTimeout = 2130903253; + + // aapt resource value: 0x7F0300D6 + public const int fontProviderPackage = 2130903254; + + // aapt resource value: 0x7F0300D7 + public const int fontProviderQuery = 2130903255; + + // aapt resource value: 0x7F0300D8 + public const int fontStyle = 2130903256; + + // aapt resource value: 0x7F0300D9 + public const int fontVariationSettings = 2130903257; + + // aapt resource value: 0x7F0300DA + public const int fontWeight = 2130903258; + + // aapt resource value: 0x7F0300DB + public const int foregroundInsidePadding = 2130903259; + + // aapt resource value: 0x7F0300DC + public const int gapBetweenBars = 2130903260; + + // aapt resource value: 0x7F0300DD + public const int goIcon = 2130903261; + + // aapt resource value: 0x7F0300DE + public const int headerLayout = 2130903262; + + // aapt resource value: 0x7F0300DF + public const int height = 2130903263; + + // aapt resource value: 0x7F0300E0 + public const int helperText = 2130903264; + + // aapt resource value: 0x7F0300E1 + public const int helperTextEnabled = 2130903265; + + // aapt resource value: 0x7F0300E2 + public const int helperTextTextAppearance = 2130903266; + + // aapt resource value: 0x7F0300E3 + public const int hideMotionSpec = 2130903267; + + // aapt resource value: 0x7F0300E4 + public const int hideOnContentScroll = 2130903268; + + // aapt resource value: 0x7F0300E5 + public const int hideOnScroll = 2130903269; + + // aapt resource value: 0x7F0300E6 + public const int hintAnimationEnabled = 2130903270; + + // aapt resource value: 0x7F0300E7 + public const int hintEnabled = 2130903271; + + // aapt resource value: 0x7F0300E8 + public const int hintTextAppearance = 2130903272; + + // aapt resource value: 0x7F0300E9 + public const int homeAsUpIndicator = 2130903273; + + // aapt resource value: 0x7F0300EA + public const int homeLayout = 2130903274; + + // aapt resource value: 0x7F0300EB + public const int hoveredFocusedTranslationZ = 2130903275; + + // aapt resource value: 0x7F0300EC + public const int icon = 2130903276; + + // aapt resource value: 0x7F0300ED + public const int iconEndPadding = 2130903277; + + // aapt resource value: 0x7F0300EE + public const int iconGravity = 2130903278; + + // aapt resource value: 0x7F0300F4 + public const int iconifiedByDefault = 2130903284; + + // aapt resource value: 0x7F0300EF + public const int iconPadding = 2130903279; + + // aapt resource value: 0x7F0300F0 + public const int iconSize = 2130903280; + + // aapt resource value: 0x7F0300F1 + public const int iconStartPadding = 2130903281; + + // aapt resource value: 0x7F0300F2 + public const int iconTint = 2130903282; + + // aapt resource value: 0x7F0300F3 + public const int iconTintMode = 2130903283; + + // aapt resource value: 0x7F0300F5 + public const int imageButtonStyle = 2130903285; + + // aapt resource value: 0x7F0300F6 + public const int indeterminateProgressStyle = 2130903286; + + // aapt resource value: 0x7F0300F7 + public const int initialActivityCount = 2130903287; + + // aapt resource value: 0x7F0300F8 + public const int insetForeground = 2130903288; + + // aapt resource value: 0x7F0300F9 + public const int isLightTheme = 2130903289; + + // aapt resource value: 0x7F0300FA + public const int itemBackground = 2130903290; + + // aapt resource value: 0x7F0300FB + public const int itemHorizontalPadding = 2130903291; + + // aapt resource value: 0x7F0300FC + public const int itemHorizontalTranslationEnabled = 2130903292; + + // aapt resource value: 0x7F0300FD + public const int itemIconPadding = 2130903293; + + // aapt resource value: 0x7F0300FE + public const int itemIconSize = 2130903294; + + // aapt resource value: 0x7F0300FF + public const int itemIconTint = 2130903295; + + // aapt resource value: 0x7F030100 + public const int itemPadding = 2130903296; + + // aapt resource value: 0x7F030101 + public const int itemSpacing = 2130903297; + + // aapt resource value: 0x7F030102 + public const int itemTextAppearance = 2130903298; + + // aapt resource value: 0x7F030103 + public const int itemTextAppearanceActive = 2130903299; + + // aapt resource value: 0x7F030104 + public const int itemTextAppearanceInactive = 2130903300; + + // aapt resource value: 0x7F030105 + public const int itemTextColor = 2130903301; + + // aapt resource value: 0x7F030106 + public const int keylines = 2130903302; + + // aapt resource value: 0x7F030107 + public const int labelVisibilityMode = 2130903303; + + // aapt resource value: 0x7F030108 + public const int lastBaselineToBottomHeight = 2130903304; + + // aapt resource value: 0x7F030109 + public const int layout = 2130903305; + + // aapt resource value: 0x7F03010A + public const int layoutManager = 2130903306; + + // aapt resource value: 0x7F03010B + public const int layout_anchor = 2130903307; + + // aapt resource value: 0x7F03010C + public const int layout_anchorGravity = 2130903308; + + // aapt resource value: 0x7F03010D + public const int layout_behavior = 2130903309; + + // aapt resource value: 0x7F03010E + public const int layout_collapseMode = 2130903310; + + // aapt resource value: 0x7F03010F + public const int layout_collapseParallaxMultiplier = 2130903311; + + // aapt resource value: 0x7F030110 + public const int layout_dodgeInsetEdges = 2130903312; + + // aapt resource value: 0x7F030111 + public const int layout_insetEdge = 2130903313; + + // aapt resource value: 0x7F030112 + public const int layout_keyline = 2130903314; + + // aapt resource value: 0x7F030113 + public const int layout_scrollFlags = 2130903315; + + // aapt resource value: 0x7F030114 + public const int layout_scrollInterpolator = 2130903316; + + // aapt resource value: 0x7F030115 + public const int liftOnScroll = 2130903317; + + // aapt resource value: 0x7F030116 + public const int lineHeight = 2130903318; + + // aapt resource value: 0x7F030117 + public const int lineSpacing = 2130903319; + + // aapt resource value: 0x7F030118 + public const int listChoiceBackgroundIndicator = 2130903320; + + // aapt resource value: 0x7F030119 + public const int listDividerAlertDialog = 2130903321; + + // aapt resource value: 0x7F03011A + public const int listItemLayout = 2130903322; + + // aapt resource value: 0x7F03011B + public const int listLayout = 2130903323; + + // aapt resource value: 0x7F03011C + public const int listMenuViewStyle = 2130903324; + + // aapt resource value: 0x7F03011D + public const int listPopupWindowStyle = 2130903325; + + // aapt resource value: 0x7F03011E + public const int listPreferredItemHeight = 2130903326; + + // aapt resource value: 0x7F03011F + public const int listPreferredItemHeightLarge = 2130903327; + + // aapt resource value: 0x7F030120 + public const int listPreferredItemHeightSmall = 2130903328; + + // aapt resource value: 0x7F030121 + public const int listPreferredItemPaddingLeft = 2130903329; + + // aapt resource value: 0x7F030122 + public const int listPreferredItemPaddingRight = 2130903330; + + // aapt resource value: 0x7F030123 + public const int logo = 2130903331; + + // aapt resource value: 0x7F030124 + public const int logoDescription = 2130903332; + + // aapt resource value: 0x7F030125 + public const int materialButtonStyle = 2130903333; + + // aapt resource value: 0x7F030126 + public const int materialCardViewStyle = 2130903334; + + // aapt resource value: 0x7F030127 + public const int maxActionInlineWidth = 2130903335; + + // aapt resource value: 0x7F030128 + public const int maxButtonHeight = 2130903336; + + // aapt resource value: 0x7F030129 + public const int maxImageSize = 2130903337; + + // aapt resource value: 0x7F03012A + public const int measureWithLargestChild = 2130903338; + + // aapt resource value: 0x7F03012B + public const int menu = 2130903339; + + // aapt resource value: 0x7F03012C + public const int multiChoiceItemLayout = 2130903340; + + // aapt resource value: 0x7F03012D + public const int navigationContentDescription = 2130903341; + + // aapt resource value: 0x7F03012E + public const int navigationIcon = 2130903342; + + // aapt resource value: 0x7F03012F + public const int navigationMode = 2130903343; + + // aapt resource value: 0x7F030130 + public const int navigationViewStyle = 2130903344; + + // aapt resource value: 0x7F030131 + public const int numericModifiers = 2130903345; + + // aapt resource value: 0x7F030132 + public const int overlapAnchor = 2130903346; + + // aapt resource value: 0x7F030133 + public const int paddingBottomNoButtons = 2130903347; + + // aapt resource value: 0x7F030134 + public const int paddingEnd = 2130903348; + + // aapt resource value: 0x7F030135 + public const int paddingStart = 2130903349; + + // aapt resource value: 0x7F030136 + public const int paddingTopNoTitle = 2130903350; + + // aapt resource value: 0x7F030137 + public const int panelBackground = 2130903351; + + // aapt resource value: 0x7F030138 + public const int panelMenuListTheme = 2130903352; + + // aapt resource value: 0x7F030139 + public const int panelMenuListWidth = 2130903353; + + // aapt resource value: 0x7F03013A + public const int passwordToggleContentDescription = 2130903354; + + // aapt resource value: 0x7F03013B + public const int passwordToggleDrawable = 2130903355; + + // aapt resource value: 0x7F03013C + public const int passwordToggleEnabled = 2130903356; + + // aapt resource value: 0x7F03013D + public const int passwordToggleTint = 2130903357; + + // aapt resource value: 0x7F03013E + public const int passwordToggleTintMode = 2130903358; + + // aapt resource value: 0x7F03013F + public const int popupMenuStyle = 2130903359; + + // aapt resource value: 0x7F030140 + public const int popupTheme = 2130903360; + + // aapt resource value: 0x7F030141 + public const int popupWindowStyle = 2130903361; + + // aapt resource value: 0x7F030142 + public const int preserveIconSpacing = 2130903362; + + // aapt resource value: 0x7F030143 + public const int pressedTranslationZ = 2130903363; + + // aapt resource value: 0x7F030144 + public const int progressBarPadding = 2130903364; + + // aapt resource value: 0x7F030145 + public const int progressBarStyle = 2130903365; + + // aapt resource value: 0x7F030146 + public const int queryBackground = 2130903366; + + // aapt resource value: 0x7F030147 + public const int queryHint = 2130903367; + + // aapt resource value: 0x7F030148 + public const int radioButtonStyle = 2130903368; + + // aapt resource value: 0x7F030149 + public const int ratingBarStyle = 2130903369; + + // aapt resource value: 0x7F03014A + public const int ratingBarStyleIndicator = 2130903370; + + // aapt resource value: 0x7F03014B + public const int ratingBarStyleSmall = 2130903371; + + // aapt resource value: 0x7F03014C + public const int reverseLayout = 2130903372; + + // aapt resource value: 0x7F03014D + public const int rippleColor = 2130903373; + + // aapt resource value: 0x7F03014E + public const int scrimAnimationDuration = 2130903374; + + // aapt resource value: 0x7F03014F + public const int scrimBackground = 2130903375; + + // aapt resource value: 0x7F030150 + public const int scrimVisibleHeightTrigger = 2130903376; + + // aapt resource value: 0x7F030151 + public const int searchHintIcon = 2130903377; + + // aapt resource value: 0x7F030152 + public const int searchIcon = 2130903378; + + // aapt resource value: 0x7F030153 + public const int searchViewStyle = 2130903379; + + // aapt resource value: 0x7F030154 + public const int seekBarStyle = 2130903380; + + // aapt resource value: 0x7F030155 + public const int selectableItemBackground = 2130903381; + + // aapt resource value: 0x7F030156 + public const int selectableItemBackgroundBorderless = 2130903382; + + // aapt resource value: 0x7F030157 + public const int showAsAction = 2130903383; + + // aapt resource value: 0x7F030158 + public const int showDividers = 2130903384; + + // aapt resource value: 0x7F030159 + public const int showMotionSpec = 2130903385; + + // aapt resource value: 0x7F03015A + public const int showText = 2130903386; + + // aapt resource value: 0x7F03015B + public const int showTitle = 2130903387; + + // aapt resource value: 0x7F03015C + public const int singleChoiceItemLayout = 2130903388; + + // aapt resource value: 0x7F03015D + public const int singleLine = 2130903389; + + // aapt resource value: 0x7F03015E + public const int singleSelection = 2130903390; + + // aapt resource value: 0x7F03015F + public const int snackbarButtonStyle = 2130903391; + + // aapt resource value: 0x7F030160 + public const int snackbarStyle = 2130903392; + + // aapt resource value: 0x7F030161 + public const int spanCount = 2130903393; + + // aapt resource value: 0x7F030162 + public const int spinBars = 2130903394; + + // aapt resource value: 0x7F030163 + public const int spinnerDropDownItemStyle = 2130903395; + + // aapt resource value: 0x7F030164 + public const int spinnerStyle = 2130903396; + + // aapt resource value: 0x7F030165 + public const int splitTrack = 2130903397; + + // aapt resource value: 0x7F030166 + public const int srcCompat = 2130903398; + + // aapt resource value: 0x7F030167 + public const int stackFromEnd = 2130903399; + + // aapt resource value: 0x7F030168 + public const int state_above_anchor = 2130903400; + + // aapt resource value: 0x7F030169 + public const int state_collapsed = 2130903401; + + // aapt resource value: 0x7F03016A + public const int state_collapsible = 2130903402; + + // aapt resource value: 0x7F03016B + public const int state_liftable = 2130903403; + + // aapt resource value: 0x7F03016C + public const int state_lifted = 2130903404; + + // aapt resource value: 0x7F03016D + public const int statusBarBackground = 2130903405; + + // aapt resource value: 0x7F03016E + public const int statusBarScrim = 2130903406; + + // aapt resource value: 0x7F03016F + public const int strokeColor = 2130903407; + + // aapt resource value: 0x7F030170 + public const int strokeWidth = 2130903408; + + // aapt resource value: 0x7F030171 + public const int subMenuArrow = 2130903409; + + // aapt resource value: 0x7F030172 + public const int submitBackground = 2130903410; + + // aapt resource value: 0x7F030173 + public const int subtitle = 2130903411; + + // aapt resource value: 0x7F030174 + public const int subtitleTextAppearance = 2130903412; + + // aapt resource value: 0x7F030175 + public const int subtitleTextColor = 2130903413; + + // aapt resource value: 0x7F030176 + public const int subtitleTextStyle = 2130903414; + + // aapt resource value: 0x7F030177 + public const int suggestionRowLayout = 2130903415; + + // aapt resource value: 0x7F030178 + public const int switchMinWidth = 2130903416; + + // aapt resource value: 0x7F030179 + public const int switchPadding = 2130903417; + + // aapt resource value: 0x7F03017A + public const int switchStyle = 2130903418; + + // aapt resource value: 0x7F03017B + public const int switchTextAppearance = 2130903419; + + // aapt resource value: 0x7F03017C + public const int tabBackground = 2130903420; + + // aapt resource value: 0x7F03017D + public const int tabContentStart = 2130903421; + + // aapt resource value: 0x7F03017E + public const int tabGravity = 2130903422; + + // aapt resource value: 0x7F03017F + public const int tabIconTint = 2130903423; + + // aapt resource value: 0x7F030180 + public const int tabIconTintMode = 2130903424; + + // aapt resource value: 0x7F030181 + public const int tabIndicator = 2130903425; + + // aapt resource value: 0x7F030182 + public const int tabIndicatorAnimationDuration = 2130903426; + + // aapt resource value: 0x7F030183 + public const int tabIndicatorColor = 2130903427; + + // aapt resource value: 0x7F030184 + public const int tabIndicatorFullWidth = 2130903428; + + // aapt resource value: 0x7F030185 + public const int tabIndicatorGravity = 2130903429; + + // aapt resource value: 0x7F030186 + public const int tabIndicatorHeight = 2130903430; + + // aapt resource value: 0x7F030187 + public const int tabInlineLabel = 2130903431; + + // aapt resource value: 0x7F030188 + public const int tabMaxWidth = 2130903432; + + // aapt resource value: 0x7F030189 + public const int tabMinWidth = 2130903433; + + // aapt resource value: 0x7F03018A + public const int tabMode = 2130903434; + + // aapt resource value: 0x7F03018B + public const int tabPadding = 2130903435; + + // aapt resource value: 0x7F03018C + public const int tabPaddingBottom = 2130903436; + + // aapt resource value: 0x7F03018D + public const int tabPaddingEnd = 2130903437; + + // aapt resource value: 0x7F03018E + public const int tabPaddingStart = 2130903438; + + // aapt resource value: 0x7F03018F + public const int tabPaddingTop = 2130903439; + + // aapt resource value: 0x7F030190 + public const int tabRippleColor = 2130903440; + + // aapt resource value: 0x7F030191 + public const int tabSelectedTextColor = 2130903441; + + // aapt resource value: 0x7F030192 + public const int tabStyle = 2130903442; + + // aapt resource value: 0x7F030193 + public const int tabTextAppearance = 2130903443; + + // aapt resource value: 0x7F030194 + public const int tabTextColor = 2130903444; + + // aapt resource value: 0x7F030195 + public const int tabUnboundedRipple = 2130903445; + + // aapt resource value: 0x7F030196 + public const int textAllCaps = 2130903446; + + // aapt resource value: 0x7F030197 + public const int textAppearanceBody1 = 2130903447; + + // aapt resource value: 0x7F030198 + public const int textAppearanceBody2 = 2130903448; + + // aapt resource value: 0x7F030199 + public const int textAppearanceButton = 2130903449; + + // aapt resource value: 0x7F03019A + public const int textAppearanceCaption = 2130903450; + + // aapt resource value: 0x7F03019B + public const int textAppearanceHeadline1 = 2130903451; + + // aapt resource value: 0x7F03019C + public const int textAppearanceHeadline2 = 2130903452; + + // aapt resource value: 0x7F03019D + public const int textAppearanceHeadline3 = 2130903453; + + // aapt resource value: 0x7F03019E + public const int textAppearanceHeadline4 = 2130903454; + + // aapt resource value: 0x7F03019F + public const int textAppearanceHeadline5 = 2130903455; + + // aapt resource value: 0x7F0301A0 + public const int textAppearanceHeadline6 = 2130903456; + + // aapt resource value: 0x7F0301A1 + public const int textAppearanceLargePopupMenu = 2130903457; + + // aapt resource value: 0x7F0301A2 + public const int textAppearanceListItem = 2130903458; + + // aapt resource value: 0x7F0301A3 + public const int textAppearanceListItemSecondary = 2130903459; + + // aapt resource value: 0x7F0301A4 + public const int textAppearanceListItemSmall = 2130903460; + + // aapt resource value: 0x7F0301A5 + public const int textAppearanceOverline = 2130903461; + + // aapt resource value: 0x7F0301A6 + public const int textAppearancePopupMenuHeader = 2130903462; + + // aapt resource value: 0x7F0301A7 + public const int textAppearanceSearchResultSubtitle = 2130903463; + + // aapt resource value: 0x7F0301A8 + public const int textAppearanceSearchResultTitle = 2130903464; + + // aapt resource value: 0x7F0301A9 + public const int textAppearanceSmallPopupMenu = 2130903465; + + // aapt resource value: 0x7F0301AA + public const int textAppearanceSubtitle1 = 2130903466; + + // aapt resource value: 0x7F0301AB + public const int textAppearanceSubtitle2 = 2130903467; + + // aapt resource value: 0x7F0301AC + public const int textColorAlertDialogListItem = 2130903468; + + // aapt resource value: 0x7F0301AD + public const int textColorSearchUrl = 2130903469; + + // aapt resource value: 0x7F0301AE + public const int textEndPadding = 2130903470; + + // aapt resource value: 0x7F0301AF + public const int textInputStyle = 2130903471; + + // aapt resource value: 0x7F0301B0 + public const int textStartPadding = 2130903472; + + // aapt resource value: 0x7F0301B1 + public const int theme = 2130903473; + + // aapt resource value: 0x7F0301B2 + public const int thickness = 2130903474; + + // aapt resource value: 0x7F0301B3 + public const int thumbTextPadding = 2130903475; + + // aapt resource value: 0x7F0301B4 + public const int thumbTint = 2130903476; + + // aapt resource value: 0x7F0301B5 + public const int thumbTintMode = 2130903477; + + // aapt resource value: 0x7F0301B6 + public const int tickMark = 2130903478; + + // aapt resource value: 0x7F0301B7 + public const int tickMarkTint = 2130903479; + + // aapt resource value: 0x7F0301B8 + public const int tickMarkTintMode = 2130903480; + + // aapt resource value: 0x7F0301B9 + public const int tint = 2130903481; + + // aapt resource value: 0x7F0301BA + public const int tintMode = 2130903482; + + // aapt resource value: 0x7F0301BB + public const int title = 2130903483; + + // aapt resource value: 0x7F0301BC + public const int titleEnabled = 2130903484; + + // aapt resource value: 0x7F0301BD + public const int titleMargin = 2130903485; + + // aapt resource value: 0x7F0301BE + public const int titleMarginBottom = 2130903486; + + // aapt resource value: 0x7F0301BF + public const int titleMarginEnd = 2130903487; + + // aapt resource value: 0x7F0301C2 + public const int titleMargins = 2130903490; + + // aapt resource value: 0x7F0301C0 + public const int titleMarginStart = 2130903488; + + // aapt resource value: 0x7F0301C1 + public const int titleMarginTop = 2130903489; + + // aapt resource value: 0x7F0301C3 + public const int titleTextAppearance = 2130903491; + + // aapt resource value: 0x7F0301C4 + public const int titleTextColor = 2130903492; + + // aapt resource value: 0x7F0301C5 + public const int titleTextStyle = 2130903493; + + // aapt resource value: 0x7F0301C6 + public const int toolbarId = 2130903494; + + // aapt resource value: 0x7F0301C7 + public const int toolbarNavigationButtonStyle = 2130903495; + + // aapt resource value: 0x7F0301C8 + public const int toolbarStyle = 2130903496; + + // aapt resource value: 0x7F0301C9 + public const int tooltipForegroundColor = 2130903497; + + // aapt resource value: 0x7F0301CA + public const int tooltipFrameBackground = 2130903498; + + // aapt resource value: 0x7F0301CB + public const int tooltipText = 2130903499; + + // aapt resource value: 0x7F0301CC + public const int track = 2130903500; + + // aapt resource value: 0x7F0301CD + public const int trackTint = 2130903501; + + // aapt resource value: 0x7F0301CE + public const int trackTintMode = 2130903502; + + // aapt resource value: 0x7F0301CF + public const int ttcIndex = 2130903503; + + // aapt resource value: 0x7F0301D0 + public const int useCompatPadding = 2130903504; + + // aapt resource value: 0x7F0301D1 + public const int viewInflaterClass = 2130903505; + + // aapt resource value: 0x7F0301D2 + public const int voiceIcon = 2130903506; + + // aapt resource value: 0x7F0301D3 + public const int windowActionBar = 2130903507; + + // aapt resource value: 0x7F0301D4 + public const int windowActionBarOverlay = 2130903508; + + // aapt resource value: 0x7F0301D5 + public const int windowActionModeOverlay = 2130903509; + + // aapt resource value: 0x7F0301D6 + public const int windowFixedHeightMajor = 2130903510; + + // aapt resource value: 0x7F0301D7 + public const int windowFixedHeightMinor = 2130903511; + + // aapt resource value: 0x7F0301D8 + public const int windowFixedWidthMajor = 2130903512; + + // aapt resource value: 0x7F0301D9 + public const int windowFixedWidthMinor = 2130903513; + + // aapt resource value: 0x7F0301DA + public const int windowMinWidthMajor = 2130903514; + + // aapt resource value: 0x7F0301DB + public const int windowMinWidthMinor = 2130903515; + + // aapt resource value: 0x7F0301DC + public const int windowNoTitle = 2130903516; + + static Attribute() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Attribute() + { + } + } + + public partial class Boolean + { + + // aapt resource value: 0x7F040000 + public const int abc_action_bar_embed_tabs = 2130968576; + + // aapt resource value: 0x7F040001 + public const int abc_allow_stacked_button_bar = 2130968577; + + // aapt resource value: 0x7F040002 + public const int abc_config_actionMenuItemAllCaps = 2130968578; + + // aapt resource value: 0x7F040003 + public const int mtrl_btn_textappearance_all_caps = 2130968579; + + static Boolean() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Boolean() + { + } + } + + public partial class Color + { + + // aapt resource value: 0x7F050000 + public const int abc_background_cache_hint_selector_material_dark = 2131034112; + + // aapt resource value: 0x7F050001 + public const int abc_background_cache_hint_selector_material_light = 2131034113; + + // aapt resource value: 0x7F050002 + public const int abc_btn_colored_borderless_text_material = 2131034114; + + // aapt resource value: 0x7F050003 + public const int abc_btn_colored_text_material = 2131034115; + + // aapt resource value: 0x7F050004 + public const int abc_color_highlight_material = 2131034116; + + // aapt resource value: 0x7F050005 + public const int abc_hint_foreground_material_dark = 2131034117; + + // aapt resource value: 0x7F050006 + public const int abc_hint_foreground_material_light = 2131034118; + + // aapt resource value: 0x7F050007 + public const int abc_input_method_navigation_guard = 2131034119; + + // aapt resource value: 0x7F050008 + public const int abc_primary_text_disable_only_material_dark = 2131034120; + + // aapt resource value: 0x7F050009 + public const int abc_primary_text_disable_only_material_light = 2131034121; + + // aapt resource value: 0x7F05000A + public const int abc_primary_text_material_dark = 2131034122; + + // aapt resource value: 0x7F05000B + public const int abc_primary_text_material_light = 2131034123; + + // aapt resource value: 0x7F05000C + public const int abc_search_url_text = 2131034124; + + // aapt resource value: 0x7F05000D + public const int abc_search_url_text_normal = 2131034125; + + // aapt resource value: 0x7F05000E + public const int abc_search_url_text_pressed = 2131034126; + + // aapt resource value: 0x7F05000F + public const int abc_search_url_text_selected = 2131034127; + + // aapt resource value: 0x7F050010 + public const int abc_secondary_text_material_dark = 2131034128; + + // aapt resource value: 0x7F050011 + public const int abc_secondary_text_material_light = 2131034129; + + // aapt resource value: 0x7F050012 + public const int abc_tint_btn_checkable = 2131034130; + + // aapt resource value: 0x7F050013 + public const int abc_tint_default = 2131034131; + + // aapt resource value: 0x7F050014 + public const int abc_tint_edittext = 2131034132; + + // aapt resource value: 0x7F050015 + public const int abc_tint_seek_thumb = 2131034133; + + // aapt resource value: 0x7F050016 + public const int abc_tint_spinner = 2131034134; + + // aapt resource value: 0x7F050017 + public const int abc_tint_switch_track = 2131034135; + + // aapt resource value: 0x7F050018 + public const int accent_material_dark = 2131034136; + + // aapt resource value: 0x7F050019 + public const int accent_material_light = 2131034137; + + // aapt resource value: 0x7F05001A + public const int background_floating_material_dark = 2131034138; + + // aapt resource value: 0x7F05001B + public const int background_floating_material_light = 2131034139; + + // aapt resource value: 0x7F05001C + public const int background_material_dark = 2131034140; + + // aapt resource value: 0x7F05001D + public const int background_material_light = 2131034141; + + // aapt resource value: 0x7F05001E + public const int bright_foreground_disabled_material_dark = 2131034142; + + // aapt resource value: 0x7F05001F + public const int bright_foreground_disabled_material_light = 2131034143; + + // aapt resource value: 0x7F050020 + public const int bright_foreground_inverse_material_dark = 2131034144; + + // aapt resource value: 0x7F050021 + public const int bright_foreground_inverse_material_light = 2131034145; + + // aapt resource value: 0x7F050022 + public const int bright_foreground_material_dark = 2131034146; + + // aapt resource value: 0x7F050023 + public const int bright_foreground_material_light = 2131034147; + + // aapt resource value: 0x7F050024 + public const int browser_actions_bg_grey = 2131034148; + + // aapt resource value: 0x7F050025 + public const int browser_actions_divider_color = 2131034149; + + // aapt resource value: 0x7F050026 + public const int browser_actions_text_color = 2131034150; + + // aapt resource value: 0x7F050027 + public const int browser_actions_title_color = 2131034151; + + // aapt resource value: 0x7F050028 + public const int button_material_dark = 2131034152; + + // aapt resource value: 0x7F050029 + public const int button_material_light = 2131034153; + + // aapt resource value: 0x7F05002A + public const int cardview_dark_background = 2131034154; + + // aapt resource value: 0x7F05002B + public const int cardview_light_background = 2131034155; + + // aapt resource value: 0x7F05002C + public const int cardview_shadow_end_color = 2131034156; + + // aapt resource value: 0x7F05002D + public const int cardview_shadow_start_color = 2131034157; + + // aapt resource value: 0x7F05002E + public const int colorAccent = 2131034158; + + // aapt resource value: 0x7F05002F + public const int colorPrimary = 2131034159; + + // aapt resource value: 0x7F050030 + public const int colorPrimaryDark = 2131034160; + + // aapt resource value: 0x7F050031 + public const int design_bottom_navigation_shadow_color = 2131034161; + + // aapt resource value: 0x7F050032 + public const int design_default_color_primary = 2131034162; + + // aapt resource value: 0x7F050033 + public const int design_default_color_primary_dark = 2131034163; + + // aapt resource value: 0x7F050034 + public const int design_error = 2131034164; + + // aapt resource value: 0x7F050035 + public const int design_fab_shadow_end_color = 2131034165; + + // aapt resource value: 0x7F050036 + public const int design_fab_shadow_mid_color = 2131034166; + + // aapt resource value: 0x7F050037 + public const int design_fab_shadow_start_color = 2131034167; + + // aapt resource value: 0x7F050038 + public const int design_fab_stroke_end_inner_color = 2131034168; + + // aapt resource value: 0x7F050039 + public const int design_fab_stroke_end_outer_color = 2131034169; + + // aapt resource value: 0x7F05003A + public const int design_fab_stroke_top_inner_color = 2131034170; + + // aapt resource value: 0x7F05003B + public const int design_fab_stroke_top_outer_color = 2131034171; + + // aapt resource value: 0x7F05003C + public const int design_snackbar_background_color = 2131034172; + + // aapt resource value: 0x7F05003D + public const int design_tint_password_toggle = 2131034173; + + // aapt resource value: 0x7F05003E + public const int dim_foreground_disabled_material_dark = 2131034174; + + // aapt resource value: 0x7F05003F + public const int dim_foreground_disabled_material_light = 2131034175; + + // aapt resource value: 0x7F050040 + public const int dim_foreground_material_dark = 2131034176; + + // aapt resource value: 0x7F050041 + public const int dim_foreground_material_light = 2131034177; + + // aapt resource value: 0x7F050042 + public const int error_color_material_dark = 2131034178; + + // aapt resource value: 0x7F050043 + public const int error_color_material_light = 2131034179; + + // aapt resource value: 0x7F050044 + public const int foreground_material_dark = 2131034180; + + // aapt resource value: 0x7F050045 + public const int foreground_material_light = 2131034181; + + // aapt resource value: 0x7F050046 + public const int highlighted_text_material_dark = 2131034182; + + // aapt resource value: 0x7F050047 + public const int highlighted_text_material_light = 2131034183; + + // aapt resource value: 0x7F050048 + public const int launcher_background = 2131034184; + + // aapt resource value: 0x7F050049 + public const int material_blue_grey_800 = 2131034185; + + // aapt resource value: 0x7F05004A + public const int material_blue_grey_900 = 2131034186; + + // aapt resource value: 0x7F05004B + public const int material_blue_grey_950 = 2131034187; + + // aapt resource value: 0x7F05004C + public const int material_deep_teal_200 = 2131034188; + + // aapt resource value: 0x7F05004D + public const int material_deep_teal_500 = 2131034189; + + // aapt resource value: 0x7F05004E + public const int material_grey_100 = 2131034190; + + // aapt resource value: 0x7F05004F + public const int material_grey_300 = 2131034191; + + // aapt resource value: 0x7F050050 + public const int material_grey_50 = 2131034192; + + // aapt resource value: 0x7F050051 + public const int material_grey_600 = 2131034193; + + // aapt resource value: 0x7F050052 + public const int material_grey_800 = 2131034194; + + // aapt resource value: 0x7F050053 + public const int material_grey_850 = 2131034195; + + // aapt resource value: 0x7F050054 + public const int material_grey_900 = 2131034196; + + // aapt resource value: 0x7F050055 + public const int mtrl_bottom_nav_colored_item_tint = 2131034197; + + // aapt resource value: 0x7F050056 + public const int mtrl_bottom_nav_item_tint = 2131034198; + + // aapt resource value: 0x7F050057 + public const int mtrl_btn_bg_color_disabled = 2131034199; + + // aapt resource value: 0x7F050058 + public const int mtrl_btn_bg_color_selector = 2131034200; + + // aapt resource value: 0x7F050059 + public const int mtrl_btn_ripple_color = 2131034201; + + // aapt resource value: 0x7F05005A + public const int mtrl_btn_stroke_color_selector = 2131034202; + + // aapt resource value: 0x7F05005B + public const int mtrl_btn_text_btn_ripple_color = 2131034203; + + // aapt resource value: 0x7F05005C + public const int mtrl_btn_text_color_disabled = 2131034204; + + // aapt resource value: 0x7F05005D + public const int mtrl_btn_text_color_selector = 2131034205; + + // aapt resource value: 0x7F05005E + public const int mtrl_btn_transparent_bg_color = 2131034206; + + // aapt resource value: 0x7F05005F + public const int mtrl_chip_background_color = 2131034207; + + // aapt resource value: 0x7F050060 + public const int mtrl_chip_close_icon_tint = 2131034208; + + // aapt resource value: 0x7F050061 + public const int mtrl_chip_ripple_color = 2131034209; + + // aapt resource value: 0x7F050062 + public const int mtrl_chip_text_color = 2131034210; + + // aapt resource value: 0x7F050063 + public const int mtrl_fab_ripple_color = 2131034211; + + // aapt resource value: 0x7F050064 + public const int mtrl_scrim_color = 2131034212; + + // aapt resource value: 0x7F050065 + public const int mtrl_tabs_colored_ripple_color = 2131034213; + + // aapt resource value: 0x7F050066 + public const int mtrl_tabs_icon_color_selector = 2131034214; + + // aapt resource value: 0x7F050067 + public const int mtrl_tabs_icon_color_selector_colored = 2131034215; + + // aapt resource value: 0x7F050068 + public const int mtrl_tabs_legacy_text_color_selector = 2131034216; + + // aapt resource value: 0x7F050069 + public const int mtrl_tabs_ripple_color = 2131034217; + + // aapt resource value: 0x7F05006B + public const int mtrl_textinput_default_box_stroke_color = 2131034219; + + // aapt resource value: 0x7F05006C + public const int mtrl_textinput_disabled_color = 2131034220; + + // aapt resource value: 0x7F05006D + public const int mtrl_textinput_filled_box_default_background_color = 2131034221; + + // aapt resource value: 0x7F05006E + public const int mtrl_textinput_hovered_box_stroke_color = 2131034222; + + // aapt resource value: 0x7F05006A + public const int mtrl_text_btn_text_color_selector = 2131034218; + + // aapt resource value: 0x7F05006F + public const int notification_action_color_filter = 2131034223; + + // aapt resource value: 0x7F050070 + public const int notification_icon_bg_color = 2131034224; + + // aapt resource value: 0x7F050071 + public const int notification_material_background_media_default_color = 2131034225; + + // aapt resource value: 0x7F050072 + public const int primary_dark_material_dark = 2131034226; + + // aapt resource value: 0x7F050073 + public const int primary_dark_material_light = 2131034227; + + // aapt resource value: 0x7F050074 + public const int primary_material_dark = 2131034228; + + // aapt resource value: 0x7F050075 + public const int primary_material_light = 2131034229; + + // aapt resource value: 0x7F050076 + public const int primary_text_default_material_dark = 2131034230; + + // aapt resource value: 0x7F050077 + public const int primary_text_default_material_light = 2131034231; + + // aapt resource value: 0x7F050078 + public const int primary_text_disabled_material_dark = 2131034232; + + // aapt resource value: 0x7F050079 + public const int primary_text_disabled_material_light = 2131034233; + + // aapt resource value: 0x7F05007A + public const int ripple_material_dark = 2131034234; + + // aapt resource value: 0x7F05007B + public const int ripple_material_light = 2131034235; + + // aapt resource value: 0x7F05007C + public const int secondary_text_default_material_dark = 2131034236; + + // aapt resource value: 0x7F05007D + public const int secondary_text_default_material_light = 2131034237; + + // aapt resource value: 0x7F05007E + public const int secondary_text_disabled_material_dark = 2131034238; + + // aapt resource value: 0x7F05007F + public const int secondary_text_disabled_material_light = 2131034239; + + // aapt resource value: 0x7F050080 + public const int switch_thumb_disabled_material_dark = 2131034240; + + // aapt resource value: 0x7F050081 + public const int switch_thumb_disabled_material_light = 2131034241; + + // aapt resource value: 0x7F050082 + public const int switch_thumb_material_dark = 2131034242; + + // aapt resource value: 0x7F050083 + public const int switch_thumb_material_light = 2131034243; + + // aapt resource value: 0x7F050084 + public const int switch_thumb_normal_material_dark = 2131034244; + + // aapt resource value: 0x7F050085 + public const int switch_thumb_normal_material_light = 2131034245; + + // aapt resource value: 0x7F050086 + public const int tooltip_background_dark = 2131034246; + + // aapt resource value: 0x7F050087 + public const int tooltip_background_light = 2131034247; + + static Color() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Color() + { + } + } + + public partial class Dimension + { + + // aapt resource value: 0x7F060000 + public const int abc_action_bar_content_inset_material = 2131099648; + + // aapt resource value: 0x7F060001 + public const int abc_action_bar_content_inset_with_nav = 2131099649; + + // aapt resource value: 0x7F060002 + public const int abc_action_bar_default_height_material = 2131099650; + + // aapt resource value: 0x7F060003 + public const int abc_action_bar_default_padding_end_material = 2131099651; + + // aapt resource value: 0x7F060004 + public const int abc_action_bar_default_padding_start_material = 2131099652; + + // aapt resource value: 0x7F060005 + public const int abc_action_bar_elevation_material = 2131099653; + + // aapt resource value: 0x7F060006 + public const int abc_action_bar_icon_vertical_padding_material = 2131099654; + + // aapt resource value: 0x7F060007 + public const int abc_action_bar_overflow_padding_end_material = 2131099655; + + // aapt resource value: 0x7F060008 + public const int abc_action_bar_overflow_padding_start_material = 2131099656; + + // aapt resource value: 0x7F060009 + public const int abc_action_bar_stacked_max_height = 2131099657; + + // aapt resource value: 0x7F06000A + public const int abc_action_bar_stacked_tab_max_width = 2131099658; + + // aapt resource value: 0x7F06000B + public const int abc_action_bar_subtitle_bottom_margin_material = 2131099659; + + // aapt resource value: 0x7F06000C + public const int abc_action_bar_subtitle_top_margin_material = 2131099660; + + // aapt resource value: 0x7F06000D + public const int abc_action_button_min_height_material = 2131099661; + + // aapt resource value: 0x7F06000E + public const int abc_action_button_min_width_material = 2131099662; + + // aapt resource value: 0x7F06000F + public const int abc_action_button_min_width_overflow_material = 2131099663; + + // aapt resource value: 0x7F060010 + public const int abc_alert_dialog_button_bar_height = 2131099664; + + // aapt resource value: 0x7F060011 + public const int abc_alert_dialog_button_dimen = 2131099665; + + // aapt resource value: 0x7F060012 + public const int abc_button_inset_horizontal_material = 2131099666; + + // aapt resource value: 0x7F060013 + public const int abc_button_inset_vertical_material = 2131099667; + + // aapt resource value: 0x7F060014 + public const int abc_button_padding_horizontal_material = 2131099668; + + // aapt resource value: 0x7F060015 + public const int abc_button_padding_vertical_material = 2131099669; + + // aapt resource value: 0x7F060016 + public const int abc_cascading_menus_min_smallest_width = 2131099670; + + // aapt resource value: 0x7F060017 + public const int abc_config_prefDialogWidth = 2131099671; + + // aapt resource value: 0x7F060018 + public const int abc_control_corner_material = 2131099672; + + // aapt resource value: 0x7F060019 + public const int abc_control_inset_material = 2131099673; + + // aapt resource value: 0x7F06001A + public const int abc_control_padding_material = 2131099674; + + // aapt resource value: 0x7F06001B + public const int abc_dialog_corner_radius_material = 2131099675; + + // aapt resource value: 0x7F06001C + public const int abc_dialog_fixed_height_major = 2131099676; + + // aapt resource value: 0x7F06001D + public const int abc_dialog_fixed_height_minor = 2131099677; + + // aapt resource value: 0x7F06001E + public const int abc_dialog_fixed_width_major = 2131099678; + + // aapt resource value: 0x7F06001F + public const int abc_dialog_fixed_width_minor = 2131099679; + + // aapt resource value: 0x7F060020 + public const int abc_dialog_list_padding_bottom_no_buttons = 2131099680; + + // aapt resource value: 0x7F060021 + public const int abc_dialog_list_padding_top_no_title = 2131099681; + + // aapt resource value: 0x7F060022 + public const int abc_dialog_min_width_major = 2131099682; + + // aapt resource value: 0x7F060023 + public const int abc_dialog_min_width_minor = 2131099683; + + // aapt resource value: 0x7F060024 + public const int abc_dialog_padding_material = 2131099684; + + // aapt resource value: 0x7F060025 + public const int abc_dialog_padding_top_material = 2131099685; + + // aapt resource value: 0x7F060026 + public const int abc_dialog_title_divider_material = 2131099686; + + // aapt resource value: 0x7F060027 + public const int abc_disabled_alpha_material_dark = 2131099687; + + // aapt resource value: 0x7F060028 + public const int abc_disabled_alpha_material_light = 2131099688; + + // aapt resource value: 0x7F060029 + public const int abc_dropdownitem_icon_width = 2131099689; + + // aapt resource value: 0x7F06002A + public const int abc_dropdownitem_text_padding_left = 2131099690; + + // aapt resource value: 0x7F06002B + public const int abc_dropdownitem_text_padding_right = 2131099691; + + // aapt resource value: 0x7F06002C + public const int abc_edit_text_inset_bottom_material = 2131099692; + + // aapt resource value: 0x7F06002D + public const int abc_edit_text_inset_horizontal_material = 2131099693; + + // aapt resource value: 0x7F06002E + public const int abc_edit_text_inset_top_material = 2131099694; + + // aapt resource value: 0x7F06002F + public const int abc_floating_window_z = 2131099695; + + // aapt resource value: 0x7F060030 + public const int abc_list_item_padding_horizontal_material = 2131099696; + + // aapt resource value: 0x7F060031 + public const int abc_panel_menu_list_width = 2131099697; + + // aapt resource value: 0x7F060032 + public const int abc_progress_bar_height_material = 2131099698; + + // aapt resource value: 0x7F060033 + public const int abc_search_view_preferred_height = 2131099699; + + // aapt resource value: 0x7F060034 + public const int abc_search_view_preferred_width = 2131099700; + + // aapt resource value: 0x7F060035 + public const int abc_seekbar_track_background_height_material = 2131099701; + + // aapt resource value: 0x7F060036 + public const int abc_seekbar_track_progress_height_material = 2131099702; + + // aapt resource value: 0x7F060037 + public const int abc_select_dialog_padding_start_material = 2131099703; + + // aapt resource value: 0x7F060038 + public const int abc_switch_padding = 2131099704; + + // aapt resource value: 0x7F060039 + public const int abc_text_size_body_1_material = 2131099705; + + // aapt resource value: 0x7F06003A + public const int abc_text_size_body_2_material = 2131099706; + + // aapt resource value: 0x7F06003B + public const int abc_text_size_button_material = 2131099707; + + // aapt resource value: 0x7F06003C + public const int abc_text_size_caption_material = 2131099708; + + // aapt resource value: 0x7F06003D + public const int abc_text_size_display_1_material = 2131099709; + + // aapt resource value: 0x7F06003E + public const int abc_text_size_display_2_material = 2131099710; + + // aapt resource value: 0x7F06003F + public const int abc_text_size_display_3_material = 2131099711; + + // aapt resource value: 0x7F060040 + public const int abc_text_size_display_4_material = 2131099712; + + // aapt resource value: 0x7F060041 + public const int abc_text_size_headline_material = 2131099713; + + // aapt resource value: 0x7F060042 + public const int abc_text_size_large_material = 2131099714; + + // aapt resource value: 0x7F060043 + public const int abc_text_size_medium_material = 2131099715; + + // aapt resource value: 0x7F060044 + public const int abc_text_size_menu_header_material = 2131099716; + + // aapt resource value: 0x7F060045 + public const int abc_text_size_menu_material = 2131099717; + + // aapt resource value: 0x7F060046 + public const int abc_text_size_small_material = 2131099718; + + // aapt resource value: 0x7F060047 + public const int abc_text_size_subhead_material = 2131099719; + + // aapt resource value: 0x7F060048 + public const int abc_text_size_subtitle_material_toolbar = 2131099720; + + // aapt resource value: 0x7F060049 + public const int abc_text_size_title_material = 2131099721; + + // aapt resource value: 0x7F06004A + public const int abc_text_size_title_material_toolbar = 2131099722; + + // aapt resource value: 0x7F06004B + public const int browser_actions_context_menu_max_width = 2131099723; + + // aapt resource value: 0x7F06004C + public const int browser_actions_context_menu_min_padding = 2131099724; + + // aapt resource value: 0x7F06004D + public const int cardview_compat_inset_shadow = 2131099725; + + // aapt resource value: 0x7F06004E + public const int cardview_default_elevation = 2131099726; + + // aapt resource value: 0x7F06004F + public const int cardview_default_radius = 2131099727; + + // aapt resource value: 0x7F060050 + public const int compat_button_inset_horizontal_material = 2131099728; + + // aapt resource value: 0x7F060051 + public const int compat_button_inset_vertical_material = 2131099729; + + // aapt resource value: 0x7F060052 + public const int compat_button_padding_horizontal_material = 2131099730; + + // aapt resource value: 0x7F060053 + public const int compat_button_padding_vertical_material = 2131099731; + + // aapt resource value: 0x7F060054 + public const int compat_control_corner_material = 2131099732; + + // aapt resource value: 0x7F060055 + public const int compat_notification_large_icon_max_height = 2131099733; + + // aapt resource value: 0x7F060056 + public const int compat_notification_large_icon_max_width = 2131099734; + + // aapt resource value: 0x7F060057 + public const int design_appbar_elevation = 2131099735; + + // aapt resource value: 0x7F060058 + public const int design_bottom_navigation_active_item_max_width = 2131099736; + + // aapt resource value: 0x7F060059 + public const int design_bottom_navigation_active_item_min_width = 2131099737; + + // aapt resource value: 0x7F06005A + public const int design_bottom_navigation_active_text_size = 2131099738; + + // aapt resource value: 0x7F06005B + public const int design_bottom_navigation_elevation = 2131099739; + + // aapt resource value: 0x7F06005C + public const int design_bottom_navigation_height = 2131099740; + + // aapt resource value: 0x7F06005D + public const int design_bottom_navigation_icon_size = 2131099741; + + // aapt resource value: 0x7F06005E + public const int design_bottom_navigation_item_max_width = 2131099742; + + // aapt resource value: 0x7F06005F + public const int design_bottom_navigation_item_min_width = 2131099743; + + // aapt resource value: 0x7F060060 + public const int design_bottom_navigation_margin = 2131099744; + + // aapt resource value: 0x7F060061 + public const int design_bottom_navigation_shadow_height = 2131099745; + + // aapt resource value: 0x7F060062 + public const int design_bottom_navigation_text_size = 2131099746; + + // aapt resource value: 0x7F060063 + public const int design_bottom_sheet_modal_elevation = 2131099747; + + // aapt resource value: 0x7F060064 + public const int design_bottom_sheet_peek_height_min = 2131099748; + + // aapt resource value: 0x7F060065 + public const int design_fab_border_width = 2131099749; + + // aapt resource value: 0x7F060066 + public const int design_fab_elevation = 2131099750; + + // aapt resource value: 0x7F060067 + public const int design_fab_image_size = 2131099751; + + // aapt resource value: 0x7F060068 + public const int design_fab_size_mini = 2131099752; + + // aapt resource value: 0x7F060069 + public const int design_fab_size_normal = 2131099753; + + // aapt resource value: 0x7F06006A + public const int design_fab_translation_z_hovered_focused = 2131099754; + + // aapt resource value: 0x7F06006B + public const int design_fab_translation_z_pressed = 2131099755; + + // aapt resource value: 0x7F06006C + public const int design_navigation_elevation = 2131099756; + + // aapt resource value: 0x7F06006D + public const int design_navigation_icon_padding = 2131099757; + + // aapt resource value: 0x7F06006E + public const int design_navigation_icon_size = 2131099758; + + // aapt resource value: 0x7F06006F + public const int design_navigation_item_horizontal_padding = 2131099759; + + // aapt resource value: 0x7F060070 + public const int design_navigation_item_icon_padding = 2131099760; + + // aapt resource value: 0x7F060071 + public const int design_navigation_max_width = 2131099761; + + // aapt resource value: 0x7F060072 + public const int design_navigation_padding_bottom = 2131099762; + + // aapt resource value: 0x7F060073 + public const int design_navigation_separator_vertical_padding = 2131099763; + + // aapt resource value: 0x7F060074 + public const int design_snackbar_action_inline_max_width = 2131099764; + + // aapt resource value: 0x7F060075 + public const int design_snackbar_background_corner_radius = 2131099765; + + // aapt resource value: 0x7F060076 + public const int design_snackbar_elevation = 2131099766; + + // aapt resource value: 0x7F060077 + public const int design_snackbar_extra_spacing_horizontal = 2131099767; + + // aapt resource value: 0x7F060078 + public const int design_snackbar_max_width = 2131099768; + + // aapt resource value: 0x7F060079 + public const int design_snackbar_min_width = 2131099769; + + // aapt resource value: 0x7F06007A + public const int design_snackbar_padding_horizontal = 2131099770; + + // aapt resource value: 0x7F06007B + public const int design_snackbar_padding_vertical = 2131099771; + + // aapt resource value: 0x7F06007C + public const int design_snackbar_padding_vertical_2lines = 2131099772; + + // aapt resource value: 0x7F06007D + public const int design_snackbar_text_size = 2131099773; + + // aapt resource value: 0x7F06007E + public const int design_tab_max_width = 2131099774; + + // aapt resource value: 0x7F06007F + public const int design_tab_scrollable_min_width = 2131099775; + + // aapt resource value: 0x7F060080 + public const int design_tab_text_size = 2131099776; + + // aapt resource value: 0x7F060081 + public const int design_tab_text_size_2line = 2131099777; + + // aapt resource value: 0x7F060082 + public const int design_textinput_caption_translate_y = 2131099778; + + // aapt resource value: 0x7F060083 + public const int disabled_alpha_material_dark = 2131099779; + + // aapt resource value: 0x7F060084 + public const int disabled_alpha_material_light = 2131099780; + + // aapt resource value: 0x7F060085 + public const int fastscroll_default_thickness = 2131099781; + + // aapt resource value: 0x7F060086 + public const int fastscroll_margin = 2131099782; + + // aapt resource value: 0x7F060087 + public const int fastscroll_minimum_range = 2131099783; + + // aapt resource value: 0x7F060088 + public const int highlight_alpha_material_colored = 2131099784; + + // aapt resource value: 0x7F060089 + public const int highlight_alpha_material_dark = 2131099785; + + // aapt resource value: 0x7F06008A + public const int highlight_alpha_material_light = 2131099786; + + // aapt resource value: 0x7F06008B + public const int hint_alpha_material_dark = 2131099787; + + // aapt resource value: 0x7F06008C + public const int hint_alpha_material_light = 2131099788; + + // aapt resource value: 0x7F06008D + public const int hint_pressed_alpha_material_dark = 2131099789; + + // aapt resource value: 0x7F06008E + public const int hint_pressed_alpha_material_light = 2131099790; + + // aapt resource value: 0x7F06008F + public const int item_touch_helper_max_drag_scroll_per_frame = 2131099791; + + // aapt resource value: 0x7F060090 + public const int item_touch_helper_swipe_escape_max_velocity = 2131099792; + + // aapt resource value: 0x7F060091 + public const int item_touch_helper_swipe_escape_velocity = 2131099793; + + // aapt resource value: 0x7F060092 + public const int mtrl_bottomappbar_fabOffsetEndMode = 2131099794; + + // aapt resource value: 0x7F060093 + public const int mtrl_bottomappbar_fab_cradle_margin = 2131099795; + + // aapt resource value: 0x7F060094 + public const int mtrl_bottomappbar_fab_cradle_rounded_corner_radius = 2131099796; + + // aapt resource value: 0x7F060095 + public const int mtrl_bottomappbar_fab_cradle_vertical_offset = 2131099797; + + // aapt resource value: 0x7F060096 + public const int mtrl_bottomappbar_height = 2131099798; + + // aapt resource value: 0x7F060097 + public const int mtrl_btn_corner_radius = 2131099799; + + // aapt resource value: 0x7F060098 + public const int mtrl_btn_dialog_btn_min_width = 2131099800; + + // aapt resource value: 0x7F060099 + public const int mtrl_btn_disabled_elevation = 2131099801; + + // aapt resource value: 0x7F06009A + public const int mtrl_btn_disabled_z = 2131099802; + + // aapt resource value: 0x7F06009B + public const int mtrl_btn_elevation = 2131099803; + + // aapt resource value: 0x7F06009C + public const int mtrl_btn_focused_z = 2131099804; + + // aapt resource value: 0x7F06009D + public const int mtrl_btn_hovered_z = 2131099805; + + // aapt resource value: 0x7F06009E + public const int mtrl_btn_icon_btn_padding_left = 2131099806; + + // aapt resource value: 0x7F06009F + public const int mtrl_btn_icon_padding = 2131099807; + + // aapt resource value: 0x7F0600A0 + public const int mtrl_btn_inset = 2131099808; + + // aapt resource value: 0x7F0600A1 + public const int mtrl_btn_letter_spacing = 2131099809; + + // aapt resource value: 0x7F0600A2 + public const int mtrl_btn_padding_bottom = 2131099810; + + // aapt resource value: 0x7F0600A3 + public const int mtrl_btn_padding_left = 2131099811; + + // aapt resource value: 0x7F0600A4 + public const int mtrl_btn_padding_right = 2131099812; + + // aapt resource value: 0x7F0600A5 + public const int mtrl_btn_padding_top = 2131099813; + + // aapt resource value: 0x7F0600A6 + public const int mtrl_btn_pressed_z = 2131099814; + + // aapt resource value: 0x7F0600A7 + public const int mtrl_btn_stroke_size = 2131099815; + + // aapt resource value: 0x7F0600A8 + public const int mtrl_btn_text_btn_icon_padding = 2131099816; + + // aapt resource value: 0x7F0600A9 + public const int mtrl_btn_text_btn_padding_left = 2131099817; + + // aapt resource value: 0x7F0600AA + public const int mtrl_btn_text_btn_padding_right = 2131099818; + + // aapt resource value: 0x7F0600AB + public const int mtrl_btn_text_size = 2131099819; + + // aapt resource value: 0x7F0600AC + public const int mtrl_btn_z = 2131099820; + + // aapt resource value: 0x7F0600AD + public const int mtrl_card_elevation = 2131099821; + + // aapt resource value: 0x7F0600AE + public const int mtrl_card_spacing = 2131099822; + + // aapt resource value: 0x7F0600AF + public const int mtrl_chip_pressed_translation_z = 2131099823; + + // aapt resource value: 0x7F0600B0 + public const int mtrl_chip_text_size = 2131099824; + + // aapt resource value: 0x7F0600B1 + public const int mtrl_fab_elevation = 2131099825; + + // aapt resource value: 0x7F0600B2 + public const int mtrl_fab_translation_z_hovered_focused = 2131099826; + + // aapt resource value: 0x7F0600B3 + public const int mtrl_fab_translation_z_pressed = 2131099827; + + // aapt resource value: 0x7F0600B4 + public const int mtrl_navigation_elevation = 2131099828; + + // aapt resource value: 0x7F0600B5 + public const int mtrl_navigation_item_horizontal_padding = 2131099829; + + // aapt resource value: 0x7F0600B6 + public const int mtrl_navigation_item_icon_padding = 2131099830; + + // aapt resource value: 0x7F0600B7 + public const int mtrl_snackbar_background_corner_radius = 2131099831; + + // aapt resource value: 0x7F0600B8 + public const int mtrl_snackbar_margin = 2131099832; + + // aapt resource value: 0x7F0600B9 + public const int mtrl_textinput_box_bottom_offset = 2131099833; + + // aapt resource value: 0x7F0600BA + public const int mtrl_textinput_box_corner_radius_medium = 2131099834; + + // aapt resource value: 0x7F0600BB + public const int mtrl_textinput_box_corner_radius_small = 2131099835; + + // aapt resource value: 0x7F0600BC + public const int mtrl_textinput_box_label_cutout_padding = 2131099836; + + // aapt resource value: 0x7F0600BD + public const int mtrl_textinput_box_padding_end = 2131099837; + + // aapt resource value: 0x7F0600BE + public const int mtrl_textinput_box_stroke_width_default = 2131099838; + + // aapt resource value: 0x7F0600BF + public const int mtrl_textinput_box_stroke_width_focused = 2131099839; + + // aapt resource value: 0x7F0600C0 + public const int mtrl_textinput_outline_box_expanded_padding = 2131099840; + + // aapt resource value: 0x7F0600C1 + public const int mtrl_toolbar_default_height = 2131099841; + + // aapt resource value: 0x7F0600C2 + public const int notification_action_icon_size = 2131099842; + + // aapt resource value: 0x7F0600C3 + public const int notification_action_text_size = 2131099843; + + // aapt resource value: 0x7F0600C4 + public const int notification_big_circle_margin = 2131099844; + + // aapt resource value: 0x7F0600C5 + public const int notification_content_margin_start = 2131099845; + + // aapt resource value: 0x7F0600C6 + public const int notification_large_icon_height = 2131099846; + + // aapt resource value: 0x7F0600C7 + public const int notification_large_icon_width = 2131099847; + + // aapt resource value: 0x7F0600C8 + public const int notification_main_column_padding_top = 2131099848; + + // aapt resource value: 0x7F0600C9 + public const int notification_media_narrow_margin = 2131099849; + + // aapt resource value: 0x7F0600CA + public const int notification_right_icon_size = 2131099850; + + // aapt resource value: 0x7F0600CB + public const int notification_right_side_padding_top = 2131099851; + + // aapt resource value: 0x7F0600CC + public const int notification_small_icon_background_padding = 2131099852; + + // aapt resource value: 0x7F0600CD + public const int notification_small_icon_size_as_large = 2131099853; + + // aapt resource value: 0x7F0600CE + public const int notification_subtext_size = 2131099854; + + // aapt resource value: 0x7F0600CF + public const int notification_top_pad = 2131099855; + + // aapt resource value: 0x7F0600D0 + public const int notification_top_pad_large_text = 2131099856; + + // aapt resource value: 0x7F0600D1 + public const int subtitle_corner_radius = 2131099857; + + // aapt resource value: 0x7F0600D2 + public const int subtitle_outline_width = 2131099858; + + // aapt resource value: 0x7F0600D3 + public const int subtitle_shadow_offset = 2131099859; + + // aapt resource value: 0x7F0600D4 + public const int subtitle_shadow_radius = 2131099860; + + // aapt resource value: 0x7F0600D5 + public const int tooltip_corner_radius = 2131099861; + + // aapt resource value: 0x7F0600D6 + public const int tooltip_horizontal_padding = 2131099862; + + // aapt resource value: 0x7F0600D7 + public const int tooltip_margin = 2131099863; + + // aapt resource value: 0x7F0600D8 + public const int tooltip_precise_anchor_extra_offset = 2131099864; + + // aapt resource value: 0x7F0600D9 + public const int tooltip_precise_anchor_threshold = 2131099865; + + // aapt resource value: 0x7F0600DA + public const int tooltip_vertical_padding = 2131099866; + + // aapt resource value: 0x7F0600DB + public const int tooltip_y_offset_non_touch = 2131099867; + + // aapt resource value: 0x7F0600DC + public const int tooltip_y_offset_touch = 2131099868; + + static Dimension() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Dimension() + { + } + } + + public partial class Drawable + { + + // aapt resource value: 0x7F070006 + public const int abc_ab_share_pack_mtrl_alpha = 2131165190; + + // aapt resource value: 0x7F070007 + public const int abc_action_bar_item_background_material = 2131165191; + + // aapt resource value: 0x7F070008 + public const int abc_btn_borderless_material = 2131165192; + + // aapt resource value: 0x7F070009 + public const int abc_btn_check_material = 2131165193; + + // aapt resource value: 0x7F07000A + public const int abc_btn_check_to_on_mtrl_000 = 2131165194; + + // aapt resource value: 0x7F07000B + public const int abc_btn_check_to_on_mtrl_015 = 2131165195; + + // aapt resource value: 0x7F07000C + public const int abc_btn_colored_material = 2131165196; + + // aapt resource value: 0x7F07000D + public const int abc_btn_default_mtrl_shape = 2131165197; + + // aapt resource value: 0x7F07000E + public const int abc_btn_radio_material = 2131165198; + + // aapt resource value: 0x7F07000F + public const int abc_btn_radio_to_on_mtrl_000 = 2131165199; + + // aapt resource value: 0x7F070010 + public const int abc_btn_radio_to_on_mtrl_015 = 2131165200; + + // aapt resource value: 0x7F070011 + public const int abc_btn_switch_to_on_mtrl_00001 = 2131165201; + + // aapt resource value: 0x7F070012 + public const int abc_btn_switch_to_on_mtrl_00012 = 2131165202; + + // aapt resource value: 0x7F070013 + public const int abc_cab_background_internal_bg = 2131165203; + + // aapt resource value: 0x7F070014 + public const int abc_cab_background_top_material = 2131165204; + + // aapt resource value: 0x7F070015 + public const int abc_cab_background_top_mtrl_alpha = 2131165205; + + // aapt resource value: 0x7F070016 + public const int abc_control_background_material = 2131165206; + + // aapt resource value: 0x7F070017 + public const int abc_dialog_material_background = 2131165207; + + // aapt resource value: 0x7F070018 + public const int abc_edit_text_material = 2131165208; + + // aapt resource value: 0x7F070019 + public const int abc_ic_ab_back_material = 2131165209; + + // aapt resource value: 0x7F07001A + public const int abc_ic_arrow_drop_right_black_24dp = 2131165210; + + // aapt resource value: 0x7F07001B + public const int abc_ic_clear_material = 2131165211; + + // aapt resource value: 0x7F07001C + public const int abc_ic_commit_search_api_mtrl_alpha = 2131165212; + + // aapt resource value: 0x7F07001D + public const int abc_ic_go_search_api_material = 2131165213; + + // aapt resource value: 0x7F07001E + public const int abc_ic_menu_copy_mtrl_am_alpha = 2131165214; + + // aapt resource value: 0x7F07001F + public const int abc_ic_menu_cut_mtrl_alpha = 2131165215; + + // aapt resource value: 0x7F070020 + public const int abc_ic_menu_overflow_material = 2131165216; + + // aapt resource value: 0x7F070021 + public const int abc_ic_menu_paste_mtrl_am_alpha = 2131165217; + + // aapt resource value: 0x7F070022 + public const int abc_ic_menu_selectall_mtrl_alpha = 2131165218; + + // aapt resource value: 0x7F070023 + public const int abc_ic_menu_share_mtrl_alpha = 2131165219; + + // aapt resource value: 0x7F070024 + public const int abc_ic_search_api_material = 2131165220; + + // aapt resource value: 0x7F070025 + public const int abc_ic_star_black_16dp = 2131165221; + + // aapt resource value: 0x7F070026 + public const int abc_ic_star_black_36dp = 2131165222; + + // aapt resource value: 0x7F070027 + public const int abc_ic_star_black_48dp = 2131165223; + + // aapt resource value: 0x7F070028 + public const int abc_ic_star_half_black_16dp = 2131165224; + + // aapt resource value: 0x7F070029 + public const int abc_ic_star_half_black_36dp = 2131165225; + + // aapt resource value: 0x7F07002A + public const int abc_ic_star_half_black_48dp = 2131165226; + + // aapt resource value: 0x7F07002B + public const int abc_ic_voice_search_api_material = 2131165227; + + // aapt resource value: 0x7F07002C + public const int abc_item_background_holo_dark = 2131165228; + + // aapt resource value: 0x7F07002D + public const int abc_item_background_holo_light = 2131165229; + + // aapt resource value: 0x7F07002E + public const int abc_list_divider_material = 2131165230; + + // aapt resource value: 0x7F07002F + public const int abc_list_divider_mtrl_alpha = 2131165231; + + // aapt resource value: 0x7F070030 + public const int abc_list_focused_holo = 2131165232; + + // aapt resource value: 0x7F070031 + public const int abc_list_longpressed_holo = 2131165233; + + // aapt resource value: 0x7F070032 + public const int abc_list_pressed_holo_dark = 2131165234; + + // aapt resource value: 0x7F070033 + public const int abc_list_pressed_holo_light = 2131165235; + + // aapt resource value: 0x7F070034 + public const int abc_list_selector_background_transition_holo_dark = 2131165236; + + // aapt resource value: 0x7F070035 + public const int abc_list_selector_background_transition_holo_light = 2131165237; + + // aapt resource value: 0x7F070036 + public const int abc_list_selector_disabled_holo_dark = 2131165238; + + // aapt resource value: 0x7F070037 + public const int abc_list_selector_disabled_holo_light = 2131165239; + + // aapt resource value: 0x7F070038 + public const int abc_list_selector_holo_dark = 2131165240; + + // aapt resource value: 0x7F070039 + public const int abc_list_selector_holo_light = 2131165241; + + // aapt resource value: 0x7F07003A + public const int abc_menu_hardkey_panel_mtrl_mult = 2131165242; + + // aapt resource value: 0x7F07003B + public const int abc_popup_background_mtrl_mult = 2131165243; + + // aapt resource value: 0x7F07003C + public const int abc_ratingbar_indicator_material = 2131165244; + + // aapt resource value: 0x7F07003D + public const int abc_ratingbar_material = 2131165245; + + // aapt resource value: 0x7F07003E + public const int abc_ratingbar_small_material = 2131165246; + + // aapt resource value: 0x7F07003F + public const int abc_scrubber_control_off_mtrl_alpha = 2131165247; + + // aapt resource value: 0x7F070040 + public const int abc_scrubber_control_to_pressed_mtrl_000 = 2131165248; + + // aapt resource value: 0x7F070041 + public const int abc_scrubber_control_to_pressed_mtrl_005 = 2131165249; + + // aapt resource value: 0x7F070042 + public const int abc_scrubber_primary_mtrl_alpha = 2131165250; + + // aapt resource value: 0x7F070043 + public const int abc_scrubber_track_mtrl_alpha = 2131165251; + + // aapt resource value: 0x7F070044 + public const int abc_seekbar_thumb_material = 2131165252; + + // aapt resource value: 0x7F070045 + public const int abc_seekbar_tick_mark_material = 2131165253; + + // aapt resource value: 0x7F070046 + public const int abc_seekbar_track_material = 2131165254; + + // aapt resource value: 0x7F070047 + public const int abc_spinner_mtrl_am_alpha = 2131165255; + + // aapt resource value: 0x7F070048 + public const int abc_spinner_textfield_background_material = 2131165256; + + // aapt resource value: 0x7F070049 + public const int abc_switch_thumb_material = 2131165257; + + // aapt resource value: 0x7F07004A + public const int abc_switch_track_mtrl_alpha = 2131165258; + + // aapt resource value: 0x7F07004B + public const int abc_tab_indicator_material = 2131165259; + + // aapt resource value: 0x7F07004C + public const int abc_tab_indicator_mtrl_alpha = 2131165260; + + // aapt resource value: 0x7F070054 + public const int abc_textfield_activated_mtrl_alpha = 2131165268; + + // aapt resource value: 0x7F070055 + public const int abc_textfield_default_mtrl_alpha = 2131165269; + + // aapt resource value: 0x7F070056 + public const int abc_textfield_search_activated_mtrl_alpha = 2131165270; + + // aapt resource value: 0x7F070057 + public const int abc_textfield_search_default_mtrl_alpha = 2131165271; + + // aapt resource value: 0x7F070058 + public const int abc_textfield_search_material = 2131165272; + + // aapt resource value: 0x7F07004D + public const int abc_text_cursor_material = 2131165261; + + // aapt resource value: 0x7F07004E + public const int abc_text_select_handle_left_mtrl_dark = 2131165262; + + // aapt resource value: 0x7F07004F + public const int abc_text_select_handle_left_mtrl_light = 2131165263; + + // aapt resource value: 0x7F070050 + public const int abc_text_select_handle_middle_mtrl_dark = 2131165264; + + // aapt resource value: 0x7F070051 + public const int abc_text_select_handle_middle_mtrl_light = 2131165265; + + // aapt resource value: 0x7F070052 + public const int abc_text_select_handle_right_mtrl_dark = 2131165266; + + // aapt resource value: 0x7F070053 + public const int abc_text_select_handle_right_mtrl_light = 2131165267; + + // aapt resource value: 0x7F070059 + public const int abc_vector_test = 2131165273; + + // aapt resource value: 0x7F07005A + public const int avd_hide_password = 2131165274; + + // aapt resource value: 0x7F07005B + public const int avd_show_password = 2131165275; + + // aapt resource value: 0x7F07005C + public const int design_bottom_navigation_item_background = 2131165276; + + // aapt resource value: 0x7F07005D + public const int design_fab_background = 2131165277; + + // aapt resource value: 0x7F07005E + public const int design_ic_visibility = 2131165278; + + // aapt resource value: 0x7F07005F + public const int design_ic_visibility_off = 2131165279; + + // aapt resource value: 0x7F070060 + public const int design_password_eye = 2131165280; + + // aapt resource value: 0x7F070061 + public const int design_snackbar_background = 2131165281; + + // aapt resource value: 0x7F070062 + public const int ic_mtrl_chip_checked_black = 2131165282; + + // aapt resource value: 0x7F070063 + public const int ic_mtrl_chip_checked_circle = 2131165283; + + // aapt resource value: 0x7F070064 + public const int ic_mtrl_chip_close_circle = 2131165284; + + // aapt resource value: 0x7F070065 + public const int mtrl_snackbar_background = 2131165285; + + // aapt resource value: 0x7F070066 + public const int mtrl_tabs_default_indicator = 2131165286; + + // aapt resource value: 0x7F070067 + public const int navigation_empty_icon = 2131165287; + + // aapt resource value: 0x7F070068 + public const int notification_action_background = 2131165288; + + // aapt resource value: 0x7F070069 + public const int notification_bg = 2131165289; + + // aapt resource value: 0x7F07006A + public const int notification_bg_low = 2131165290; + + // aapt resource value: 0x7F07006B + public const int notification_bg_low_normal = 2131165291; + + // aapt resource value: 0x7F07006C + public const int notification_bg_low_pressed = 2131165292; + + // aapt resource value: 0x7F07006D + public const int notification_bg_normal = 2131165293; + + // aapt resource value: 0x7F07006E + public const int notification_bg_normal_pressed = 2131165294; + + // aapt resource value: 0x7F07006F + public const int notification_icon_background = 2131165295; + + // aapt resource value: 0x7F070070 + public const int notification_template_icon_bg = 2131165296; + + // aapt resource value: 0x7F070071 + public const int notification_template_icon_low_bg = 2131165297; + + // aapt resource value: 0x7F070072 + public const int notification_tile_bg = 2131165298; + + // aapt resource value: 0x7F070073 + public const int notify_panel_notification_icon_bg = 2131165299; + + // aapt resource value: 0x7F070074 + public const int tooltip_frame_dark = 2131165300; + + // aapt resource value: 0x7F070075 + public const int tooltip_frame_light = 2131165301; + + static Drawable() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Drawable() + { + } + } + + public partial class Id + { + + // aapt resource value: 0x7F080006 + public const int action0 = 2131230726; + + // aapt resource value: 0x7F080018 + public const int actions = 2131230744; + + // aapt resource value: 0x7F080007 + public const int action_bar = 2131230727; + + // aapt resource value: 0x7F080008 + public const int action_bar_activity_content = 2131230728; + + // aapt resource value: 0x7F080009 + public const int action_bar_container = 2131230729; + + // aapt resource value: 0x7F08000A + public const int action_bar_root = 2131230730; + + // aapt resource value: 0x7F08000B + public const int action_bar_spinner = 2131230731; + + // aapt resource value: 0x7F08000C + public const int action_bar_subtitle = 2131230732; + + // aapt resource value: 0x7F08000D + public const int action_bar_title = 2131230733; + + // aapt resource value: 0x7F08000E + public const int action_container = 2131230734; + + // aapt resource value: 0x7F08000F + public const int action_context_bar = 2131230735; + + // aapt resource value: 0x7F080010 + public const int action_divider = 2131230736; + + // aapt resource value: 0x7F080011 + public const int action_image = 2131230737; + + // aapt resource value: 0x7F080012 + public const int action_menu_divider = 2131230738; + + // aapt resource value: 0x7F080013 + public const int action_menu_presenter = 2131230739; + + // aapt resource value: 0x7F080014 + public const int action_mode_bar = 2131230740; + + // aapt resource value: 0x7F080015 + public const int action_mode_bar_stub = 2131230741; + + // aapt resource value: 0x7F080016 + public const int action_mode_close_button = 2131230742; + + // aapt resource value: 0x7F080017 + public const int action_text = 2131230743; + + // aapt resource value: 0x7F080019 + public const int activity_chooser_view_content = 2131230745; + + // aapt resource value: 0x7F08001A + public const int add = 2131230746; + + // aapt resource value: 0x7F08001B + public const int alertTitle = 2131230747; + + // aapt resource value: 0x7F08001C + public const int all = 2131230748; + + // aapt resource value: 0x7F080000 + public const int ALT = 2131230720; + + // aapt resource value: 0x7F08001D + public const int always = 2131230749; + + // aapt resource value: 0x7F08001E + public const int async = 2131230750; + + // aapt resource value: 0x7F08001F + public const int auto = 2131230751; + + // aapt resource value: 0x7F080020 + public const int beginning = 2131230752; + + // aapt resource value: 0x7F080021 + public const int blocking = 2131230753; + + // aapt resource value: 0x7F080022 + public const int bottom = 2131230754; + + // aapt resource value: 0x7F080023 + public const int bottomtab_navarea = 2131230755; + + // aapt resource value: 0x7F080024 + public const int bottomtab_tabbar = 2131230756; + + // aapt resource value: 0x7F080025 + public const int browser_actions_header_text = 2131230757; + + // aapt resource value: 0x7F080028 + public const int browser_actions_menu_items = 2131230760; + + // aapt resource value: 0x7F080026 + public const int browser_actions_menu_item_icon = 2131230758; + + // aapt resource value: 0x7F080027 + public const int browser_actions_menu_item_text = 2131230759; + + // aapt resource value: 0x7F080029 + public const int browser_actions_menu_view = 2131230761; + + // aapt resource value: 0x7F08002A + public const int buttonPanel = 2131230762; + + // aapt resource value: 0x7F08002B + public const int cancel_action = 2131230763; + + // aapt resource value: 0x7F08002C + public const int center = 2131230764; + + // aapt resource value: 0x7F08002D + public const int center_horizontal = 2131230765; + + // aapt resource value: 0x7F08002E + public const int center_vertical = 2131230766; + + // aapt resource value: 0x7F08002F + public const int checkbox = 2131230767; + + // aapt resource value: 0x7F080030 + public const int chronometer = 2131230768; + + // aapt resource value: 0x7F080031 + public const int clip_horizontal = 2131230769; + + // aapt resource value: 0x7F080032 + public const int clip_vertical = 2131230770; + + // aapt resource value: 0x7F080033 + public const int collapseActionView = 2131230771; + + // aapt resource value: 0x7F080034 + public const int container = 2131230772; + + // aapt resource value: 0x7F080035 + public const int content = 2131230773; + + // aapt resource value: 0x7F080036 + public const int contentPanel = 2131230774; + + // aapt resource value: 0x7F080037 + public const int coordinator = 2131230775; + + // aapt resource value: 0x7F080001 + public const int CTRL = 2131230721; + + // aapt resource value: 0x7F080038 + public const int custom = 2131230776; + + // aapt resource value: 0x7F080039 + public const int customPanel = 2131230777; + + // aapt resource value: 0x7F08003A + public const int decor_content_parent = 2131230778; + + // aapt resource value: 0x7F08003B + public const int default_activity_button = 2131230779; + + // aapt resource value: 0x7F08003C + public const int design_bottom_sheet = 2131230780; + + // aapt resource value: 0x7F08003D + public const int design_menu_item_action_area = 2131230781; + + // aapt resource value: 0x7F08003E + public const int design_menu_item_action_area_stub = 2131230782; + + // aapt resource value: 0x7F08003F + public const int design_menu_item_text = 2131230783; + + // aapt resource value: 0x7F080040 + public const int design_navigation_view = 2131230784; + + // aapt resource value: 0x7F080041 + public const int disableHome = 2131230785; + + // aapt resource value: 0x7F080042 + public const int edit_query = 2131230786; + + // aapt resource value: 0x7F080043 + public const int end = 2131230787; + + // aapt resource value: 0x7F080044 + public const int end_padder = 2131230788; + + // aapt resource value: 0x7F080045 + public const int enterAlways = 2131230789; + + // aapt resource value: 0x7F080046 + public const int enterAlwaysCollapsed = 2131230790; + + // aapt resource value: 0x7F080047 + public const int exitUntilCollapsed = 2131230791; + + // aapt resource value: 0x7F080049 + public const int expanded_menu = 2131230793; + + // aapt resource value: 0x7F080048 + public const int expand_activities_button = 2131230792; + + // aapt resource value: 0x7F08004A + public const int fill = 2131230794; + + // aapt resource value: 0x7F08004D + public const int filled = 2131230797; + + // aapt resource value: 0x7F08004B + public const int fill_horizontal = 2131230795; + + // aapt resource value: 0x7F08004C + public const int fill_vertical = 2131230796; + + // aapt resource value: 0x7F08004E + public const int @fixed = 2131230798; + + // aapt resource value: 0x7F08004F + public const int flyoutcontent_appbar = 2131230799; + + // aapt resource value: 0x7F080050 + public const int flyoutcontent_recycler = 2131230800; + + // aapt resource value: 0x7F080051 + public const int forever = 2131230801; + + // aapt resource value: 0x7F080002 + public const int FUNCTION = 2131230722; + + // aapt resource value: 0x7F080052 + public const int ghost_view = 2131230802; + + // aapt resource value: 0x7F080053 + public const int group_divider = 2131230803; + + // aapt resource value: 0x7F080054 + public const int home = 2131230804; + + // aapt resource value: 0x7F080055 + public const int homeAsUp = 2131230805; + + // aapt resource value: 0x7F080056 + public const int icon = 2131230806; + + // aapt resource value: 0x7F080057 + public const int icon_group = 2131230807; + + // aapt resource value: 0x7F080058 + public const int ifRoom = 2131230808; + + // aapt resource value: 0x7F080059 + public const int image = 2131230809; + + // aapt resource value: 0x7F08005A + public const int info = 2131230810; + + // aapt resource value: 0x7F08005B + public const int italic = 2131230811; + + // aapt resource value: 0x7F08005C + public const int item_touch_helper_previous_elevation = 2131230812; + + // aapt resource value: 0x7F08005D + public const int labeled = 2131230813; + + // aapt resource value: 0x7F08005E + public const int largeLabel = 2131230814; + + // aapt resource value: 0x7F08005F + public const int left = 2131230815; + + // aapt resource value: 0x7F080060 + public const int line1 = 2131230816; + + // aapt resource value: 0x7F080061 + public const int line3 = 2131230817; + + // aapt resource value: 0x7F080062 + public const int listMode = 2131230818; + + // aapt resource value: 0x7F080063 + public const int list_item = 2131230819; + + // aapt resource value: 0x7F080064 + public const int main_appbar = 2131230820; + + // aapt resource value: 0x7F080065 + public const int main_tablayout = 2131230821; + + // aapt resource value: 0x7F080066 + public const int main_toolbar = 2131230822; + + // aapt resource value: 0x7F080067 + public const int main_viewpager = 2131230823; + + // aapt resource value: 0x7F080068 + public const int masked = 2131230824; + + // aapt resource value: 0x7F080069 + public const int media_actions = 2131230825; + + // aapt resource value: 0x7F08006A + public const int message = 2131230826; + + // aapt resource value: 0x7F080003 + public const int META = 2131230723; + + // aapt resource value: 0x7F08006B + public const int middle = 2131230827; + + // aapt resource value: 0x7F08006C + public const int mini = 2131230828; + + // aapt resource value: 0x7F08006D + public const int mtrl_child_content_container = 2131230829; + + // aapt resource value: 0x7F08006E + public const int mtrl_internal_children_alpha_tag = 2131230830; + + // aapt resource value: 0x7F08006F + public const int multiply = 2131230831; + + // aapt resource value: 0x7F080070 + public const int navigation_header_container = 2131230832; + + // aapt resource value: 0x7F080071 + public const int never = 2131230833; + + // aapt resource value: 0x7F080072 + public const int none = 2131230834; + + // aapt resource value: 0x7F080073 + public const int normal = 2131230835; + + // aapt resource value: 0x7F080074 + public const int notification_background = 2131230836; + + // aapt resource value: 0x7F080075 + public const int notification_main_column = 2131230837; + + // aapt resource value: 0x7F080076 + public const int notification_main_column_container = 2131230838; + + // aapt resource value: 0x7F080077 + public const int outline = 2131230839; + + // aapt resource value: 0x7F080078 + public const int parallax = 2131230840; + + // aapt resource value: 0x7F080079 + public const int parentPanel = 2131230841; + + // aapt resource value: 0x7F08007A + public const int parent_matrix = 2131230842; + + // aapt resource value: 0x7F08007B + public const int pin = 2131230843; + + // aapt resource value: 0x7F08007C + public const int progress_circular = 2131230844; + + // aapt resource value: 0x7F08007D + public const int progress_horizontal = 2131230845; + + // aapt resource value: 0x7F08007E + public const int radio = 2131230846; + + // aapt resource value: 0x7F08007F + public const int right = 2131230847; + + // aapt resource value: 0x7F080080 + public const int right_icon = 2131230848; + + // aapt resource value: 0x7F080081 + public const int right_side = 2131230849; + + // aapt resource value: 0x7F080082 + public const int save_image_matrix = 2131230850; + + // aapt resource value: 0x7F080083 + public const int save_non_transition_alpha = 2131230851; + + // aapt resource value: 0x7F080084 + public const int save_scale_type = 2131230852; + + // aapt resource value: 0x7F080085 + public const int screen = 2131230853; + + // aapt resource value: 0x7F080086 + public const int scroll = 2131230854; + + // aapt resource value: 0x7F08008A + public const int scrollable = 2131230858; + + // aapt resource value: 0x7F080087 + public const int scrollIndicatorDown = 2131230855; + + // aapt resource value: 0x7F080088 + public const int scrollIndicatorUp = 2131230856; + + // aapt resource value: 0x7F080089 + public const int scrollView = 2131230857; + + // aapt resource value: 0x7F08008B + public const int search_badge = 2131230859; + + // aapt resource value: 0x7F08008C + public const int search_bar = 2131230860; + + // aapt resource value: 0x7F08008D + public const int search_button = 2131230861; + + // aapt resource value: 0x7F08008E + public const int search_close_btn = 2131230862; + + // aapt resource value: 0x7F08008F + public const int search_edit_frame = 2131230863; + + // aapt resource value: 0x7F080090 + public const int search_go_btn = 2131230864; + + // aapt resource value: 0x7F080091 + public const int search_mag_icon = 2131230865; + + // aapt resource value: 0x7F080092 + public const int search_plate = 2131230866; + + // aapt resource value: 0x7F080093 + public const int search_src_text = 2131230867; + + // aapt resource value: 0x7F080094 + public const int search_voice_btn = 2131230868; + + // aapt resource value: 0x7F080096 + public const int selected = 2131230870; + + // aapt resource value: 0x7F080095 + public const int select_dialog_listview = 2131230869; + + // aapt resource value: 0x7F080097 + public const int shellcontent_appbar = 2131230871; + + // aapt resource value: 0x7F080098 + public const int shellcontent_toolbar = 2131230872; + + // aapt resource value: 0x7F080004 + public const int SHIFT = 2131230724; + + // aapt resource value: 0x7F080099 + public const int shortcut = 2131230873; + + // aapt resource value: 0x7F08009A + public const int showCustom = 2131230874; + + // aapt resource value: 0x7F08009B + public const int showHome = 2131230875; + + // aapt resource value: 0x7F08009C + public const int showTitle = 2131230876; + + // aapt resource value: 0x7F08009D + public const int sliding_tabs = 2131230877; + + // aapt resource value: 0x7F08009E + public const int smallLabel = 2131230878; + + // aapt resource value: 0x7F08009F + public const int snackbar_action = 2131230879; + + // aapt resource value: 0x7F0800A0 + public const int snackbar_text = 2131230880; + + // aapt resource value: 0x7F0800A1 + public const int snap = 2131230881; + + // aapt resource value: 0x7F0800A2 + public const int snapMargins = 2131230882; + + // aapt resource value: 0x7F0800A3 + public const int spacer = 2131230883; + + // aapt resource value: 0x7F0800A4 + public const int split_action_bar = 2131230884; + + // aapt resource value: 0x7F0800A5 + public const int src_atop = 2131230885; + + // aapt resource value: 0x7F0800A6 + public const int src_in = 2131230886; + + // aapt resource value: 0x7F0800A7 + public const int src_over = 2131230887; + + // aapt resource value: 0x7F0800A8 + public const int start = 2131230888; + + // aapt resource value: 0x7F0800A9 + public const int status_bar_latest_event_content = 2131230889; + + // aapt resource value: 0x7F0800AA + public const int stretch = 2131230890; + + // aapt resource value: 0x7F0800AB + public const int submenuarrow = 2131230891; + + // aapt resource value: 0x7F0800AC + public const int submit_area = 2131230892; + + // aapt resource value: 0x7F080005 + public const int SYM = 2131230725; + + // aapt resource value: 0x7F0800AD + public const int tabMode = 2131230893; + + // aapt resource value: 0x7F0800AE + public const int tag_transition_group = 2131230894; + + // aapt resource value: 0x7F0800AF + public const int tag_unhandled_key_event_manager = 2131230895; + + // aapt resource value: 0x7F0800B0 + public const int tag_unhandled_key_listeners = 2131230896; + + // aapt resource value: 0x7F0800B1 + public const int text = 2131230897; + + // aapt resource value: 0x7F0800B2 + public const int text2 = 2131230898; + + // aapt resource value: 0x7F0800B7 + public const int textinput_counter = 2131230903; + + // aapt resource value: 0x7F0800B8 + public const int textinput_error = 2131230904; + + // aapt resource value: 0x7F0800B9 + public const int textinput_helper_text = 2131230905; + + // aapt resource value: 0x7F0800B3 + public const int textSpacerNoButtons = 2131230899; + + // aapt resource value: 0x7F0800B4 + public const int textSpacerNoTitle = 2131230900; + + // aapt resource value: 0x7F0800B5 + public const int textStart = 2131230901; + + // aapt resource value: 0x7F0800B6 + public const int text_input_password_toggle = 2131230902; + + // aapt resource value: 0x7F0800BA + public const int time = 2131230906; + + // aapt resource value: 0x7F0800BB + public const int title = 2131230907; + + // aapt resource value: 0x7F0800BC + public const int titleDividerNoCustom = 2131230908; + + // aapt resource value: 0x7F0800BD + public const int title_template = 2131230909; + + // aapt resource value: 0x7F0800BE + public const int toolbar = 2131230910; + + // aapt resource value: 0x7F0800BF + public const int top = 2131230911; + + // aapt resource value: 0x7F0800C0 + public const int topPanel = 2131230912; + + // aapt resource value: 0x7F0800C1 + public const int touch_outside = 2131230913; + + // aapt resource value: 0x7F0800C2 + public const int transition_current_scene = 2131230914; + + // aapt resource value: 0x7F0800C3 + public const int transition_layout_save = 2131230915; + + // aapt resource value: 0x7F0800C4 + public const int transition_position = 2131230916; + + // aapt resource value: 0x7F0800C5 + public const int transition_scene_layoutid_cache = 2131230917; + + // aapt resource value: 0x7F0800C6 + public const int transition_transform = 2131230918; + + // aapt resource value: 0x7F0800C7 + public const int uniform = 2131230919; + + // aapt resource value: 0x7F0800C8 + public const int unlabeled = 2131230920; + + // aapt resource value: 0x7F0800C9 + public const int up = 2131230921; + + // aapt resource value: 0x7F0800CA + public const int useLogo = 2131230922; + + // aapt resource value: 0x7F0800CB + public const int view_offset_helper = 2131230923; + + // aapt resource value: 0x7F0800CC + public const int visible = 2131230924; + + // aapt resource value: 0x7F0800CD + public const int withText = 2131230925; + + // aapt resource value: 0x7F0800CE + public const int wrap_content = 2131230926; + + static Id() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Id() + { + } + } + + public partial class Integer + { + + // aapt resource value: 0x7F090000 + public const int abc_config_activityDefaultDur = 2131296256; + + // aapt resource value: 0x7F090001 + public const int abc_config_activityShortDur = 2131296257; + + // aapt resource value: 0x7F090002 + public const int app_bar_elevation_anim_duration = 2131296258; + + // aapt resource value: 0x7F090003 + public const int bottom_sheet_slide_duration = 2131296259; + + // aapt resource value: 0x7F090004 + public const int cancel_button_image_alpha = 2131296260; + + // aapt resource value: 0x7F090005 + public const int config_tooltipAnimTime = 2131296261; + + // aapt resource value: 0x7F090006 + public const int design_snackbar_text_max_lines = 2131296262; + + // aapt resource value: 0x7F090007 + public const int design_tab_indicator_anim_duration_ms = 2131296263; + + // aapt resource value: 0x7F090008 + public const int hide_password_duration = 2131296264; + + // aapt resource value: 0x7F090009 + public const int mtrl_btn_anim_delay_ms = 2131296265; + + // aapt resource value: 0x7F09000A + public const int mtrl_btn_anim_duration_ms = 2131296266; + + // aapt resource value: 0x7F09000B + public const int mtrl_chip_anim_duration = 2131296267; + + // aapt resource value: 0x7F09000C + public const int mtrl_tab_indicator_anim_duration_ms = 2131296268; + + // aapt resource value: 0x7F09000D + public const int show_password_duration = 2131296269; + + // aapt resource value: 0x7F09000E + public const int status_bar_notification_info_maxnum = 2131296270; + + static Integer() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Integer() + { + } + } + + public partial class Interpolator + { + + // aapt resource value: 0x7F0A0000 + public const int mtrl_fast_out_linear_in = 2131361792; + + // aapt resource value: 0x7F0A0001 + public const int mtrl_fast_out_slow_in = 2131361793; + + // aapt resource value: 0x7F0A0002 + public const int mtrl_linear = 2131361794; + + // aapt resource value: 0x7F0A0003 + public const int mtrl_linear_out_slow_in = 2131361795; + + static Interpolator() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Interpolator() + { + } + } + + public partial class Layout + { + + // aapt resource value: 0x7F0B0000 + public const int abc_action_bar_title_item = 2131427328; + + // aapt resource value: 0x7F0B0001 + public const int abc_action_bar_up_container = 2131427329; + + // aapt resource value: 0x7F0B0002 + public const int abc_action_menu_item_layout = 2131427330; + + // aapt resource value: 0x7F0B0003 + public const int abc_action_menu_layout = 2131427331; + + // aapt resource value: 0x7F0B0004 + public const int abc_action_mode_bar = 2131427332; + + // aapt resource value: 0x7F0B0005 + public const int abc_action_mode_close_item_material = 2131427333; + + // aapt resource value: 0x7F0B0006 + public const int abc_activity_chooser_view = 2131427334; + + // aapt resource value: 0x7F0B0007 + public const int abc_activity_chooser_view_list_item = 2131427335; + + // aapt resource value: 0x7F0B0008 + public const int abc_alert_dialog_button_bar_material = 2131427336; + + // aapt resource value: 0x7F0B0009 + public const int abc_alert_dialog_material = 2131427337; + + // aapt resource value: 0x7F0B000A + public const int abc_alert_dialog_title_material = 2131427338; + + // aapt resource value: 0x7F0B000B + public const int abc_cascading_menu_item_layout = 2131427339; + + // aapt resource value: 0x7F0B000C + public const int abc_dialog_title_material = 2131427340; + + // aapt resource value: 0x7F0B000D + public const int abc_expanded_menu_layout = 2131427341; + + // aapt resource value: 0x7F0B000E + public const int abc_list_menu_item_checkbox = 2131427342; + + // aapt resource value: 0x7F0B000F + public const int abc_list_menu_item_icon = 2131427343; + + // aapt resource value: 0x7F0B0010 + public const int abc_list_menu_item_layout = 2131427344; + + // aapt resource value: 0x7F0B0011 + public const int abc_list_menu_item_radio = 2131427345; + + // aapt resource value: 0x7F0B0012 + public const int abc_popup_menu_header_item_layout = 2131427346; + + // aapt resource value: 0x7F0B0013 + public const int abc_popup_menu_item_layout = 2131427347; + + // aapt resource value: 0x7F0B0014 + public const int abc_screen_content_include = 2131427348; + + // aapt resource value: 0x7F0B0015 + public const int abc_screen_simple = 2131427349; + + // aapt resource value: 0x7F0B0016 + public const int abc_screen_simple_overlay_action_mode = 2131427350; + + // aapt resource value: 0x7F0B0017 + public const int abc_screen_toolbar = 2131427351; + + // aapt resource value: 0x7F0B0018 + public const int abc_search_dropdown_item_icons_2line = 2131427352; + + // aapt resource value: 0x7F0B0019 + public const int abc_search_view = 2131427353; + + // aapt resource value: 0x7F0B001A + public const int abc_select_dialog_material = 2131427354; + + // aapt resource value: 0x7F0B001B + public const int abc_tooltip = 2131427355; + + // aapt resource value: 0x7F0B001C + public const int BottomTabLayout = 2131427356; + + // aapt resource value: 0x7F0B001D + public const int browser_actions_context_menu_page = 2131427357; + + // aapt resource value: 0x7F0B001E + public const int browser_actions_context_menu_row = 2131427358; + + // aapt resource value: 0x7F0B001F + public const int design_bottom_navigation_item = 2131427359; + + // aapt resource value: 0x7F0B0020 + public const int design_bottom_sheet_dialog = 2131427360; + + // aapt resource value: 0x7F0B0021 + public const int design_layout_snackbar = 2131427361; + + // aapt resource value: 0x7F0B0022 + public const int design_layout_snackbar_include = 2131427362; + + // aapt resource value: 0x7F0B0023 + public const int design_layout_tab_icon = 2131427363; + + // aapt resource value: 0x7F0B0024 + public const int design_layout_tab_text = 2131427364; + + // aapt resource value: 0x7F0B0025 + public const int design_menu_item_action_area = 2131427365; + + // aapt resource value: 0x7F0B0026 + public const int design_navigation_item = 2131427366; + + // aapt resource value: 0x7F0B0027 + public const int design_navigation_item_header = 2131427367; + + // aapt resource value: 0x7F0B0028 + public const int design_navigation_item_separator = 2131427368; + + // aapt resource value: 0x7F0B0029 + public const int design_navigation_item_subheader = 2131427369; + + // aapt resource value: 0x7F0B002A + public const int design_navigation_menu = 2131427370; + + // aapt resource value: 0x7F0B002B + public const int design_navigation_menu_item = 2131427371; + + // aapt resource value: 0x7F0B002C + public const int design_text_input_password_icon = 2131427372; + + // aapt resource value: 0x7F0B002D + public const int FlyoutContent = 2131427373; + + // aapt resource value: 0x7F0B002E + public const int mtrl_layout_snackbar = 2131427374; + + // aapt resource value: 0x7F0B002F + public const int mtrl_layout_snackbar_include = 2131427375; + + // aapt resource value: 0x7F0B0030 + public const int notification_action = 2131427376; + + // aapt resource value: 0x7F0B0031 + public const int notification_action_tombstone = 2131427377; + + // aapt resource value: 0x7F0B0032 + public const int notification_media_action = 2131427378; + + // aapt resource value: 0x7F0B0033 + public const int notification_media_cancel_action = 2131427379; + + // aapt resource value: 0x7F0B0034 + public const int notification_template_big_media = 2131427380; + + // aapt resource value: 0x7F0B0035 + public const int notification_template_big_media_custom = 2131427381; + + // aapt resource value: 0x7F0B0036 + public const int notification_template_big_media_narrow = 2131427382; + + // aapt resource value: 0x7F0B0037 + public const int notification_template_big_media_narrow_custom = 2131427383; + + // aapt resource value: 0x7F0B0038 + public const int notification_template_custom_big = 2131427384; + + // aapt resource value: 0x7F0B0039 + public const int notification_template_icon_group = 2131427385; + + // aapt resource value: 0x7F0B003A + public const int notification_template_lines_media = 2131427386; + + // aapt resource value: 0x7F0B003B + public const int notification_template_media = 2131427387; + + // aapt resource value: 0x7F0B003C + public const int notification_template_media_custom = 2131427388; + + // aapt resource value: 0x7F0B003D + public const int notification_template_part_chronometer = 2131427389; + + // aapt resource value: 0x7F0B003E + public const int notification_template_part_time = 2131427390; + + // aapt resource value: 0x7F0B003F + public const int RootLayout = 2131427391; + + // aapt resource value: 0x7F0B0040 + public const int select_dialog_item_material = 2131427392; + + // aapt resource value: 0x7F0B0041 + public const int select_dialog_multichoice_material = 2131427393; + + // aapt resource value: 0x7F0B0042 + public const int select_dialog_singlechoice_material = 2131427394; + + // aapt resource value: 0x7F0B0043 + public const int ShellContent = 2131427395; + + // aapt resource value: 0x7F0B0044 + public const int support_simple_spinner_dropdown_item = 2131427396; + + // aapt resource value: 0x7F0B0045 + public const int Tabbar = 2131427397; + + // aapt resource value: 0x7F0B0046 + public const int Toolbar = 2131427398; + + static Layout() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Layout() + { + } + } + + public partial class Mipmap + { + + // aapt resource value: 0x7F0C0000 + public const int icon = 2131492864; + + // aapt resource value: 0x7F0C0001 + public const int icon_round = 2131492865; + + // aapt resource value: 0x7F0C0002 + public const int launcher_foreground = 2131492866; + + static Mipmap() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Mipmap() + { + } + } + + public partial class String + { + + // aapt resource value: 0x7F0D0000 + public const int abc_action_bar_home_description = 2131558400; + + // aapt resource value: 0x7F0D0001 + public const int abc_action_bar_up_description = 2131558401; + + // aapt resource value: 0x7F0D0002 + public const int abc_action_menu_overflow_description = 2131558402; + + // aapt resource value: 0x7F0D0003 + public const int abc_action_mode_done = 2131558403; + + // aapt resource value: 0x7F0D0005 + public const int abc_activitychooserview_choose_application = 2131558405; + + // aapt resource value: 0x7F0D0004 + public const int abc_activity_chooser_view_see_all = 2131558404; + + // aapt resource value: 0x7F0D0006 + public const int abc_capital_off = 2131558406; + + // aapt resource value: 0x7F0D0007 + public const int abc_capital_on = 2131558407; + + // aapt resource value: 0x7F0D0008 + public const int abc_font_family_body_1_material = 2131558408; + + // aapt resource value: 0x7F0D0009 + public const int abc_font_family_body_2_material = 2131558409; + + // aapt resource value: 0x7F0D000A + public const int abc_font_family_button_material = 2131558410; + + // aapt resource value: 0x7F0D000B + public const int abc_font_family_caption_material = 2131558411; + + // aapt resource value: 0x7F0D000C + public const int abc_font_family_display_1_material = 2131558412; + + // aapt resource value: 0x7F0D000D + public const int abc_font_family_display_2_material = 2131558413; + + // aapt resource value: 0x7F0D000E + public const int abc_font_family_display_3_material = 2131558414; + + // aapt resource value: 0x7F0D000F + public const int abc_font_family_display_4_material = 2131558415; + + // aapt resource value: 0x7F0D0010 + public const int abc_font_family_headline_material = 2131558416; + + // aapt resource value: 0x7F0D0011 + public const int abc_font_family_menu_material = 2131558417; + + // aapt resource value: 0x7F0D0012 + public const int abc_font_family_subhead_material = 2131558418; + + // aapt resource value: 0x7F0D0013 + public const int abc_font_family_title_material = 2131558419; + + // aapt resource value: 0x7F0D0014 + public const int abc_menu_alt_shortcut_label = 2131558420; + + // aapt resource value: 0x7F0D0015 + public const int abc_menu_ctrl_shortcut_label = 2131558421; + + // aapt resource value: 0x7F0D0016 + public const int abc_menu_delete_shortcut_label = 2131558422; + + // aapt resource value: 0x7F0D0017 + public const int abc_menu_enter_shortcut_label = 2131558423; + + // aapt resource value: 0x7F0D0018 + public const int abc_menu_function_shortcut_label = 2131558424; + + // aapt resource value: 0x7F0D0019 + public const int abc_menu_meta_shortcut_label = 2131558425; + + // aapt resource value: 0x7F0D001A + public const int abc_menu_shift_shortcut_label = 2131558426; + + // aapt resource value: 0x7F0D001B + public const int abc_menu_space_shortcut_label = 2131558427; + + // aapt resource value: 0x7F0D001C + public const int abc_menu_sym_shortcut_label = 2131558428; + + // aapt resource value: 0x7F0D001D + public const int abc_prepend_shortcut_label = 2131558429; + + // aapt resource value: 0x7F0D001F + public const int abc_searchview_description_clear = 2131558431; + + // aapt resource value: 0x7F0D0020 + public const int abc_searchview_description_query = 2131558432; + + // aapt resource value: 0x7F0D0021 + public const int abc_searchview_description_search = 2131558433; + + // aapt resource value: 0x7F0D0022 + public const int abc_searchview_description_submit = 2131558434; + + // aapt resource value: 0x7F0D0023 + public const int abc_searchview_description_voice = 2131558435; + + // aapt resource value: 0x7F0D001E + public const int abc_search_hint = 2131558430; + + // aapt resource value: 0x7F0D0024 + public const int abc_shareactionprovider_share_with = 2131558436; + + // aapt resource value: 0x7F0D0025 + public const int abc_shareactionprovider_share_with_application = 2131558437; + + // aapt resource value: 0x7F0D0026 + public const int abc_toolbar_collapse_description = 2131558438; + + // aapt resource value: 0x7F0D0027 + public const int appbar_scrolling_view_behavior = 2131558439; + + // aapt resource value: 0x7F0D0028 + public const int bottom_sheet_behavior = 2131558440; + + // aapt resource value: 0x7F0D0029 + public const int character_counter_content_description = 2131558441; + + // aapt resource value: 0x7F0D002A + public const int character_counter_pattern = 2131558442; + + // aapt resource value: 0x7F0D002B + public const int fab_transformation_scrim_behavior = 2131558443; + + // aapt resource value: 0x7F0D002C + public const int fab_transformation_sheet_behavior = 2131558444; + + // aapt resource value: 0x7F0D002D + public const int hide_bottom_view_on_scroll_behavior = 2131558445; + + // aapt resource value: 0x7F0D002E + public const int mtrl_chip_close_icon_content_description = 2131558446; + + // aapt resource value: 0x7F0D002F + public const int password_toggle_content_description = 2131558447; + + // aapt resource value: 0x7F0D0030 + public const int path_password_eye = 2131558448; + + // aapt resource value: 0x7F0D0031 + public const int path_password_eye_mask_strike_through = 2131558449; + + // aapt resource value: 0x7F0D0032 + public const int path_password_eye_mask_visible = 2131558450; + + // aapt resource value: 0x7F0D0033 + public const int path_password_strike_through = 2131558451; + + // aapt resource value: 0x7F0D0034 + public const int search_menu_title = 2131558452; + + // aapt resource value: 0x7F0D0035 + public const int status_bar_notification_info_overflow = 2131558453; + + static String() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private String() + { + } + } + + public partial class Style + { + + // aapt resource value: 0x7F0E0000 + public const int AlertDialog_AppCompat = 2131623936; + + // aapt resource value: 0x7F0E0001 + public const int AlertDialog_AppCompat_Light = 2131623937; + + // aapt resource value: 0x7F0E0002 + public const int Animation_AppCompat_Dialog = 2131623938; + + // aapt resource value: 0x7F0E0003 + public const int Animation_AppCompat_DropDownUp = 2131623939; + + // aapt resource value: 0x7F0E0004 + public const int Animation_AppCompat_Tooltip = 2131623940; + + // aapt resource value: 0x7F0E0005 + public const int Animation_Design_BottomSheetDialog = 2131623941; + + // aapt resource value: 0x7F0E0006 + public const int AppCompatDialogStyle = 2131623942; + + // aapt resource value: 0x7F0E0007 + public const int Base_AlertDialog_AppCompat = 2131623943; + + // aapt resource value: 0x7F0E0008 + public const int Base_AlertDialog_AppCompat_Light = 2131623944; + + // aapt resource value: 0x7F0E0009 + public const int Base_Animation_AppCompat_Dialog = 2131623945; + + // aapt resource value: 0x7F0E000A + public const int Base_Animation_AppCompat_DropDownUp = 2131623946; + + // aapt resource value: 0x7F0E000B + public const int Base_Animation_AppCompat_Tooltip = 2131623947; + + // aapt resource value: 0x7F0E000C + public const int Base_CardView = 2131623948; + + // aapt resource value: 0x7F0E000E + public const int Base_DialogWindowTitleBackground_AppCompat = 2131623950; + + // aapt resource value: 0x7F0E000D + public const int Base_DialogWindowTitle_AppCompat = 2131623949; + + // aapt resource value: 0x7F0E000F + public const int Base_TextAppearance_AppCompat = 2131623951; + + // aapt resource value: 0x7F0E0010 + public const int Base_TextAppearance_AppCompat_Body1 = 2131623952; + + // aapt resource value: 0x7F0E0011 + public const int Base_TextAppearance_AppCompat_Body2 = 2131623953; + + // aapt resource value: 0x7F0E0012 + public const int Base_TextAppearance_AppCompat_Button = 2131623954; + + // aapt resource value: 0x7F0E0013 + public const int Base_TextAppearance_AppCompat_Caption = 2131623955; + + // aapt resource value: 0x7F0E0014 + public const int Base_TextAppearance_AppCompat_Display1 = 2131623956; + + // aapt resource value: 0x7F0E0015 + public const int Base_TextAppearance_AppCompat_Display2 = 2131623957; + + // aapt resource value: 0x7F0E0016 + public const int Base_TextAppearance_AppCompat_Display3 = 2131623958; + + // aapt resource value: 0x7F0E0017 + public const int Base_TextAppearance_AppCompat_Display4 = 2131623959; + + // aapt resource value: 0x7F0E0018 + public const int Base_TextAppearance_AppCompat_Headline = 2131623960; + + // aapt resource value: 0x7F0E0019 + public const int Base_TextAppearance_AppCompat_Inverse = 2131623961; + + // aapt resource value: 0x7F0E001A + public const int Base_TextAppearance_AppCompat_Large = 2131623962; + + // aapt resource value: 0x7F0E001B + public const int Base_TextAppearance_AppCompat_Large_Inverse = 2131623963; + + // aapt resource value: 0x7F0E001C + public const int Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = 2131623964; + + // aapt resource value: 0x7F0E001D + public const int Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = 2131623965; + + // aapt resource value: 0x7F0E001E + public const int Base_TextAppearance_AppCompat_Medium = 2131623966; + + // aapt resource value: 0x7F0E001F + public const int Base_TextAppearance_AppCompat_Medium_Inverse = 2131623967; + + // aapt resource value: 0x7F0E0020 + public const int Base_TextAppearance_AppCompat_Menu = 2131623968; + + // aapt resource value: 0x7F0E0021 + public const int Base_TextAppearance_AppCompat_SearchResult = 2131623969; + + // aapt resource value: 0x7F0E0022 + public const int Base_TextAppearance_AppCompat_SearchResult_Subtitle = 2131623970; + + // aapt resource value: 0x7F0E0023 + public const int Base_TextAppearance_AppCompat_SearchResult_Title = 2131623971; + + // aapt resource value: 0x7F0E0024 + public const int Base_TextAppearance_AppCompat_Small = 2131623972; + + // aapt resource value: 0x7F0E0025 + public const int Base_TextAppearance_AppCompat_Small_Inverse = 2131623973; + + // aapt resource value: 0x7F0E0026 + public const int Base_TextAppearance_AppCompat_Subhead = 2131623974; + + // aapt resource value: 0x7F0E0027 + public const int Base_TextAppearance_AppCompat_Subhead_Inverse = 2131623975; + + // aapt resource value: 0x7F0E0028 + public const int Base_TextAppearance_AppCompat_Title = 2131623976; + + // aapt resource value: 0x7F0E0029 + public const int Base_TextAppearance_AppCompat_Title_Inverse = 2131623977; + + // aapt resource value: 0x7F0E002A + public const int Base_TextAppearance_AppCompat_Tooltip = 2131623978; + + // aapt resource value: 0x7F0E002B + public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Menu = 2131623979; + + // aapt resource value: 0x7F0E002C + public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle = 2131623980; + + // aapt resource value: 0x7F0E002D + public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = 2131623981; + + // aapt resource value: 0x7F0E002E + public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Title = 2131623982; + + // aapt resource value: 0x7F0E002F + public const int Base_TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = 2131623983; + + // aapt resource value: 0x7F0E0030 + public const int Base_TextAppearance_AppCompat_Widget_ActionMode_Subtitle = 2131623984; + + // aapt resource value: 0x7F0E0031 + public const int Base_TextAppearance_AppCompat_Widget_ActionMode_Title = 2131623985; + + // aapt resource value: 0x7F0E0032 + public const int Base_TextAppearance_AppCompat_Widget_Button = 2131623986; + + // aapt resource value: 0x7F0E0033 + public const int Base_TextAppearance_AppCompat_Widget_Button_Borderless_Colored = 2131623987; + + // aapt resource value: 0x7F0E0034 + public const int Base_TextAppearance_AppCompat_Widget_Button_Colored = 2131623988; + + // aapt resource value: 0x7F0E0035 + public const int Base_TextAppearance_AppCompat_Widget_Button_Inverse = 2131623989; + + // aapt resource value: 0x7F0E0036 + public const int Base_TextAppearance_AppCompat_Widget_DropDownItem = 2131623990; + + // aapt resource value: 0x7F0E0037 + public const int Base_TextAppearance_AppCompat_Widget_PopupMenu_Header = 2131623991; + + // aapt resource value: 0x7F0E0038 + public const int Base_TextAppearance_AppCompat_Widget_PopupMenu_Large = 2131623992; + + // aapt resource value: 0x7F0E0039 + public const int Base_TextAppearance_AppCompat_Widget_PopupMenu_Small = 2131623993; + + // aapt resource value: 0x7F0E003A + public const int Base_TextAppearance_AppCompat_Widget_Switch = 2131623994; + + // aapt resource value: 0x7F0E003B + public const int Base_TextAppearance_AppCompat_Widget_TextView_SpinnerItem = 2131623995; + + // aapt resource value: 0x7F0E003C + public const int Base_TextAppearance_Widget_AppCompat_ExpandedMenu_Item = 2131623996; + + // aapt resource value: 0x7F0E003D + public const int Base_TextAppearance_Widget_AppCompat_Toolbar_Subtitle = 2131623997; + + // aapt resource value: 0x7F0E003E + public const int Base_TextAppearance_Widget_AppCompat_Toolbar_Title = 2131623998; + + // aapt resource value: 0x7F0E005E + public const int Base_ThemeOverlay_AppCompat = 2131624030; + + // aapt resource value: 0x7F0E005F + public const int Base_ThemeOverlay_AppCompat_ActionBar = 2131624031; + + // aapt resource value: 0x7F0E0060 + public const int Base_ThemeOverlay_AppCompat_Dark = 2131624032; + + // aapt resource value: 0x7F0E0061 + public const int Base_ThemeOverlay_AppCompat_Dark_ActionBar = 2131624033; + + // aapt resource value: 0x7F0E0062 + public const int Base_ThemeOverlay_AppCompat_Dialog = 2131624034; + + // aapt resource value: 0x7F0E0063 + public const int Base_ThemeOverlay_AppCompat_Dialog_Alert = 2131624035; + + // aapt resource value: 0x7F0E0064 + public const int Base_ThemeOverlay_AppCompat_Light = 2131624036; + + // aapt resource value: 0x7F0E0065 + public const int Base_ThemeOverlay_MaterialComponents_Dialog = 2131624037; + + // aapt resource value: 0x7F0E0066 + public const int Base_ThemeOverlay_MaterialComponents_Dialog_Alert = 2131624038; + + // aapt resource value: 0x7F0E003F + public const int Base_Theme_AppCompat = 2131623999; + + // aapt resource value: 0x7F0E0040 + public const int Base_Theme_AppCompat_CompactMenu = 2131624000; + + // aapt resource value: 0x7F0E0041 + public const int Base_Theme_AppCompat_Dialog = 2131624001; + + // aapt resource value: 0x7F0E0045 + public const int Base_Theme_AppCompat_DialogWhenLarge = 2131624005; + + // aapt resource value: 0x7F0E0042 + public const int Base_Theme_AppCompat_Dialog_Alert = 2131624002; + + // aapt resource value: 0x7F0E0043 + public const int Base_Theme_AppCompat_Dialog_FixedSize = 2131624003; + + // aapt resource value: 0x7F0E0044 + public const int Base_Theme_AppCompat_Dialog_MinWidth = 2131624004; + + // aapt resource value: 0x7F0E0046 + public const int Base_Theme_AppCompat_Light = 2131624006; + + // aapt resource value: 0x7F0E0047 + public const int Base_Theme_AppCompat_Light_DarkActionBar = 2131624007; + + // aapt resource value: 0x7F0E0048 + public const int Base_Theme_AppCompat_Light_Dialog = 2131624008; + + // aapt resource value: 0x7F0E004C + public const int Base_Theme_AppCompat_Light_DialogWhenLarge = 2131624012; + + // aapt resource value: 0x7F0E0049 + public const int Base_Theme_AppCompat_Light_Dialog_Alert = 2131624009; + + // aapt resource value: 0x7F0E004A + public const int Base_Theme_AppCompat_Light_Dialog_FixedSize = 2131624010; + + // aapt resource value: 0x7F0E004B + public const int Base_Theme_AppCompat_Light_Dialog_MinWidth = 2131624011; + + // aapt resource value: 0x7F0E004D + public const int Base_Theme_MaterialComponents = 2131624013; + + // aapt resource value: 0x7F0E004E + public const int Base_Theme_MaterialComponents_Bridge = 2131624014; + + // aapt resource value: 0x7F0E004F + public const int Base_Theme_MaterialComponents_CompactMenu = 2131624015; + + // aapt resource value: 0x7F0E0050 + public const int Base_Theme_MaterialComponents_Dialog = 2131624016; + + // aapt resource value: 0x7F0E0054 + public const int Base_Theme_MaterialComponents_DialogWhenLarge = 2131624020; + + // aapt resource value: 0x7F0E0051 + public const int Base_Theme_MaterialComponents_Dialog_Alert = 2131624017; + + // aapt resource value: 0x7F0E0052 + public const int Base_Theme_MaterialComponents_Dialog_FixedSize = 2131624018; + + // aapt resource value: 0x7F0E0053 + public const int Base_Theme_MaterialComponents_Dialog_MinWidth = 2131624019; + + // aapt resource value: 0x7F0E0055 + public const int Base_Theme_MaterialComponents_Light = 2131624021; + + // aapt resource value: 0x7F0E0056 + public const int Base_Theme_MaterialComponents_Light_Bridge = 2131624022; + + // aapt resource value: 0x7F0E0057 + public const int Base_Theme_MaterialComponents_Light_DarkActionBar = 2131624023; + + // aapt resource value: 0x7F0E0058 + public const int Base_Theme_MaterialComponents_Light_DarkActionBar_Bridge = 2131624024; + + // aapt resource value: 0x7F0E0059 + public const int Base_Theme_MaterialComponents_Light_Dialog = 2131624025; + + // aapt resource value: 0x7F0E005D + public const int Base_Theme_MaterialComponents_Light_DialogWhenLarge = 2131624029; + + // aapt resource value: 0x7F0E005A + public const int Base_Theme_MaterialComponents_Light_Dialog_Alert = 2131624026; + + // aapt resource value: 0x7F0E005B + public const int Base_Theme_MaterialComponents_Light_Dialog_FixedSize = 2131624027; + + // aapt resource value: 0x7F0E005C + public const int Base_Theme_MaterialComponents_Light_Dialog_MinWidth = 2131624028; + + // aapt resource value: 0x7F0E006E + public const int Base_V14_ThemeOverlay_MaterialComponents_Dialog = 2131624046; + + // aapt resource value: 0x7F0E006F + public const int Base_V14_ThemeOverlay_MaterialComponents_Dialog_Alert = 2131624047; + + // aapt resource value: 0x7F0E0067 + public const int Base_V14_Theme_MaterialComponents = 2131624039; + + // aapt resource value: 0x7F0E0068 + public const int Base_V14_Theme_MaterialComponents_Bridge = 2131624040; + + // aapt resource value: 0x7F0E0069 + public const int Base_V14_Theme_MaterialComponents_Dialog = 2131624041; + + // aapt resource value: 0x7F0E006A + public const int Base_V14_Theme_MaterialComponents_Light = 2131624042; + + // aapt resource value: 0x7F0E006B + public const int Base_V14_Theme_MaterialComponents_Light_Bridge = 2131624043; + + // aapt resource value: 0x7F0E006C + public const int Base_V14_Theme_MaterialComponents_Light_DarkActionBar_Bridge = 2131624044; + + // aapt resource value: 0x7F0E006D + public const int Base_V14_Theme_MaterialComponents_Light_Dialog = 2131624045; + + // aapt resource value: 0x7F0E0074 + public const int Base_V21_ThemeOverlay_AppCompat_Dialog = 2131624052; + + // aapt resource value: 0x7F0E0070 + public const int Base_V21_Theme_AppCompat = 2131624048; + + // aapt resource value: 0x7F0E0071 + public const int Base_V21_Theme_AppCompat_Dialog = 2131624049; + + // aapt resource value: 0x7F0E0072 + public const int Base_V21_Theme_AppCompat_Light = 2131624050; + + // aapt resource value: 0x7F0E0073 + public const int Base_V21_Theme_AppCompat_Light_Dialog = 2131624051; + + // aapt resource value: 0x7F0E0075 + public const int Base_V22_Theme_AppCompat = 2131624053; + + // aapt resource value: 0x7F0E0076 + public const int Base_V22_Theme_AppCompat_Light = 2131624054; + + // aapt resource value: 0x7F0E0077 + public const int Base_V23_Theme_AppCompat = 2131624055; + + // aapt resource value: 0x7F0E0078 + public const int Base_V23_Theme_AppCompat_Light = 2131624056; + + // aapt resource value: 0x7F0E0079 + public const int Base_V26_Theme_AppCompat = 2131624057; + + // aapt resource value: 0x7F0E007A + public const int Base_V26_Theme_AppCompat_Light = 2131624058; + + // aapt resource value: 0x7F0E007B + public const int Base_V26_Widget_AppCompat_Toolbar = 2131624059; + + // aapt resource value: 0x7F0E007C + public const int Base_V28_Theme_AppCompat = 2131624060; + + // aapt resource value: 0x7F0E007D + public const int Base_V28_Theme_AppCompat_Light = 2131624061; + + // aapt resource value: 0x7F0E0082 + public const int Base_V7_ThemeOverlay_AppCompat_Dialog = 2131624066; + + // aapt resource value: 0x7F0E007E + public const int Base_V7_Theme_AppCompat = 2131624062; + + // aapt resource value: 0x7F0E007F + public const int Base_V7_Theme_AppCompat_Dialog = 2131624063; + + // aapt resource value: 0x7F0E0080 + public const int Base_V7_Theme_AppCompat_Light = 2131624064; + + // aapt resource value: 0x7F0E0081 + public const int Base_V7_Theme_AppCompat_Light_Dialog = 2131624065; + + // aapt resource value: 0x7F0E0083 + public const int Base_V7_Widget_AppCompat_AutoCompleteTextView = 2131624067; + + // aapt resource value: 0x7F0E0084 + public const int Base_V7_Widget_AppCompat_EditText = 2131624068; + + // aapt resource value: 0x7F0E0085 + public const int Base_V7_Widget_AppCompat_Toolbar = 2131624069; + + // aapt resource value: 0x7F0E0086 + public const int Base_Widget_AppCompat_ActionBar = 2131624070; + + // aapt resource value: 0x7F0E0087 + public const int Base_Widget_AppCompat_ActionBar_Solid = 2131624071; + + // aapt resource value: 0x7F0E0088 + public const int Base_Widget_AppCompat_ActionBar_TabBar = 2131624072; + + // aapt resource value: 0x7F0E0089 + public const int Base_Widget_AppCompat_ActionBar_TabText = 2131624073; + + // aapt resource value: 0x7F0E008A + public const int Base_Widget_AppCompat_ActionBar_TabView = 2131624074; + + // aapt resource value: 0x7F0E008B + public const int Base_Widget_AppCompat_ActionButton = 2131624075; + + // aapt resource value: 0x7F0E008C + public const int Base_Widget_AppCompat_ActionButton_CloseMode = 2131624076; + + // aapt resource value: 0x7F0E008D + public const int Base_Widget_AppCompat_ActionButton_Overflow = 2131624077; + + // aapt resource value: 0x7F0E008E + public const int Base_Widget_AppCompat_ActionMode = 2131624078; + + // aapt resource value: 0x7F0E008F + public const int Base_Widget_AppCompat_ActivityChooserView = 2131624079; + + // aapt resource value: 0x7F0E0090 + public const int Base_Widget_AppCompat_AutoCompleteTextView = 2131624080; + + // aapt resource value: 0x7F0E0091 + public const int Base_Widget_AppCompat_Button = 2131624081; + + // aapt resource value: 0x7F0E0097 + public const int Base_Widget_AppCompat_ButtonBar = 2131624087; + + // aapt resource value: 0x7F0E0098 + public const int Base_Widget_AppCompat_ButtonBar_AlertDialog = 2131624088; + + // aapt resource value: 0x7F0E0092 + public const int Base_Widget_AppCompat_Button_Borderless = 2131624082; + + // aapt resource value: 0x7F0E0093 + public const int Base_Widget_AppCompat_Button_Borderless_Colored = 2131624083; + + // aapt resource value: 0x7F0E0094 + public const int Base_Widget_AppCompat_Button_ButtonBar_AlertDialog = 2131624084; + + // aapt resource value: 0x7F0E0095 + public const int Base_Widget_AppCompat_Button_Colored = 2131624085; + + // aapt resource value: 0x7F0E0096 + public const int Base_Widget_AppCompat_Button_Small = 2131624086; + + // aapt resource value: 0x7F0E0099 + public const int Base_Widget_AppCompat_CompoundButton_CheckBox = 2131624089; + + // aapt resource value: 0x7F0E009A + public const int Base_Widget_AppCompat_CompoundButton_RadioButton = 2131624090; + + // aapt resource value: 0x7F0E009B + public const int Base_Widget_AppCompat_CompoundButton_Switch = 2131624091; + + // aapt resource value: 0x7F0E009C + public const int Base_Widget_AppCompat_DrawerArrowToggle = 2131624092; + + // aapt resource value: 0x7F0E009D + public const int Base_Widget_AppCompat_DrawerArrowToggle_Common = 2131624093; + + // aapt resource value: 0x7F0E009E + public const int Base_Widget_AppCompat_DropDownItem_Spinner = 2131624094; + + // aapt resource value: 0x7F0E009F + public const int Base_Widget_AppCompat_EditText = 2131624095; + + // aapt resource value: 0x7F0E00A0 + public const int Base_Widget_AppCompat_ImageButton = 2131624096; + + // aapt resource value: 0x7F0E00A1 + public const int Base_Widget_AppCompat_Light_ActionBar = 2131624097; + + // aapt resource value: 0x7F0E00A2 + public const int Base_Widget_AppCompat_Light_ActionBar_Solid = 2131624098; + + // aapt resource value: 0x7F0E00A3 + public const int Base_Widget_AppCompat_Light_ActionBar_TabBar = 2131624099; + + // aapt resource value: 0x7F0E00A4 + public const int Base_Widget_AppCompat_Light_ActionBar_TabText = 2131624100; + + // aapt resource value: 0x7F0E00A5 + public const int Base_Widget_AppCompat_Light_ActionBar_TabText_Inverse = 2131624101; + + // aapt resource value: 0x7F0E00A6 + public const int Base_Widget_AppCompat_Light_ActionBar_TabView = 2131624102; + + // aapt resource value: 0x7F0E00A7 + public const int Base_Widget_AppCompat_Light_PopupMenu = 2131624103; + + // aapt resource value: 0x7F0E00A8 + public const int Base_Widget_AppCompat_Light_PopupMenu_Overflow = 2131624104; + + // aapt resource value: 0x7F0E00A9 + public const int Base_Widget_AppCompat_ListMenuView = 2131624105; + + // aapt resource value: 0x7F0E00AA + public const int Base_Widget_AppCompat_ListPopupWindow = 2131624106; + + // aapt resource value: 0x7F0E00AB + public const int Base_Widget_AppCompat_ListView = 2131624107; + + // aapt resource value: 0x7F0E00AC + public const int Base_Widget_AppCompat_ListView_DropDown = 2131624108; + + // aapt resource value: 0x7F0E00AD + public const int Base_Widget_AppCompat_ListView_Menu = 2131624109; + + // aapt resource value: 0x7F0E00AE + public const int Base_Widget_AppCompat_PopupMenu = 2131624110; + + // aapt resource value: 0x7F0E00AF + public const int Base_Widget_AppCompat_PopupMenu_Overflow = 2131624111; + + // aapt resource value: 0x7F0E00B0 + public const int Base_Widget_AppCompat_PopupWindow = 2131624112; + + // aapt resource value: 0x7F0E00B1 + public const int Base_Widget_AppCompat_ProgressBar = 2131624113; + + // aapt resource value: 0x7F0E00B2 + public const int Base_Widget_AppCompat_ProgressBar_Horizontal = 2131624114; + + // aapt resource value: 0x7F0E00B3 + public const int Base_Widget_AppCompat_RatingBar = 2131624115; + + // aapt resource value: 0x7F0E00B4 + public const int Base_Widget_AppCompat_RatingBar_Indicator = 2131624116; + + // aapt resource value: 0x7F0E00B5 + public const int Base_Widget_AppCompat_RatingBar_Small = 2131624117; + + // aapt resource value: 0x7F0E00B6 + public const int Base_Widget_AppCompat_SearchView = 2131624118; + + // aapt resource value: 0x7F0E00B7 + public const int Base_Widget_AppCompat_SearchView_ActionBar = 2131624119; + + // aapt resource value: 0x7F0E00B8 + public const int Base_Widget_AppCompat_SeekBar = 2131624120; + + // aapt resource value: 0x7F0E00B9 + public const int Base_Widget_AppCompat_SeekBar_Discrete = 2131624121; + + // aapt resource value: 0x7F0E00BA + public const int Base_Widget_AppCompat_Spinner = 2131624122; + + // aapt resource value: 0x7F0E00BB + public const int Base_Widget_AppCompat_Spinner_Underlined = 2131624123; + + // aapt resource value: 0x7F0E00BC + public const int Base_Widget_AppCompat_TextView_SpinnerItem = 2131624124; + + // aapt resource value: 0x7F0E00BD + public const int Base_Widget_AppCompat_Toolbar = 2131624125; + + // aapt resource value: 0x7F0E00BE + public const int Base_Widget_AppCompat_Toolbar_Button_Navigation = 2131624126; + + // aapt resource value: 0x7F0E00BF + public const int Base_Widget_Design_TabLayout = 2131624127; + + // aapt resource value: 0x7F0E00C0 + public const int Base_Widget_MaterialComponents_Chip = 2131624128; + + // aapt resource value: 0x7F0E00C1 + public const int Base_Widget_MaterialComponents_TextInputEditText = 2131624129; + + // aapt resource value: 0x7F0E00C2 + public const int Base_Widget_MaterialComponents_TextInputLayout = 2131624130; + + // aapt resource value: 0x7F0E00C3 + public const int CardView = 2131624131; + + // aapt resource value: 0x7F0E00C4 + public const int CardView_Dark = 2131624132; + + // aapt resource value: 0x7F0E00C5 + public const int CardView_Light = 2131624133; + + // aapt resource value: 0x7F0E01F7 + public const int collectionViewStyle = 2131624439; + + // aapt resource value: 0x7F0E00C6 + public const int MainTheme = 2131624134; + + // aapt resource value: 0x7F0E00C7 + public const int MainTheme_Base = 2131624135; + + // aapt resource value: 0x7F0E00C8 + public const int Platform_AppCompat = 2131624136; + + // aapt resource value: 0x7F0E00C9 + public const int Platform_AppCompat_Light = 2131624137; + + // aapt resource value: 0x7F0E00CA + public const int Platform_MaterialComponents = 2131624138; + + // aapt resource value: 0x7F0E00CB + public const int Platform_MaterialComponents_Dialog = 2131624139; + + // aapt resource value: 0x7F0E00CC + public const int Platform_MaterialComponents_Light = 2131624140; + + // aapt resource value: 0x7F0E00CD + public const int Platform_MaterialComponents_Light_Dialog = 2131624141; + + // aapt resource value: 0x7F0E00CE + public const int Platform_ThemeOverlay_AppCompat = 2131624142; + + // aapt resource value: 0x7F0E00CF + public const int Platform_ThemeOverlay_AppCompat_Dark = 2131624143; + + // aapt resource value: 0x7F0E00D0 + public const int Platform_ThemeOverlay_AppCompat_Light = 2131624144; + + // aapt resource value: 0x7F0E00D1 + public const int Platform_V21_AppCompat = 2131624145; + + // aapt resource value: 0x7F0E00D2 + public const int Platform_V21_AppCompat_Light = 2131624146; + + // aapt resource value: 0x7F0E00D3 + public const int Platform_V25_AppCompat = 2131624147; + + // aapt resource value: 0x7F0E00D4 + public const int Platform_V25_AppCompat_Light = 2131624148; + + // aapt resource value: 0x7F0E00D5 + public const int Platform_Widget_AppCompat_Spinner = 2131624149; + + // aapt resource value: 0x7F0E00D6 + public const int RtlOverlay_DialogWindowTitle_AppCompat = 2131624150; + + // aapt resource value: 0x7F0E00D7 + public const int RtlOverlay_Widget_AppCompat_ActionBar_TitleItem = 2131624151; + + // aapt resource value: 0x7F0E00D8 + public const int RtlOverlay_Widget_AppCompat_DialogTitle_Icon = 2131624152; + + // aapt resource value: 0x7F0E00D9 + public const int RtlOverlay_Widget_AppCompat_PopupMenuItem = 2131624153; + + // aapt resource value: 0x7F0E00DA + public const int RtlOverlay_Widget_AppCompat_PopupMenuItem_InternalGroup = 2131624154; + + // aapt resource value: 0x7F0E00DB + public const int RtlOverlay_Widget_AppCompat_PopupMenuItem_Shortcut = 2131624155; + + // aapt resource value: 0x7F0E00DC + public const int RtlOverlay_Widget_AppCompat_PopupMenuItem_SubmenuArrow = 2131624156; + + // aapt resource value: 0x7F0E00DD + public const int RtlOverlay_Widget_AppCompat_PopupMenuItem_Text = 2131624157; + + // aapt resource value: 0x7F0E00DE + public const int RtlOverlay_Widget_AppCompat_PopupMenuItem_Title = 2131624158; + + // aapt resource value: 0x7F0E00E4 + public const int RtlOverlay_Widget_AppCompat_SearchView_MagIcon = 2131624164; + + // aapt resource value: 0x7F0E00DF + public const int RtlOverlay_Widget_AppCompat_Search_DropDown = 2131624159; + + // aapt resource value: 0x7F0E00E0 + public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Icon1 = 2131624160; + + // aapt resource value: 0x7F0E00E1 + public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Icon2 = 2131624161; + + // aapt resource value: 0x7F0E00E2 + public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Query = 2131624162; + + // aapt resource value: 0x7F0E00E3 + public const int RtlOverlay_Widget_AppCompat_Search_DropDown_Text = 2131624163; + + // aapt resource value: 0x7F0E00E5 + public const int RtlUnderlay_Widget_AppCompat_ActionButton = 2131624165; + + // aapt resource value: 0x7F0E00E6 + public const int RtlUnderlay_Widget_AppCompat_ActionButton_Overflow = 2131624166; + + // aapt resource value: 0x7F0E00E7 + public const int TextAppearance_AppCompat = 2131624167; + + // aapt resource value: 0x7F0E00E8 + public const int TextAppearance_AppCompat_Body1 = 2131624168; + + // aapt resource value: 0x7F0E00E9 + public const int TextAppearance_AppCompat_Body2 = 2131624169; + + // aapt resource value: 0x7F0E00EA + public const int TextAppearance_AppCompat_Button = 2131624170; + + // aapt resource value: 0x7F0E00EB + public const int TextAppearance_AppCompat_Caption = 2131624171; + + // aapt resource value: 0x7F0E00EC + public const int TextAppearance_AppCompat_Display1 = 2131624172; + + // aapt resource value: 0x7F0E00ED + public const int TextAppearance_AppCompat_Display2 = 2131624173; + + // aapt resource value: 0x7F0E00EE + public const int TextAppearance_AppCompat_Display3 = 2131624174; + + // aapt resource value: 0x7F0E00EF + public const int TextAppearance_AppCompat_Display4 = 2131624175; + + // aapt resource value: 0x7F0E00F0 + public const int TextAppearance_AppCompat_Headline = 2131624176; + + // aapt resource value: 0x7F0E00F1 + public const int TextAppearance_AppCompat_Inverse = 2131624177; + + // aapt resource value: 0x7F0E00F2 + public const int TextAppearance_AppCompat_Large = 2131624178; + + // aapt resource value: 0x7F0E00F3 + public const int TextAppearance_AppCompat_Large_Inverse = 2131624179; + + // aapt resource value: 0x7F0E00F4 + public const int TextAppearance_AppCompat_Light_SearchResult_Subtitle = 2131624180; + + // aapt resource value: 0x7F0E00F5 + public const int TextAppearance_AppCompat_Light_SearchResult_Title = 2131624181; + + // aapt resource value: 0x7F0E00F6 + public const int TextAppearance_AppCompat_Light_Widget_PopupMenu_Large = 2131624182; + + // aapt resource value: 0x7F0E00F7 + public const int TextAppearance_AppCompat_Light_Widget_PopupMenu_Small = 2131624183; + + // aapt resource value: 0x7F0E00F8 + public const int TextAppearance_AppCompat_Medium = 2131624184; + + // aapt resource value: 0x7F0E00F9 + public const int TextAppearance_AppCompat_Medium_Inverse = 2131624185; + + // aapt resource value: 0x7F0E00FA + public const int TextAppearance_AppCompat_Menu = 2131624186; + + // aapt resource value: 0x7F0E00FB + public const int TextAppearance_AppCompat_SearchResult_Subtitle = 2131624187; + + // aapt resource value: 0x7F0E00FC + public const int TextAppearance_AppCompat_SearchResult_Title = 2131624188; + + // aapt resource value: 0x7F0E00FD + public const int TextAppearance_AppCompat_Small = 2131624189; + + // aapt resource value: 0x7F0E00FE + public const int TextAppearance_AppCompat_Small_Inverse = 2131624190; + + // aapt resource value: 0x7F0E00FF + public const int TextAppearance_AppCompat_Subhead = 2131624191; + + // aapt resource value: 0x7F0E0100 + public const int TextAppearance_AppCompat_Subhead_Inverse = 2131624192; + + // aapt resource value: 0x7F0E0101 + public const int TextAppearance_AppCompat_Title = 2131624193; + + // aapt resource value: 0x7F0E0102 + public const int TextAppearance_AppCompat_Title_Inverse = 2131624194; + + // aapt resource value: 0x7F0E0103 + public const int TextAppearance_AppCompat_Tooltip = 2131624195; + + // aapt resource value: 0x7F0E0104 + public const int TextAppearance_AppCompat_Widget_ActionBar_Menu = 2131624196; + + // aapt resource value: 0x7F0E0105 + public const int TextAppearance_AppCompat_Widget_ActionBar_Subtitle = 2131624197; + + // aapt resource value: 0x7F0E0106 + public const int TextAppearance_AppCompat_Widget_ActionBar_Subtitle_Inverse = 2131624198; + + // aapt resource value: 0x7F0E0107 + public const int TextAppearance_AppCompat_Widget_ActionBar_Title = 2131624199; + + // aapt resource value: 0x7F0E0108 + public const int TextAppearance_AppCompat_Widget_ActionBar_Title_Inverse = 2131624200; + + // aapt resource value: 0x7F0E0109 + public const int TextAppearance_AppCompat_Widget_ActionMode_Subtitle = 2131624201; + + // aapt resource value: 0x7F0E010A + public const int TextAppearance_AppCompat_Widget_ActionMode_Subtitle_Inverse = 2131624202; + + // aapt resource value: 0x7F0E010B + public const int TextAppearance_AppCompat_Widget_ActionMode_Title = 2131624203; + + // aapt resource value: 0x7F0E010C + public const int TextAppearance_AppCompat_Widget_ActionMode_Title_Inverse = 2131624204; + + // aapt resource value: 0x7F0E010D + public const int TextAppearance_AppCompat_Widget_Button = 2131624205; + + // aapt resource value: 0x7F0E010E + public const int TextAppearance_AppCompat_Widget_Button_Borderless_Colored = 2131624206; + + // aapt resource value: 0x7F0E010F + public const int TextAppearance_AppCompat_Widget_Button_Colored = 2131624207; + + // aapt resource value: 0x7F0E0110 + public const int TextAppearance_AppCompat_Widget_Button_Inverse = 2131624208; + + // aapt resource value: 0x7F0E0111 + public const int TextAppearance_AppCompat_Widget_DropDownItem = 2131624209; + + // aapt resource value: 0x7F0E0112 + public const int TextAppearance_AppCompat_Widget_PopupMenu_Header = 2131624210; + + // aapt resource value: 0x7F0E0113 + public const int TextAppearance_AppCompat_Widget_PopupMenu_Large = 2131624211; + + // aapt resource value: 0x7F0E0114 + public const int TextAppearance_AppCompat_Widget_PopupMenu_Small = 2131624212; + + // aapt resource value: 0x7F0E0115 + public const int TextAppearance_AppCompat_Widget_Switch = 2131624213; + + // aapt resource value: 0x7F0E0116 + public const int TextAppearance_AppCompat_Widget_TextView_SpinnerItem = 2131624214; + + // aapt resource value: 0x7F0E0117 + public const int TextAppearance_Compat_Notification = 2131624215; + + // aapt resource value: 0x7F0E0118 + public const int TextAppearance_Compat_Notification_Info = 2131624216; + + // aapt resource value: 0x7F0E0119 + public const int TextAppearance_Compat_Notification_Info_Media = 2131624217; + + // aapt resource value: 0x7F0E011A + public const int TextAppearance_Compat_Notification_Line2 = 2131624218; + + // aapt resource value: 0x7F0E011B + public const int TextAppearance_Compat_Notification_Line2_Media = 2131624219; + + // aapt resource value: 0x7F0E011C + public const int TextAppearance_Compat_Notification_Media = 2131624220; + + // aapt resource value: 0x7F0E011D + public const int TextAppearance_Compat_Notification_Time = 2131624221; + + // aapt resource value: 0x7F0E011E + public const int TextAppearance_Compat_Notification_Time_Media = 2131624222; + + // aapt resource value: 0x7F0E011F + public const int TextAppearance_Compat_Notification_Title = 2131624223; + + // aapt resource value: 0x7F0E0120 + public const int TextAppearance_Compat_Notification_Title_Media = 2131624224; + + // aapt resource value: 0x7F0E0121 + public const int TextAppearance_Design_CollapsingToolbar_Expanded = 2131624225; + + // aapt resource value: 0x7F0E0122 + public const int TextAppearance_Design_Counter = 2131624226; + + // aapt resource value: 0x7F0E0123 + public const int TextAppearance_Design_Counter_Overflow = 2131624227; + + // aapt resource value: 0x7F0E0124 + public const int TextAppearance_Design_Error = 2131624228; + + // aapt resource value: 0x7F0E0125 + public const int TextAppearance_Design_HelperText = 2131624229; + + // aapt resource value: 0x7F0E0126 + public const int TextAppearance_Design_Hint = 2131624230; + + // aapt resource value: 0x7F0E0127 + public const int TextAppearance_Design_Snackbar_Message = 2131624231; + + // aapt resource value: 0x7F0E0128 + public const int TextAppearance_Design_Tab = 2131624232; + + // aapt resource value: 0x7F0E0129 + public const int TextAppearance_MaterialComponents_Body1 = 2131624233; + + // aapt resource value: 0x7F0E012A + public const int TextAppearance_MaterialComponents_Body2 = 2131624234; + + // aapt resource value: 0x7F0E012B + public const int TextAppearance_MaterialComponents_Button = 2131624235; + + // aapt resource value: 0x7F0E012C + public const int TextAppearance_MaterialComponents_Caption = 2131624236; + + // aapt resource value: 0x7F0E012D + public const int TextAppearance_MaterialComponents_Chip = 2131624237; + + // aapt resource value: 0x7F0E012E + public const int TextAppearance_MaterialComponents_Headline1 = 2131624238; + + // aapt resource value: 0x7F0E012F + public const int TextAppearance_MaterialComponents_Headline2 = 2131624239; + + // aapt resource value: 0x7F0E0130 + public const int TextAppearance_MaterialComponents_Headline3 = 2131624240; + + // aapt resource value: 0x7F0E0131 + public const int TextAppearance_MaterialComponents_Headline4 = 2131624241; + + // aapt resource value: 0x7F0E0132 + public const int TextAppearance_MaterialComponents_Headline5 = 2131624242; + + // aapt resource value: 0x7F0E0133 + public const int TextAppearance_MaterialComponents_Headline6 = 2131624243; + + // aapt resource value: 0x7F0E0134 + public const int TextAppearance_MaterialComponents_Overline = 2131624244; + + // aapt resource value: 0x7F0E0135 + public const int TextAppearance_MaterialComponents_Subtitle1 = 2131624245; + + // aapt resource value: 0x7F0E0136 + public const int TextAppearance_MaterialComponents_Subtitle2 = 2131624246; + + // aapt resource value: 0x7F0E0137 + public const int TextAppearance_MaterialComponents_Tab = 2131624247; + + // aapt resource value: 0x7F0E0138 + public const int TextAppearance_Widget_AppCompat_ExpandedMenu_Item = 2131624248; + + // aapt resource value: 0x7F0E0139 + public const int TextAppearance_Widget_AppCompat_Toolbar_Subtitle = 2131624249; + + // aapt resource value: 0x7F0E013A + public const int TextAppearance_Widget_AppCompat_Toolbar_Title = 2131624250; + + // aapt resource value: 0x7F0E016B + public const int ThemeOverlay_AppCompat = 2131624299; + + // aapt resource value: 0x7F0E016C + public const int ThemeOverlay_AppCompat_ActionBar = 2131624300; + + // aapt resource value: 0x7F0E016D + public const int ThemeOverlay_AppCompat_Dark = 2131624301; + + // aapt resource value: 0x7F0E016E + public const int ThemeOverlay_AppCompat_Dark_ActionBar = 2131624302; + + // aapt resource value: 0x7F0E016F + public const int ThemeOverlay_AppCompat_Dialog = 2131624303; + + // aapt resource value: 0x7F0E0170 + public const int ThemeOverlay_AppCompat_Dialog_Alert = 2131624304; + + // aapt resource value: 0x7F0E0171 + public const int ThemeOverlay_AppCompat_Light = 2131624305; + + // aapt resource value: 0x7F0E0172 + public const int ThemeOverlay_MaterialComponents = 2131624306; + + // aapt resource value: 0x7F0E0173 + public const int ThemeOverlay_MaterialComponents_ActionBar = 2131624307; + + // aapt resource value: 0x7F0E0174 + public const int ThemeOverlay_MaterialComponents_Dark = 2131624308; + + // aapt resource value: 0x7F0E0175 + public const int ThemeOverlay_MaterialComponents_Dark_ActionBar = 2131624309; + + // aapt resource value: 0x7F0E0176 + public const int ThemeOverlay_MaterialComponents_Dialog = 2131624310; + + // aapt resource value: 0x7F0E0177 + public const int ThemeOverlay_MaterialComponents_Dialog_Alert = 2131624311; + + // aapt resource value: 0x7F0E0178 + public const int ThemeOverlay_MaterialComponents_Light = 2131624312; + + // aapt resource value: 0x7F0E0179 + public const int ThemeOverlay_MaterialComponents_TextInputEditText = 2131624313; + + // aapt resource value: 0x7F0E017A + public const int ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox = 2131624314; + + // aapt resource value: 0x7F0E017B + public const int ThemeOverlay_MaterialComponents_TextInputEditText_FilledBox_Dense = 2131624315; + + // aapt resource value: 0x7F0E017C + public const int ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox = 2131624316; + + // aapt resource value: 0x7F0E017D + public const int ThemeOverlay_MaterialComponents_TextInputEditText_OutlinedBox_Dense = 2131624317; + + // aapt resource value: 0x7F0E013B + public const int Theme_AppCompat = 2131624251; + + // aapt resource value: 0x7F0E013C + public const int Theme_AppCompat_CompactMenu = 2131624252; + + // aapt resource value: 0x7F0E013D + public const int Theme_AppCompat_DayNight = 2131624253; + + // aapt resource value: 0x7F0E013E + public const int Theme_AppCompat_DayNight_DarkActionBar = 2131624254; + + // aapt resource value: 0x7F0E013F + public const int Theme_AppCompat_DayNight_Dialog = 2131624255; + + // aapt resource value: 0x7F0E0142 + public const int Theme_AppCompat_DayNight_DialogWhenLarge = 2131624258; + + // aapt resource value: 0x7F0E0140 + public const int Theme_AppCompat_DayNight_Dialog_Alert = 2131624256; + + // aapt resource value: 0x7F0E0141 + public const int Theme_AppCompat_DayNight_Dialog_MinWidth = 2131624257; + + // aapt resource value: 0x7F0E0143 + public const int Theme_AppCompat_DayNight_NoActionBar = 2131624259; + + // aapt resource value: 0x7F0E0144 + public const int Theme_AppCompat_Dialog = 2131624260; + + // aapt resource value: 0x7F0E0147 + public const int Theme_AppCompat_DialogWhenLarge = 2131624263; + + // aapt resource value: 0x7F0E0145 + public const int Theme_AppCompat_Dialog_Alert = 2131624261; + + // aapt resource value: 0x7F0E0146 + public const int Theme_AppCompat_Dialog_MinWidth = 2131624262; + + // aapt resource value: 0x7F0E0148 + public const int Theme_AppCompat_Light = 2131624264; + + // aapt resource value: 0x7F0E0149 + public const int Theme_AppCompat_Light_DarkActionBar = 2131624265; + + // aapt resource value: 0x7F0E014A + public const int Theme_AppCompat_Light_Dialog = 2131624266; + + // aapt resource value: 0x7F0E014D + public const int Theme_AppCompat_Light_DialogWhenLarge = 2131624269; + + // aapt resource value: 0x7F0E014B + public const int Theme_AppCompat_Light_Dialog_Alert = 2131624267; + + // aapt resource value: 0x7F0E014C + public const int Theme_AppCompat_Light_Dialog_MinWidth = 2131624268; + + // aapt resource value: 0x7F0E014E + public const int Theme_AppCompat_Light_NoActionBar = 2131624270; + + // aapt resource value: 0x7F0E014F + public const int Theme_AppCompat_NoActionBar = 2131624271; + + // aapt resource value: 0x7F0E0150 + public const int Theme_Design = 2131624272; + + // aapt resource value: 0x7F0E0151 + public const int Theme_Design_BottomSheetDialog = 2131624273; + + // aapt resource value: 0x7F0E0152 + public const int Theme_Design_Light = 2131624274; + + // aapt resource value: 0x7F0E0153 + public const int Theme_Design_Light_BottomSheetDialog = 2131624275; + + // aapt resource value: 0x7F0E0154 + public const int Theme_Design_Light_NoActionBar = 2131624276; + + // aapt resource value: 0x7F0E0155 + public const int Theme_Design_NoActionBar = 2131624277; + + // aapt resource value: 0x7F0E0156 + public const int Theme_MaterialComponents = 2131624278; + + // aapt resource value: 0x7F0E0157 + public const int Theme_MaterialComponents_BottomSheetDialog = 2131624279; + + // aapt resource value: 0x7F0E0158 + public const int Theme_MaterialComponents_Bridge = 2131624280; + + // aapt resource value: 0x7F0E0159 + public const int Theme_MaterialComponents_CompactMenu = 2131624281; + + // aapt resource value: 0x7F0E015A + public const int Theme_MaterialComponents_Dialog = 2131624282; + + // aapt resource value: 0x7F0E015D + public const int Theme_MaterialComponents_DialogWhenLarge = 2131624285; + + // aapt resource value: 0x7F0E015B + public const int Theme_MaterialComponents_Dialog_Alert = 2131624283; + + // aapt resource value: 0x7F0E015C + public const int Theme_MaterialComponents_Dialog_MinWidth = 2131624284; + + // aapt resource value: 0x7F0E015E + public const int Theme_MaterialComponents_Light = 2131624286; + + // aapt resource value: 0x7F0E015F + public const int Theme_MaterialComponents_Light_BottomSheetDialog = 2131624287; + + // aapt resource value: 0x7F0E0160 + public const int Theme_MaterialComponents_Light_Bridge = 2131624288; + + // aapt resource value: 0x7F0E0161 + public const int Theme_MaterialComponents_Light_DarkActionBar = 2131624289; + + // aapt resource value: 0x7F0E0162 + public const int Theme_MaterialComponents_Light_DarkActionBar_Bridge = 2131624290; + + // aapt resource value: 0x7F0E0163 + public const int Theme_MaterialComponents_Light_Dialog = 2131624291; + + // aapt resource value: 0x7F0E0166 + public const int Theme_MaterialComponents_Light_DialogWhenLarge = 2131624294; + + // aapt resource value: 0x7F0E0164 + public const int Theme_MaterialComponents_Light_Dialog_Alert = 2131624292; + + // aapt resource value: 0x7F0E0165 + public const int Theme_MaterialComponents_Light_Dialog_MinWidth = 2131624293; + + // aapt resource value: 0x7F0E0167 + public const int Theme_MaterialComponents_Light_NoActionBar = 2131624295; + + // aapt resource value: 0x7F0E0168 + public const int Theme_MaterialComponents_Light_NoActionBar_Bridge = 2131624296; + + // aapt resource value: 0x7F0E0169 + public const int Theme_MaterialComponents_NoActionBar = 2131624297; + + // aapt resource value: 0x7F0E016A + public const int Theme_MaterialComponents_NoActionBar_Bridge = 2131624298; + + // aapt resource value: 0x7F0E017E + public const int Widget_AppCompat_ActionBar = 2131624318; + + // aapt resource value: 0x7F0E017F + public const int Widget_AppCompat_ActionBar_Solid = 2131624319; + + // aapt resource value: 0x7F0E0180 + public const int Widget_AppCompat_ActionBar_TabBar = 2131624320; + + // aapt resource value: 0x7F0E0181 + public const int Widget_AppCompat_ActionBar_TabText = 2131624321; + + // aapt resource value: 0x7F0E0182 + public const int Widget_AppCompat_ActionBar_TabView = 2131624322; + + // aapt resource value: 0x7F0E0183 + public const int Widget_AppCompat_ActionButton = 2131624323; + + // aapt resource value: 0x7F0E0184 + public const int Widget_AppCompat_ActionButton_CloseMode = 2131624324; + + // aapt resource value: 0x7F0E0185 + public const int Widget_AppCompat_ActionButton_Overflow = 2131624325; + + // aapt resource value: 0x7F0E0186 + public const int Widget_AppCompat_ActionMode = 2131624326; + + // aapt resource value: 0x7F0E0187 + public const int Widget_AppCompat_ActivityChooserView = 2131624327; + + // aapt resource value: 0x7F0E0188 + public const int Widget_AppCompat_AutoCompleteTextView = 2131624328; + + // aapt resource value: 0x7F0E0189 + public const int Widget_AppCompat_Button = 2131624329; + + // aapt resource value: 0x7F0E018F + public const int Widget_AppCompat_ButtonBar = 2131624335; + + // aapt resource value: 0x7F0E0190 + public const int Widget_AppCompat_ButtonBar_AlertDialog = 2131624336; + + // aapt resource value: 0x7F0E018A + public const int Widget_AppCompat_Button_Borderless = 2131624330; + + // aapt resource value: 0x7F0E018B + public const int Widget_AppCompat_Button_Borderless_Colored = 2131624331; + + // aapt resource value: 0x7F0E018C + public const int Widget_AppCompat_Button_ButtonBar_AlertDialog = 2131624332; + + // aapt resource value: 0x7F0E018D + public const int Widget_AppCompat_Button_Colored = 2131624333; + + // aapt resource value: 0x7F0E018E + public const int Widget_AppCompat_Button_Small = 2131624334; + + // aapt resource value: 0x7F0E0191 + public const int Widget_AppCompat_CompoundButton_CheckBox = 2131624337; + + // aapt resource value: 0x7F0E0192 + public const int Widget_AppCompat_CompoundButton_RadioButton = 2131624338; + + // aapt resource value: 0x7F0E0193 + public const int Widget_AppCompat_CompoundButton_Switch = 2131624339; + + // aapt resource value: 0x7F0E0194 + public const int Widget_AppCompat_DrawerArrowToggle = 2131624340; + + // aapt resource value: 0x7F0E0195 + public const int Widget_AppCompat_DropDownItem_Spinner = 2131624341; + + // aapt resource value: 0x7F0E0196 + public const int Widget_AppCompat_EditText = 2131624342; + + // aapt resource value: 0x7F0E0197 + public const int Widget_AppCompat_ImageButton = 2131624343; + + // aapt resource value: 0x7F0E0198 + public const int Widget_AppCompat_Light_ActionBar = 2131624344; + + // aapt resource value: 0x7F0E0199 + public const int Widget_AppCompat_Light_ActionBar_Solid = 2131624345; + + // aapt resource value: 0x7F0E019A + public const int Widget_AppCompat_Light_ActionBar_Solid_Inverse = 2131624346; + + // aapt resource value: 0x7F0E019B + public const int Widget_AppCompat_Light_ActionBar_TabBar = 2131624347; + + // aapt resource value: 0x7F0E019C + public const int Widget_AppCompat_Light_ActionBar_TabBar_Inverse = 2131624348; + + // aapt resource value: 0x7F0E019D + public const int Widget_AppCompat_Light_ActionBar_TabText = 2131624349; + + // aapt resource value: 0x7F0E019E + public const int Widget_AppCompat_Light_ActionBar_TabText_Inverse = 2131624350; + + // aapt resource value: 0x7F0E019F + public const int Widget_AppCompat_Light_ActionBar_TabView = 2131624351; + + // aapt resource value: 0x7F0E01A0 + public const int Widget_AppCompat_Light_ActionBar_TabView_Inverse = 2131624352; + + // aapt resource value: 0x7F0E01A1 + public const int Widget_AppCompat_Light_ActionButton = 2131624353; + + // aapt resource value: 0x7F0E01A2 + public const int Widget_AppCompat_Light_ActionButton_CloseMode = 2131624354; + + // aapt resource value: 0x7F0E01A3 + public const int Widget_AppCompat_Light_ActionButton_Overflow = 2131624355; + + // aapt resource value: 0x7F0E01A4 + public const int Widget_AppCompat_Light_ActionMode_Inverse = 2131624356; + + // aapt resource value: 0x7F0E01A5 + public const int Widget_AppCompat_Light_ActivityChooserView = 2131624357; + + // aapt resource value: 0x7F0E01A6 + public const int Widget_AppCompat_Light_AutoCompleteTextView = 2131624358; + + // aapt resource value: 0x7F0E01A7 + public const int Widget_AppCompat_Light_DropDownItem_Spinner = 2131624359; + + // aapt resource value: 0x7F0E01A8 + public const int Widget_AppCompat_Light_ListPopupWindow = 2131624360; + + // aapt resource value: 0x7F0E01A9 + public const int Widget_AppCompat_Light_ListView_DropDown = 2131624361; + + // aapt resource value: 0x7F0E01AA + public const int Widget_AppCompat_Light_PopupMenu = 2131624362; + + // aapt resource value: 0x7F0E01AB + public const int Widget_AppCompat_Light_PopupMenu_Overflow = 2131624363; + + // aapt resource value: 0x7F0E01AC + public const int Widget_AppCompat_Light_SearchView = 2131624364; + + // aapt resource value: 0x7F0E01AD + public const int Widget_AppCompat_Light_Spinner_DropDown_ActionBar = 2131624365; + + // aapt resource value: 0x7F0E01AE + public const int Widget_AppCompat_ListMenuView = 2131624366; + + // aapt resource value: 0x7F0E01AF + public const int Widget_AppCompat_ListPopupWindow = 2131624367; + + // aapt resource value: 0x7F0E01B0 + public const int Widget_AppCompat_ListView = 2131624368; + + // aapt resource value: 0x7F0E01B1 + public const int Widget_AppCompat_ListView_DropDown = 2131624369; + + // aapt resource value: 0x7F0E01B2 + public const int Widget_AppCompat_ListView_Menu = 2131624370; + + // aapt resource value: 0x7F0E01B3 + public const int Widget_AppCompat_PopupMenu = 2131624371; + + // aapt resource value: 0x7F0E01B4 + public const int Widget_AppCompat_PopupMenu_Overflow = 2131624372; + + // aapt resource value: 0x7F0E01B5 + public const int Widget_AppCompat_PopupWindow = 2131624373; + + // aapt resource value: 0x7F0E01B6 + public const int Widget_AppCompat_ProgressBar = 2131624374; + + // aapt resource value: 0x7F0E01B7 + public const int Widget_AppCompat_ProgressBar_Horizontal = 2131624375; + + // aapt resource value: 0x7F0E01B8 + public const int Widget_AppCompat_RatingBar = 2131624376; + + // aapt resource value: 0x7F0E01B9 + public const int Widget_AppCompat_RatingBar_Indicator = 2131624377; + + // aapt resource value: 0x7F0E01BA + public const int Widget_AppCompat_RatingBar_Small = 2131624378; + + // aapt resource value: 0x7F0E01BB + public const int Widget_AppCompat_SearchView = 2131624379; + + // aapt resource value: 0x7F0E01BC + public const int Widget_AppCompat_SearchView_ActionBar = 2131624380; + + // aapt resource value: 0x7F0E01BD + public const int Widget_AppCompat_SeekBar = 2131624381; + + // aapt resource value: 0x7F0E01BE + public const int Widget_AppCompat_SeekBar_Discrete = 2131624382; + + // aapt resource value: 0x7F0E01BF + public const int Widget_AppCompat_Spinner = 2131624383; + + // aapt resource value: 0x7F0E01C0 + public const int Widget_AppCompat_Spinner_DropDown = 2131624384; + + // aapt resource value: 0x7F0E01C1 + public const int Widget_AppCompat_Spinner_DropDown_ActionBar = 2131624385; + + // aapt resource value: 0x7F0E01C2 + public const int Widget_AppCompat_Spinner_Underlined = 2131624386; + + // aapt resource value: 0x7F0E01C3 + public const int Widget_AppCompat_TextView_SpinnerItem = 2131624387; + + // aapt resource value: 0x7F0E01C4 + public const int Widget_AppCompat_Toolbar = 2131624388; + + // aapt resource value: 0x7F0E01C5 + public const int Widget_AppCompat_Toolbar_Button_Navigation = 2131624389; + + // aapt resource value: 0x7F0E01C6 + public const int Widget_Compat_NotificationActionContainer = 2131624390; + + // aapt resource value: 0x7F0E01C7 + public const int Widget_Compat_NotificationActionText = 2131624391; + + // aapt resource value: 0x7F0E01C8 + public const int Widget_Design_AppBarLayout = 2131624392; + + // aapt resource value: 0x7F0E01C9 + public const int Widget_Design_BottomNavigationView = 2131624393; + + // aapt resource value: 0x7F0E01CA + public const int Widget_Design_BottomSheet_Modal = 2131624394; + + // aapt resource value: 0x7F0E01CB + public const int Widget_Design_CollapsingToolbar = 2131624395; + + // aapt resource value: 0x7F0E01CC + public const int Widget_Design_FloatingActionButton = 2131624396; + + // aapt resource value: 0x7F0E01CD + public const int Widget_Design_NavigationView = 2131624397; + + // aapt resource value: 0x7F0E01CE + public const int Widget_Design_ScrimInsetsFrameLayout = 2131624398; + + // aapt resource value: 0x7F0E01CF + public const int Widget_Design_Snackbar = 2131624399; + + // aapt resource value: 0x7F0E01D0 + public const int Widget_Design_TabLayout = 2131624400; + + // aapt resource value: 0x7F0E01D1 + public const int Widget_Design_TextInputLayout = 2131624401; + + // aapt resource value: 0x7F0E01D2 + public const int Widget_MaterialComponents_BottomAppBar = 2131624402; + + // aapt resource value: 0x7F0E01D3 + public const int Widget_MaterialComponents_BottomAppBar_Colored = 2131624403; + + // aapt resource value: 0x7F0E01D4 + public const int Widget_MaterialComponents_BottomNavigationView = 2131624404; + + // aapt resource value: 0x7F0E01D5 + public const int Widget_MaterialComponents_BottomNavigationView_Colored = 2131624405; + + // aapt resource value: 0x7F0E01D6 + public const int Widget_MaterialComponents_BottomSheet_Modal = 2131624406; + + // aapt resource value: 0x7F0E01D7 + public const int Widget_MaterialComponents_Button = 2131624407; + + // aapt resource value: 0x7F0E01D8 + public const int Widget_MaterialComponents_Button_Icon = 2131624408; + + // aapt resource value: 0x7F0E01D9 + public const int Widget_MaterialComponents_Button_OutlinedButton = 2131624409; + + // aapt resource value: 0x7F0E01DA + public const int Widget_MaterialComponents_Button_OutlinedButton_Icon = 2131624410; + + // aapt resource value: 0x7F0E01DB + public const int Widget_MaterialComponents_Button_TextButton = 2131624411; + + // aapt resource value: 0x7F0E01DC + public const int Widget_MaterialComponents_Button_TextButton_Dialog = 2131624412; + + // aapt resource value: 0x7F0E01DD + public const int Widget_MaterialComponents_Button_TextButton_Dialog_Icon = 2131624413; + + // aapt resource value: 0x7F0E01DE + public const int Widget_MaterialComponents_Button_TextButton_Icon = 2131624414; + + // aapt resource value: 0x7F0E01DF + public const int Widget_MaterialComponents_Button_UnelevatedButton = 2131624415; + + // aapt resource value: 0x7F0E01E0 + public const int Widget_MaterialComponents_Button_UnelevatedButton_Icon = 2131624416; + + // aapt resource value: 0x7F0E01E1 + public const int Widget_MaterialComponents_CardView = 2131624417; + + // aapt resource value: 0x7F0E01E6 + public const int Widget_MaterialComponents_ChipGroup = 2131624422; + + // aapt resource value: 0x7F0E01E2 + public const int Widget_MaterialComponents_Chip_Action = 2131624418; + + // aapt resource value: 0x7F0E01E3 + public const int Widget_MaterialComponents_Chip_Choice = 2131624419; + + // aapt resource value: 0x7F0E01E4 + public const int Widget_MaterialComponents_Chip_Entry = 2131624420; + + // aapt resource value: 0x7F0E01E5 + public const int Widget_MaterialComponents_Chip_Filter = 2131624421; + + // aapt resource value: 0x7F0E01E7 + public const int Widget_MaterialComponents_FloatingActionButton = 2131624423; + + // aapt resource value: 0x7F0E01E8 + public const int Widget_MaterialComponents_NavigationView = 2131624424; + + // aapt resource value: 0x7F0E01E9 + public const int Widget_MaterialComponents_Snackbar = 2131624425; + + // aapt resource value: 0x7F0E01EA + public const int Widget_MaterialComponents_Snackbar_FullWidth = 2131624426; + + // aapt resource value: 0x7F0E01EB + public const int Widget_MaterialComponents_TabLayout = 2131624427; + + // aapt resource value: 0x7F0E01EC + public const int Widget_MaterialComponents_TabLayout_Colored = 2131624428; + + // aapt resource value: 0x7F0E01ED + public const int Widget_MaterialComponents_TextInputEditText_FilledBox = 2131624429; + + // aapt resource value: 0x7F0E01EE + public const int Widget_MaterialComponents_TextInputEditText_FilledBox_Dense = 2131624430; + + // aapt resource value: 0x7F0E01EF + public const int Widget_MaterialComponents_TextInputEditText_OutlinedBox = 2131624431; + + // aapt resource value: 0x7F0E01F0 + public const int Widget_MaterialComponents_TextInputEditText_OutlinedBox_Dense = 2131624432; + + // aapt resource value: 0x7F0E01F1 + public const int Widget_MaterialComponents_TextInputLayout_FilledBox = 2131624433; + + // aapt resource value: 0x7F0E01F2 + public const int Widget_MaterialComponents_TextInputLayout_FilledBox_Dense = 2131624434; + + // aapt resource value: 0x7F0E01F3 + public const int Widget_MaterialComponents_TextInputLayout_OutlinedBox = 2131624435; + + // aapt resource value: 0x7F0E01F4 + public const int Widget_MaterialComponents_TextInputLayout_OutlinedBox_Dense = 2131624436; + + // aapt resource value: 0x7F0E01F5 + public const int Widget_MaterialComponents_Toolbar = 2131624437; + + // aapt resource value: 0x7F0E01F6 + public const int Widget_Support_CoordinatorLayout = 2131624438; + + static Style() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Style() + { + } + } + + public partial class Styleable + { + + // aapt resource value: { 0x7F030031,0x7F030032,0x7F030033,0x7F030091,0x7F030092,0x7F030093,0x7F030094,0x7F030095,0x7F030096,0x7F0300A4,0x7F0300A9,0x7F0300AA,0x7F0300B5,0x7F0300DF,0x7F0300E4,0x7F0300E9,0x7F0300EA,0x7F0300EC,0x7F0300F6,0x7F030100,0x7F030123,0x7F03012F,0x7F030140,0x7F030144,0x7F030145,0x7F030173,0x7F030176,0x7F0301BB,0x7F0301C5 } + public static int[] ActionBar = new int[] { + 2130903089, + 2130903090, + 2130903091, + 2130903185, + 2130903186, + 2130903187, + 2130903188, + 2130903189, + 2130903190, + 2130903204, + 2130903209, + 2130903210, + 2130903221, + 2130903263, + 2130903268, + 2130903273, + 2130903274, + 2130903276, + 2130903286, + 2130903296, + 2130903331, + 2130903343, + 2130903360, + 2130903364, + 2130903365, + 2130903411, + 2130903414, + 2130903483, + 2130903493}; + + // aapt resource value: { 0x10100B3 } + public static int[] ActionBarLayout = new int[] { + 16842931}; + + // aapt resource value: 0 + public const int ActionBarLayout_android_layout_gravity = 0; + + // aapt resource value: 0 + public const int ActionBar_background = 0; + + // aapt resource value: 1 + public const int ActionBar_backgroundSplit = 1; + + // aapt resource value: 2 + public const int ActionBar_backgroundStacked = 2; + + // aapt resource value: 3 + public const int ActionBar_contentInsetEnd = 3; + + // aapt resource value: 4 + public const int ActionBar_contentInsetEndWithActions = 4; + + // aapt resource value: 5 + public const int ActionBar_contentInsetLeft = 5; + + // aapt resource value: 6 + public const int ActionBar_contentInsetRight = 6; + + // aapt resource value: 7 + public const int ActionBar_contentInsetStart = 7; + + // aapt resource value: 8 + public const int ActionBar_contentInsetStartWithNavigation = 8; + + // aapt resource value: 9 + public const int ActionBar_customNavigationLayout = 9; + + // aapt resource value: 10 + public const int ActionBar_displayOptions = 10; + + // aapt resource value: 11 + public const int ActionBar_divider = 11; + + // aapt resource value: 12 + public const int ActionBar_elevation = 12; + + // aapt resource value: 13 + public const int ActionBar_height = 13; + + // aapt resource value: 14 + public const int ActionBar_hideOnContentScroll = 14; + + // aapt resource value: 15 + public const int ActionBar_homeAsUpIndicator = 15; + + // aapt resource value: 16 + public const int ActionBar_homeLayout = 16; + + // aapt resource value: 17 + public const int ActionBar_icon = 17; + + // aapt resource value: 18 + public const int ActionBar_indeterminateProgressStyle = 18; + + // aapt resource value: 19 + public const int ActionBar_itemPadding = 19; + + // aapt resource value: 20 + public const int ActionBar_logo = 20; + + // aapt resource value: 21 + public const int ActionBar_navigationMode = 21; + + // aapt resource value: 22 + public const int ActionBar_popupTheme = 22; + + // aapt resource value: 23 + public const int ActionBar_progressBarPadding = 23; + + // aapt resource value: 24 + public const int ActionBar_progressBarStyle = 24; + + // aapt resource value: 25 + public const int ActionBar_subtitle = 25; + + // aapt resource value: 26 + public const int ActionBar_subtitleTextStyle = 26; + + // aapt resource value: 27 + public const int ActionBar_title = 27; + + // aapt resource value: 28 + public const int ActionBar_titleTextStyle = 28; + + // aapt resource value: { 0x101013F } + public static int[] ActionMenuItemView = new int[] { + 16843071}; + + // aapt resource value: 0 + public const int ActionMenuItemView_android_minWidth = 0; + + // aapt resource value: { 0xFFFFFFFF } + public static int[] ActionMenuView = new int[] { + -1}; + + // aapt resource value: { 0x7F030031,0x7F030032,0x7F03007E,0x7F0300DF,0x7F030176,0x7F0301C5 } + public static int[] ActionMode = new int[] { + 2130903089, + 2130903090, + 2130903166, + 2130903263, + 2130903414, + 2130903493}; + + // aapt resource value: 0 + public const int ActionMode_background = 0; + + // aapt resource value: 1 + public const int ActionMode_backgroundSplit = 1; + + // aapt resource value: 2 + public const int ActionMode_closeItemLayout = 2; + + // aapt resource value: 3 + public const int ActionMode_height = 3; + + // aapt resource value: 4 + public const int ActionMode_subtitleTextStyle = 4; + + // aapt resource value: 5 + public const int ActionMode_titleTextStyle = 5; + + // aapt resource value: { 0x7F0300BA,0x7F0300F7 } + public static int[] ActivityChooserView = new int[] { + 2130903226, + 2130903287}; + + // aapt resource value: 0 + public const int ActivityChooserView_expandActivityOverflowButtonDrawable = 0; + + // aapt resource value: 1 + public const int ActivityChooserView_initialActivityCount = 1; + + // aapt resource value: { 0x10100F2,0x7F030052,0x7F030053,0x7F03011A,0x7F03011B,0x7F03012C,0x7F03015B,0x7F03015C } + public static int[] AlertDialog = new int[] { + 16842994, + 2130903122, + 2130903123, + 2130903322, + 2130903323, + 2130903340, + 2130903387, + 2130903388}; + + // aapt resource value: 0 + public const int AlertDialog_android_layout = 0; + + // aapt resource value: 1 + public const int AlertDialog_buttonIconDimen = 1; + + // aapt resource value: 2 + public const int AlertDialog_buttonPanelSideLayout = 2; + + // aapt resource value: 3 + public const int AlertDialog_listItemLayout = 3; + + // aapt resource value: 4 + public const int AlertDialog_listLayout = 4; + + // aapt resource value: 5 + public const int AlertDialog_multiChoiceItemLayout = 5; + + // aapt resource value: 6 + public const int AlertDialog_showTitle = 6; + + // aapt resource value: 7 + public const int AlertDialog_singleChoiceItemLayout = 7; + + // aapt resource value: { 0x101011C,0x1010194,0x1010195,0x1010196,0x101030C,0x101030D } + public static int[] AnimatedStateListDrawableCompat = new int[] { + 16843036, + 16843156, + 16843157, + 16843158, + 16843532, + 16843533}; + + // aapt resource value: 3 + public const int AnimatedStateListDrawableCompat_android_constantSize = 3; + + // aapt resource value: 0 + public const int AnimatedStateListDrawableCompat_android_dither = 0; + + // aapt resource value: 4 + public const int AnimatedStateListDrawableCompat_android_enterFadeDuration = 4; + + // aapt resource value: 5 + public const int AnimatedStateListDrawableCompat_android_exitFadeDuration = 5; + + // aapt resource value: 2 + public const int AnimatedStateListDrawableCompat_android_variablePadding = 2; + + // aapt resource value: 1 + public const int AnimatedStateListDrawableCompat_android_visible = 1; + + // aapt resource value: { 0x10100D0,0x1010199 } + public static int[] AnimatedStateListDrawableItem = new int[] { + 16842960, + 16843161}; + + // aapt resource value: 1 + public const int AnimatedStateListDrawableItem_android_drawable = 1; + + // aapt resource value: 0 + public const int AnimatedStateListDrawableItem_android_id = 0; + + // aapt resource value: { 0x1010199,0x1010449,0x101044A,0x101044B } + public static int[] AnimatedStateListDrawableTransition = new int[] { + 16843161, + 16843849, + 16843850, + 16843851}; + + // aapt resource value: 0 + public const int AnimatedStateListDrawableTransition_android_drawable = 0; + + // aapt resource value: 2 + public const int AnimatedStateListDrawableTransition_android_fromId = 2; + + // aapt resource value: 3 + public const int AnimatedStateListDrawableTransition_android_reversible = 3; + + // aapt resource value: 1 + public const int AnimatedStateListDrawableTransition_android_toId = 1; + + // aapt resource value: { 0x10100D4,0x101048F,0x1010540,0x7F0300B5,0x7F0300BB,0x7F030115 } + public static int[] AppBarLayout = new int[] { + 16842964, + 16843919, + 16844096, + 2130903221, + 2130903227, + 2130903317}; + + // aapt resource value: { 0x7F030169,0x7F03016A,0x7F03016B,0x7F03016C } + public static int[] AppBarLayoutStates = new int[] { + 2130903401, + 2130903402, + 2130903403, + 2130903404}; + + // aapt resource value: 0 + public const int AppBarLayoutStates_state_collapsed = 0; + + // aapt resource value: 1 + public const int AppBarLayoutStates_state_collapsible = 1; + + // aapt resource value: 2 + public const int AppBarLayoutStates_state_liftable = 2; + + // aapt resource value: 3 + public const int AppBarLayoutStates_state_lifted = 3; + + // aapt resource value: 0 + public const int AppBarLayout_android_background = 0; + + // aapt resource value: 2 + public const int AppBarLayout_android_keyboardNavigationCluster = 2; + + // aapt resource value: 1 + public const int AppBarLayout_android_touchscreenBlocksFocus = 1; + + // aapt resource value: 3 + public const int AppBarLayout_elevation = 3; + + // aapt resource value: 4 + public const int AppBarLayout_expanded = 4; + + // aapt resource value: { 0x7F030113,0x7F030114 } + public static int[] AppBarLayout_Layout = new int[] { + 2130903315, + 2130903316}; + + // aapt resource value: 0 + public const int AppBarLayout_Layout_layout_scrollFlags = 0; + + // aapt resource value: 1 + public const int AppBarLayout_Layout_layout_scrollInterpolator = 1; + + // aapt resource value: 5 + public const int AppBarLayout_liftOnScroll = 5; + + // aapt resource value: { 0x1010119,0x7F030166,0x7F0301B9,0x7F0301BA } + public static int[] AppCompatImageView = new int[] { + 16843033, + 2130903398, + 2130903481, + 2130903482}; + + // aapt resource value: 0 + public const int AppCompatImageView_android_src = 0; + + // aapt resource value: 1 + public const int AppCompatImageView_srcCompat = 1; + + // aapt resource value: 2 + public const int AppCompatImageView_tint = 2; + + // aapt resource value: 3 + public const int AppCompatImageView_tintMode = 3; + + // aapt resource value: { 0x1010142,0x7F0301B6,0x7F0301B7,0x7F0301B8 } + public static int[] AppCompatSeekBar = new int[] { + 16843074, + 2130903478, + 2130903479, + 2130903480}; + + // aapt resource value: 0 + public const int AppCompatSeekBar_android_thumb = 0; + + // aapt resource value: 1 + public const int AppCompatSeekBar_tickMark = 1; + + // aapt resource value: 2 + public const int AppCompatSeekBar_tickMarkTint = 2; + + // aapt resource value: 3 + public const int AppCompatSeekBar_tickMarkTintMode = 3; + + // aapt resource value: { 0x1010034,0x101016D,0x101016E,0x101016F,0x1010170,0x1010392,0x1010393 } + public static int[] AppCompatTextHelper = new int[] { + 16842804, + 16843117, + 16843118, + 16843119, + 16843120, + 16843666, + 16843667}; + + // aapt resource value: 2 + public const int AppCompatTextHelper_android_drawableBottom = 2; + + // aapt resource value: 6 + public const int AppCompatTextHelper_android_drawableEnd = 6; + + // aapt resource value: 3 + public const int AppCompatTextHelper_android_drawableLeft = 3; + + // aapt resource value: 4 + public const int AppCompatTextHelper_android_drawableRight = 4; + + // aapt resource value: 5 + public const int AppCompatTextHelper_android_drawableStart = 5; + + // aapt resource value: 1 + public const int AppCompatTextHelper_android_drawableTop = 1; + + // aapt resource value: 0 + public const int AppCompatTextHelper_android_textAppearance = 0; + + // aapt resource value: { 0x1010034,0x7F03002C,0x7F03002D,0x7F03002E,0x7F03002F,0x7F030030,0x7F0300CE,0x7F0300D1,0x7F030108,0x7F030116,0x7F030196 } + public static int[] AppCompatTextView = new int[] { + 16842804, + 2130903084, + 2130903085, + 2130903086, + 2130903087, + 2130903088, + 2130903246, + 2130903249, + 2130903304, + 2130903318, + 2130903446}; + + // aapt resource value: 0 + public const int AppCompatTextView_android_textAppearance = 0; + + // aapt resource value: 1 + public const int AppCompatTextView_autoSizeMaxTextSize = 1; + + // aapt resource value: 2 + public const int AppCompatTextView_autoSizeMinTextSize = 2; + + // aapt resource value: 3 + public const int AppCompatTextView_autoSizePresetSizes = 3; + + // aapt resource value: 4 + public const int AppCompatTextView_autoSizeStepGranularity = 4; + + // aapt resource value: 5 + public const int AppCompatTextView_autoSizeTextType = 5; + + // aapt resource value: 6 + public const int AppCompatTextView_firstBaselineToTopHeight = 6; + + // aapt resource value: 7 + public const int AppCompatTextView_fontFamily = 7; + + // aapt resource value: 8 + public const int AppCompatTextView_lastBaselineToBottomHeight = 8; + + // aapt resource value: 9 + public const int AppCompatTextView_lineHeight = 9; + + // aapt resource value: 10 + public const int AppCompatTextView_textAllCaps = 10; + + // aapt resource value: { 0x1010057,0x10100AE,0x7F030000,0x7F030001,0x7F030002,0x7F030003,0x7F030004,0x7F030005,0x7F030006,0x7F030007,0x7F030008,0x7F030009,0x7F03000A,0x7F03000B,0x7F03000C,0x7F03000E,0x7F03000F,0x7F030010,0x7F030011,0x7F030012,0x7F030013,0x7F030014,0x7F030015,0x7F030016,0x7F030017,0x7F030018,0x7F030019,0x7F03001A,0x7F03001B,0x7F03001C,0x7F03001D,0x7F03001E,0x7F030021,0x7F030022,0x7F030023,0x7F030024,0x7F030025,0x7F03002B,0x7F03003E,0x7F03004C,0x7F03004D,0x7F03004E,0x7F03004F,0x7F030050,0x7F030054,0x7F030055,0x7F03005F,0x7F030064,0x7F030084,0x7F030085,0x7F030086,0x7F030087,0x7F030088,0x7F030089,0x7F03008A,0x7F03008B,0x7F03008C,0x7F03008E,0x7F03009D,0x7F0300A6,0x7F0300A7,0x7F0300A8,0x7F0300AB,0x7F0300AD,0x7F0300B0,0x7F0300B1,0x7F0300B2,0x7F0300B3,0x7F0300B4,0x7F0300E9,0x7F0300F5,0x7F030118,0x7F030119,0x7F03011C,0x7F03011D,0x7F03011E,0x7F03011F,0x7F030120,0x7F030121,0x7F030122,0x7F030137,0x7F030138,0x7F030139,0x7F03013F,0x7F030141,0x7F030148,0x7F030149,0x7F03014A,0x7F03014B,0x7F030153,0x7F030154,0x7F030155,0x7F030156,0x7F030163,0x7F030164,0x7F03017A,0x7F0301A1,0x7F0301A2,0x7F0301A3,0x7F0301A4,0x7F0301A6,0x7F0301A7,0x7F0301A8,0x7F0301A9,0x7F0301AC,0x7F0301AD,0x7F0301C7,0x7F0301C8,0x7F0301C9,0x7F0301CA,0x7F0301D1,0x7F0301D3,0x7F0301D4,0x7F0301D5,0x7F0301D6,0x7F0301D7,0x7F0301D8,0x7F0301D9,0x7F0301DA,0x7F0301DB,0x7F0301DC } + public static int[] AppCompatTheme = new int[] { + 16842839, + 16842926, + 2130903040, + 2130903041, + 2130903042, + 2130903043, + 2130903044, + 2130903045, + 2130903046, + 2130903047, + 2130903048, + 2130903049, + 2130903050, + 2130903051, + 2130903052, + 2130903054, + 2130903055, + 2130903056, + 2130903057, + 2130903058, + 2130903059, + 2130903060, + 2130903061, + 2130903062, + 2130903063, + 2130903064, + 2130903065, + 2130903066, + 2130903067, + 2130903068, + 2130903069, + 2130903070, + 2130903073, + 2130903074, + 2130903075, + 2130903076, + 2130903077, + 2130903083, + 2130903102, + 2130903116, + 2130903117, + 2130903118, + 2130903119, + 2130903120, + 2130903124, + 2130903125, + 2130903135, + 2130903140, + 2130903172, + 2130903173, + 2130903174, + 2130903175, + 2130903176, + 2130903177, + 2130903178, + 2130903179, + 2130903180, + 2130903182, + 2130903197, + 2130903206, + 2130903207, + 2130903208, + 2130903211, + 2130903213, + 2130903216, + 2130903217, + 2130903218, + 2130903219, + 2130903220, + 2130903273, + 2130903285, + 2130903320, + 2130903321, + 2130903324, + 2130903325, + 2130903326, + 2130903327, + 2130903328, + 2130903329, + 2130903330, + 2130903351, + 2130903352, + 2130903353, + 2130903359, + 2130903361, + 2130903368, + 2130903369, + 2130903370, + 2130903371, + 2130903379, + 2130903380, + 2130903381, + 2130903382, + 2130903395, + 2130903396, + 2130903418, + 2130903457, + 2130903458, + 2130903459, + 2130903460, + 2130903462, + 2130903463, + 2130903464, + 2130903465, + 2130903468, + 2130903469, + 2130903495, + 2130903496, + 2130903497, + 2130903498, + 2130903505, + 2130903507, + 2130903508, + 2130903509, + 2130903510, + 2130903511, + 2130903512, + 2130903513, + 2130903514, + 2130903515, + 2130903516}; + + // aapt resource value: 2 + public const int AppCompatTheme_actionBarDivider = 2; + + // aapt resource value: 3 + public const int AppCompatTheme_actionBarItemBackground = 3; + + // aapt resource value: 4 + public const int AppCompatTheme_actionBarPopupTheme = 4; + + // aapt resource value: 5 + public const int AppCompatTheme_actionBarSize = 5; + + // aapt resource value: 6 + public const int AppCompatTheme_actionBarSplitStyle = 6; + + // aapt resource value: 7 + public const int AppCompatTheme_actionBarStyle = 7; + + // aapt resource value: 8 + public const int AppCompatTheme_actionBarTabBarStyle = 8; + + // aapt resource value: 9 + public const int AppCompatTheme_actionBarTabStyle = 9; + + // aapt resource value: 10 + public const int AppCompatTheme_actionBarTabTextStyle = 10; + + // aapt resource value: 11 + public const int AppCompatTheme_actionBarTheme = 11; + + // aapt resource value: 12 + public const int AppCompatTheme_actionBarWidgetTheme = 12; + + // aapt resource value: 13 + public const int AppCompatTheme_actionButtonStyle = 13; + + // aapt resource value: 14 + public const int AppCompatTheme_actionDropDownStyle = 14; + + // aapt resource value: 15 + public const int AppCompatTheme_actionMenuTextAppearance = 15; + + // aapt resource value: 16 + public const int AppCompatTheme_actionMenuTextColor = 16; + + // aapt resource value: 17 + public const int AppCompatTheme_actionModeBackground = 17; + + // aapt resource value: 18 + public const int AppCompatTheme_actionModeCloseButtonStyle = 18; + + // aapt resource value: 19 + public const int AppCompatTheme_actionModeCloseDrawable = 19; + + // aapt resource value: 20 + public const int AppCompatTheme_actionModeCopyDrawable = 20; + + // aapt resource value: 21 + public const int AppCompatTheme_actionModeCutDrawable = 21; + + // aapt resource value: 22 + public const int AppCompatTheme_actionModeFindDrawable = 22; + + // aapt resource value: 23 + public const int AppCompatTheme_actionModePasteDrawable = 23; + + // aapt resource value: 24 + public const int AppCompatTheme_actionModePopupWindowStyle = 24; + + // aapt resource value: 25 + public const int AppCompatTheme_actionModeSelectAllDrawable = 25; + + // aapt resource value: 26 + public const int AppCompatTheme_actionModeShareDrawable = 26; + + // aapt resource value: 27 + public const int AppCompatTheme_actionModeSplitBackground = 27; + + // aapt resource value: 28 + public const int AppCompatTheme_actionModeStyle = 28; + + // aapt resource value: 29 + public const int AppCompatTheme_actionModeWebSearchDrawable = 29; + + // aapt resource value: 30 + public const int AppCompatTheme_actionOverflowButtonStyle = 30; + + // aapt resource value: 31 + public const int AppCompatTheme_actionOverflowMenuStyle = 31; + + // aapt resource value: 32 + public const int AppCompatTheme_activityChooserViewStyle = 32; + + // aapt resource value: 33 + public const int AppCompatTheme_alertDialogButtonGroupStyle = 33; + + // aapt resource value: 34 + public const int AppCompatTheme_alertDialogCenterButtons = 34; + + // aapt resource value: 35 + public const int AppCompatTheme_alertDialogStyle = 35; + + // aapt resource value: 36 + public const int AppCompatTheme_alertDialogTheme = 36; + + // aapt resource value: 1 + public const int AppCompatTheme_android_windowAnimationStyle = 1; + + // aapt resource value: 0 + public const int AppCompatTheme_android_windowIsFloating = 0; + + // aapt resource value: 37 + public const int AppCompatTheme_autoCompleteTextViewStyle = 37; + + // aapt resource value: 38 + public const int AppCompatTheme_borderlessButtonStyle = 38; + + // aapt resource value: 39 + public const int AppCompatTheme_buttonBarButtonStyle = 39; + + // aapt resource value: 40 + public const int AppCompatTheme_buttonBarNegativeButtonStyle = 40; + + // aapt resource value: 41 + public const int AppCompatTheme_buttonBarNeutralButtonStyle = 41; + + // aapt resource value: 42 + public const int AppCompatTheme_buttonBarPositiveButtonStyle = 42; + + // aapt resource value: 43 + public const int AppCompatTheme_buttonBarStyle = 43; + + // aapt resource value: 44 + public const int AppCompatTheme_buttonStyle = 44; + + // aapt resource value: 45 + public const int AppCompatTheme_buttonStyleSmall = 45; + + // aapt resource value: 46 + public const int AppCompatTheme_checkboxStyle = 46; + + // aapt resource value: 47 + public const int AppCompatTheme_checkedTextViewStyle = 47; + + // aapt resource value: 48 + public const int AppCompatTheme_colorAccent = 48; + + // aapt resource value: 49 + public const int AppCompatTheme_colorBackgroundFloating = 49; + + // aapt resource value: 50 + public const int AppCompatTheme_colorButtonNormal = 50; + + // aapt resource value: 51 + public const int AppCompatTheme_colorControlActivated = 51; + + // aapt resource value: 52 + public const int AppCompatTheme_colorControlHighlight = 52; + + // aapt resource value: 53 + public const int AppCompatTheme_colorControlNormal = 53; + + // aapt resource value: 54 + public const int AppCompatTheme_colorError = 54; + + // aapt resource value: 55 + public const int AppCompatTheme_colorPrimary = 55; + + // aapt resource value: 56 + public const int AppCompatTheme_colorPrimaryDark = 56; + + // aapt resource value: 57 + public const int AppCompatTheme_colorSwitchThumbNormal = 57; + + // aapt resource value: 58 + public const int AppCompatTheme_controlBackground = 58; + + // aapt resource value: 59 + public const int AppCompatTheme_dialogCornerRadius = 59; + + // aapt resource value: 60 + public const int AppCompatTheme_dialogPreferredPadding = 60; + + // aapt resource value: 61 + public const int AppCompatTheme_dialogTheme = 61; + + // aapt resource value: 62 + public const int AppCompatTheme_dividerHorizontal = 62; + + // aapt resource value: 63 + public const int AppCompatTheme_dividerVertical = 63; + + // aapt resource value: 65 + public const int AppCompatTheme_dropdownListPreferredItemHeight = 65; + + // aapt resource value: 64 + public const int AppCompatTheme_dropDownListViewStyle = 64; + + // aapt resource value: 66 + public const int AppCompatTheme_editTextBackground = 66; + + // aapt resource value: 67 + public const int AppCompatTheme_editTextColor = 67; + + // aapt resource value: 68 + public const int AppCompatTheme_editTextStyle = 68; + + // aapt resource value: 69 + public const int AppCompatTheme_homeAsUpIndicator = 69; + + // aapt resource value: 70 + public const int AppCompatTheme_imageButtonStyle = 70; + + // aapt resource value: 71 + public const int AppCompatTheme_listChoiceBackgroundIndicator = 71; + + // aapt resource value: 72 + public const int AppCompatTheme_listDividerAlertDialog = 72; + + // aapt resource value: 73 + public const int AppCompatTheme_listMenuViewStyle = 73; + + // aapt resource value: 74 + public const int AppCompatTheme_listPopupWindowStyle = 74; + + // aapt resource value: 75 + public const int AppCompatTheme_listPreferredItemHeight = 75; + + // aapt resource value: 76 + public const int AppCompatTheme_listPreferredItemHeightLarge = 76; + + // aapt resource value: 77 + public const int AppCompatTheme_listPreferredItemHeightSmall = 77; + + // aapt resource value: 78 + public const int AppCompatTheme_listPreferredItemPaddingLeft = 78; + + // aapt resource value: 79 + public const int AppCompatTheme_listPreferredItemPaddingRight = 79; + + // aapt resource value: 80 + public const int AppCompatTheme_panelBackground = 80; + + // aapt resource value: 81 + public const int AppCompatTheme_panelMenuListTheme = 81; + + // aapt resource value: 82 + public const int AppCompatTheme_panelMenuListWidth = 82; + + // aapt resource value: 83 + public const int AppCompatTheme_popupMenuStyle = 83; + + // aapt resource value: 84 + public const int AppCompatTheme_popupWindowStyle = 84; + + // aapt resource value: 85 + public const int AppCompatTheme_radioButtonStyle = 85; + + // aapt resource value: 86 + public const int AppCompatTheme_ratingBarStyle = 86; + + // aapt resource value: 87 + public const int AppCompatTheme_ratingBarStyleIndicator = 87; + + // aapt resource value: 88 + public const int AppCompatTheme_ratingBarStyleSmall = 88; + + // aapt resource value: 89 + public const int AppCompatTheme_searchViewStyle = 89; + + // aapt resource value: 90 + public const int AppCompatTheme_seekBarStyle = 90; + + // aapt resource value: 91 + public const int AppCompatTheme_selectableItemBackground = 91; + + // aapt resource value: 92 + public const int AppCompatTheme_selectableItemBackgroundBorderless = 92; + + // aapt resource value: 93 + public const int AppCompatTheme_spinnerDropDownItemStyle = 93; + + // aapt resource value: 94 + public const int AppCompatTheme_spinnerStyle = 94; + + // aapt resource value: 95 + public const int AppCompatTheme_switchStyle = 95; + + // aapt resource value: 96 + public const int AppCompatTheme_textAppearanceLargePopupMenu = 96; + + // aapt resource value: 97 + public const int AppCompatTheme_textAppearanceListItem = 97; + + // aapt resource value: 98 + public const int AppCompatTheme_textAppearanceListItemSecondary = 98; + + // aapt resource value: 99 + public const int AppCompatTheme_textAppearanceListItemSmall = 99; + + // aapt resource value: 100 + public const int AppCompatTheme_textAppearancePopupMenuHeader = 100; + + // aapt resource value: 101 + public const int AppCompatTheme_textAppearanceSearchResultSubtitle = 101; + + // aapt resource value: 102 + public const int AppCompatTheme_textAppearanceSearchResultTitle = 102; + + // aapt resource value: 103 + public const int AppCompatTheme_textAppearanceSmallPopupMenu = 103; + + // aapt resource value: 104 + public const int AppCompatTheme_textColorAlertDialogListItem = 104; + + // aapt resource value: 105 + public const int AppCompatTheme_textColorSearchUrl = 105; + + // aapt resource value: 106 + public const int AppCompatTheme_toolbarNavigationButtonStyle = 106; + + // aapt resource value: 107 + public const int AppCompatTheme_toolbarStyle = 107; + + // aapt resource value: 108 + public const int AppCompatTheme_tooltipForegroundColor = 108; + + // aapt resource value: 109 + public const int AppCompatTheme_tooltipFrameBackground = 109; + + // aapt resource value: 110 + public const int AppCompatTheme_viewInflaterClass = 110; + + // aapt resource value: 111 + public const int AppCompatTheme_windowActionBar = 111; + + // aapt resource value: 112 + public const int AppCompatTheme_windowActionBarOverlay = 112; + + // aapt resource value: 113 + public const int AppCompatTheme_windowActionModeOverlay = 113; + + // aapt resource value: 114 + public const int AppCompatTheme_windowFixedHeightMajor = 114; + + // aapt resource value: 115 + public const int AppCompatTheme_windowFixedHeightMinor = 115; + + // aapt resource value: 116 + public const int AppCompatTheme_windowFixedWidthMajor = 116; + + // aapt resource value: 117 + public const int AppCompatTheme_windowFixedWidthMinor = 117; + + // aapt resource value: 118 + public const int AppCompatTheme_windowMinWidthMajor = 118; + + // aapt resource value: 119 + public const int AppCompatTheme_windowMinWidthMinor = 119; + + // aapt resource value: 120 + public const int AppCompatTheme_windowNoTitle = 120; + + // aapt resource value: { 0x7F030034,0x7F0300C3,0x7F0300C4,0x7F0300C5,0x7F0300C6,0x7F0300E5 } + public static int[] BottomAppBar = new int[] { + 2130903092, + 2130903235, + 2130903236, + 2130903237, + 2130903238, + 2130903269}; + + // aapt resource value: 0 + public const int BottomAppBar_backgroundTint = 0; + + // aapt resource value: 1 + public const int BottomAppBar_fabAlignmentMode = 1; + + // aapt resource value: 2 + public const int BottomAppBar_fabCradleMargin = 2; + + // aapt resource value: 3 + public const int BottomAppBar_fabCradleRoundedCornerRadius = 3; + + // aapt resource value: 4 + public const int BottomAppBar_fabCradleVerticalOffset = 4; + + // aapt resource value: 5 + public const int BottomAppBar_hideOnScroll = 5; + + // aapt resource value: { 0x7F0300B5,0x7F0300FA,0x7F0300FC,0x7F0300FE,0x7F0300FF,0x7F030103,0x7F030104,0x7F030105,0x7F030107,0x7F03012B } + public static int[] BottomNavigationView = new int[] { + 2130903221, + 2130903290, + 2130903292, + 2130903294, + 2130903295, + 2130903299, + 2130903300, + 2130903301, + 2130903303, + 2130903339}; + + // aapt resource value: 0 + public const int BottomNavigationView_elevation = 0; + + // aapt resource value: 1 + public const int BottomNavigationView_itemBackground = 1; + + // aapt resource value: 2 + public const int BottomNavigationView_itemHorizontalTranslationEnabled = 2; + + // aapt resource value: 3 + public const int BottomNavigationView_itemIconSize = 3; + + // aapt resource value: 4 + public const int BottomNavigationView_itemIconTint = 4; + + // aapt resource value: 5 + public const int BottomNavigationView_itemTextAppearanceActive = 5; + + // aapt resource value: 6 + public const int BottomNavigationView_itemTextAppearanceInactive = 6; + + // aapt resource value: 7 + public const int BottomNavigationView_itemTextColor = 7; + + // aapt resource value: 8 + public const int BottomNavigationView_labelVisibilityMode = 8; + + // aapt resource value: 9 + public const int BottomNavigationView_menu = 9; + + // aapt resource value: { 0x7F030038,0x7F030039,0x7F03003B,0x7F03003C } + public static int[] BottomSheetBehavior_Layout = new int[] { + 2130903096, + 2130903097, + 2130903099, + 2130903100}; + + // aapt resource value: 0 + public const int BottomSheetBehavior_Layout_behavior_fitToContents = 0; + + // aapt resource value: 1 + public const int BottomSheetBehavior_Layout_behavior_hideable = 1; + + // aapt resource value: 2 + public const int BottomSheetBehavior_Layout_behavior_peekHeight = 2; + + // aapt resource value: 3 + public const int BottomSheetBehavior_Layout_behavior_skipCollapsed = 3; + + // aapt resource value: { 0x7F030026 } + public static int[] ButtonBarLayout = new int[] { + 2130903078}; + + // aapt resource value: 0 + public const int ButtonBarLayout_allowStacking = 0; + + // aapt resource value: { 0x101013F,0x1010140,0x7F030058,0x7F030059,0x7F03005A,0x7F03005B,0x7F03005C,0x7F03005D,0x7F030097,0x7F030098,0x7F030099,0x7F03009A,0x7F03009B } + public static int[] CardView = new int[] { + 16843071, + 16843072, + 2130903128, + 2130903129, + 2130903130, + 2130903131, + 2130903132, + 2130903133, + 2130903191, + 2130903192, + 2130903193, + 2130903194, + 2130903195}; + + // aapt resource value: 1 + public const int CardView_android_minHeight = 1; + + // aapt resource value: 0 + public const int CardView_android_minWidth = 0; + + // aapt resource value: 2 + public const int CardView_cardBackgroundColor = 2; + + // aapt resource value: 3 + public const int CardView_cardCornerRadius = 3; + + // aapt resource value: 4 + public const int CardView_cardElevation = 4; + + // aapt resource value: 5 + public const int CardView_cardMaxElevation = 5; + + // aapt resource value: 6 + public const int CardView_cardPreventCornerOverlap = 6; + + // aapt resource value: 7 + public const int CardView_cardUseCompatPadding = 7; + + // aapt resource value: 8 + public const int CardView_contentPadding = 8; + + // aapt resource value: 9 + public const int CardView_contentPaddingBottom = 9; + + // aapt resource value: 10 + public const int CardView_contentPaddingLeft = 10; + + // aapt resource value: 11 + public const int CardView_contentPaddingRight = 11; + + // aapt resource value: 12 + public const int CardView_contentPaddingTop = 12; + + // aapt resource value: { 0x1010034,0x10100AB,0x101011F,0x101014F,0x10101E5,0x7F030061,0x7F030062,0x7F030063,0x7F030065,0x7F030066,0x7F030067,0x7F030069,0x7F03006A,0x7F03006B,0x7F03006C,0x7F03006D,0x7F03006E,0x7F030073,0x7F030074,0x7F030075,0x7F030077,0x7F030078,0x7F030079,0x7F03007A,0x7F03007B,0x7F03007C,0x7F03007D,0x7F0300E3,0x7F0300ED,0x7F0300F1,0x7F03014D,0x7F030159,0x7F0301AE,0x7F0301B0 } + public static int[] Chip = new int[] { + 16842804, + 16842923, + 16843039, + 16843087, + 16843237, + 2130903137, + 2130903138, + 2130903139, + 2130903141, + 2130903142, + 2130903143, + 2130903145, + 2130903146, + 2130903147, + 2130903148, + 2130903149, + 2130903150, + 2130903155, + 2130903156, + 2130903157, + 2130903159, + 2130903160, + 2130903161, + 2130903162, + 2130903163, + 2130903164, + 2130903165, + 2130903267, + 2130903277, + 2130903281, + 2130903373, + 2130903385, + 2130903470, + 2130903472}; + + // aapt resource value: { 0x7F030060,0x7F03006F,0x7F030070,0x7F030071,0x7F03015D,0x7F03015E } + public static int[] ChipGroup = new int[] { + 2130903136, + 2130903151, + 2130903152, + 2130903153, + 2130903389, + 2130903390}; + + // aapt resource value: 0 + public const int ChipGroup_checkedChip = 0; + + // aapt resource value: 1 + public const int ChipGroup_chipSpacing = 1; + + // aapt resource value: 2 + public const int ChipGroup_chipSpacingHorizontal = 2; + + // aapt resource value: 3 + public const int ChipGroup_chipSpacingVertical = 3; + + // aapt resource value: 4 + public const int ChipGroup_singleLine = 4; + + // aapt resource value: 5 + public const int ChipGroup_singleSelection = 5; + + // aapt resource value: 4 + public const int Chip_android_checkable = 4; + + // aapt resource value: 1 + public const int Chip_android_ellipsize = 1; + + // aapt resource value: 2 + public const int Chip_android_maxWidth = 2; + + // aapt resource value: 3 + public const int Chip_android_text = 3; + + // aapt resource value: 0 + public const int Chip_android_textAppearance = 0; + + // aapt resource value: 5 + public const int Chip_checkedIcon = 5; + + // aapt resource value: 6 + public const int Chip_checkedIconEnabled = 6; + + // aapt resource value: 7 + public const int Chip_checkedIconVisible = 7; + + // aapt resource value: 8 + public const int Chip_chipBackgroundColor = 8; + + // aapt resource value: 9 + public const int Chip_chipCornerRadius = 9; + + // aapt resource value: 10 + public const int Chip_chipEndPadding = 10; + + // aapt resource value: 11 + public const int Chip_chipIcon = 11; + + // aapt resource value: 12 + public const int Chip_chipIconEnabled = 12; + + // aapt resource value: 13 + public const int Chip_chipIconSize = 13; + + // aapt resource value: 14 + public const int Chip_chipIconTint = 14; + + // aapt resource value: 15 + public const int Chip_chipIconVisible = 15; + + // aapt resource value: 16 + public const int Chip_chipMinHeight = 16; + + // aapt resource value: 17 + public const int Chip_chipStartPadding = 17; + + // aapt resource value: 18 + public const int Chip_chipStrokeColor = 18; + + // aapt resource value: 19 + public const int Chip_chipStrokeWidth = 19; + + // aapt resource value: 20 + public const int Chip_closeIcon = 20; + + // aapt resource value: 21 + public const int Chip_closeIconEnabled = 21; + + // aapt resource value: 22 + public const int Chip_closeIconEndPadding = 22; + + // aapt resource value: 23 + public const int Chip_closeIconSize = 23; + + // aapt resource value: 24 + public const int Chip_closeIconStartPadding = 24; + + // aapt resource value: 25 + public const int Chip_closeIconTint = 25; + + // aapt resource value: 26 + public const int Chip_closeIconVisible = 26; + + // aapt resource value: 27 + public const int Chip_hideMotionSpec = 27; + + // aapt resource value: 28 + public const int Chip_iconEndPadding = 28; + + // aapt resource value: 29 + public const int Chip_iconStartPadding = 29; + + // aapt resource value: 30 + public const int Chip_rippleColor = 30; + + // aapt resource value: 31 + public const int Chip_showMotionSpec = 31; + + // aapt resource value: 32 + public const int Chip_textEndPadding = 32; + + // aapt resource value: 33 + public const int Chip_textStartPadding = 33; + + // aapt resource value: { 0x7F030081,0x7F030082,0x7F03009C,0x7F0300BC,0x7F0300BD,0x7F0300BE,0x7F0300BF,0x7F0300C0,0x7F0300C1,0x7F0300C2,0x7F03014E,0x7F030150,0x7F03016E,0x7F0301BB,0x7F0301BC,0x7F0301C6 } + public static int[] CollapsingToolbarLayout = new int[] { + 2130903169, + 2130903170, + 2130903196, + 2130903228, + 2130903229, + 2130903230, + 2130903231, + 2130903232, + 2130903233, + 2130903234, + 2130903374, + 2130903376, + 2130903406, + 2130903483, + 2130903484, + 2130903494}; + + // aapt resource value: 0 + public const int CollapsingToolbarLayout_collapsedTitleGravity = 0; + + // aapt resource value: 1 + public const int CollapsingToolbarLayout_collapsedTitleTextAppearance = 1; + + // aapt resource value: 2 + public const int CollapsingToolbarLayout_contentScrim = 2; + + // aapt resource value: 3 + public const int CollapsingToolbarLayout_expandedTitleGravity = 3; + + // aapt resource value: 4 + public const int CollapsingToolbarLayout_expandedTitleMargin = 4; + + // aapt resource value: 5 + public const int CollapsingToolbarLayout_expandedTitleMarginBottom = 5; + + // aapt resource value: 6 + public const int CollapsingToolbarLayout_expandedTitleMarginEnd = 6; + + // aapt resource value: 7 + public const int CollapsingToolbarLayout_expandedTitleMarginStart = 7; + + // aapt resource value: 8 + public const int CollapsingToolbarLayout_expandedTitleMarginTop = 8; + + // aapt resource value: 9 + public const int CollapsingToolbarLayout_expandedTitleTextAppearance = 9; + + // aapt resource value: { 0x7F03010E,0x7F03010F } + public static int[] CollapsingToolbarLayout_Layout = new int[] { + 2130903310, + 2130903311}; + + // aapt resource value: 0 + public const int CollapsingToolbarLayout_Layout_layout_collapseMode = 0; + + // aapt resource value: 1 + public const int CollapsingToolbarLayout_Layout_layout_collapseParallaxMultiplier = 1; + + // aapt resource value: 10 + public const int CollapsingToolbarLayout_scrimAnimationDuration = 10; + + // aapt resource value: 11 + public const int CollapsingToolbarLayout_scrimVisibleHeightTrigger = 11; + + // aapt resource value: 12 + public const int CollapsingToolbarLayout_statusBarScrim = 12; + + // aapt resource value: 13 + public const int CollapsingToolbarLayout_title = 13; + + // aapt resource value: 14 + public const int CollapsingToolbarLayout_titleEnabled = 14; + + // aapt resource value: 15 + public const int CollapsingToolbarLayout_toolbarId = 15; + + // aapt resource value: { 0x10101A5,0x101031F,0x7F030027 } + public static int[] ColorStateListItem = new int[] { + 16843173, + 16843551, + 2130903079}; + + // aapt resource value: 2 + public const int ColorStateListItem_alpha = 2; + + // aapt resource value: 1 + public const int ColorStateListItem_android_alpha = 1; + + // aapt resource value: 0 + public const int ColorStateListItem_android_color = 0; + + // aapt resource value: { 0x1010107,0x7F030056,0x7F030057 } + public static int[] CompoundButton = new int[] { + 16843015, + 2130903126, + 2130903127}; + + // aapt resource value: 0 + public const int CompoundButton_android_button = 0; + + // aapt resource value: 1 + public const int CompoundButton_buttonTint = 1; + + // aapt resource value: 2 + public const int CompoundButton_buttonTintMode = 2; + + // aapt resource value: { 0x7F030106,0x7F03016D } + public static int[] CoordinatorLayout = new int[] { + 2130903302, + 2130903405}; + + // aapt resource value: 0 + public const int CoordinatorLayout_keylines = 0; + + // aapt resource value: { 0x10100B3,0x7F03010B,0x7F03010C,0x7F03010D,0x7F030110,0x7F030111,0x7F030112 } + public static int[] CoordinatorLayout_Layout = new int[] { + 16842931, + 2130903307, + 2130903308, + 2130903309, + 2130903312, + 2130903313, + 2130903314}; + + // aapt resource value: 0 + public const int CoordinatorLayout_Layout_android_layout_gravity = 0; + + // aapt resource value: 1 + public const int CoordinatorLayout_Layout_layout_anchor = 1; + + // aapt resource value: 2 + public const int CoordinatorLayout_Layout_layout_anchorGravity = 2; + + // aapt resource value: 3 + public const int CoordinatorLayout_Layout_layout_behavior = 3; + + // aapt resource value: 4 + public const int CoordinatorLayout_Layout_layout_dodgeInsetEdges = 4; + + // aapt resource value: 5 + public const int CoordinatorLayout_Layout_layout_insetEdge = 5; + + // aapt resource value: 6 + public const int CoordinatorLayout_Layout_layout_keyline = 6; + + // aapt resource value: 1 + public const int CoordinatorLayout_statusBarBackground = 1; + + // aapt resource value: { 0x7F030041,0x7F030042 } + public static int[] DesignTheme = new int[] { + 2130903105, + 2130903106}; + + // aapt resource value: 0 + public const int DesignTheme_bottomSheetDialogTheme = 0; + + // aapt resource value: 1 + public const int DesignTheme_bottomSheetStyle = 1; + + // aapt resource value: { 0x7F030029,0x7F03002A,0x7F030036,0x7F030083,0x7F0300AE,0x7F0300DC,0x7F030162,0x7F0301B2 } + public static int[] DrawerArrowToggle = new int[] { + 2130903081, + 2130903082, + 2130903094, + 2130903171, + 2130903214, + 2130903260, + 2130903394, + 2130903474}; + + // aapt resource value: 0 + public const int DrawerArrowToggle_arrowHeadLength = 0; + + // aapt resource value: 1 + public const int DrawerArrowToggle_arrowShaftLength = 1; + + // aapt resource value: 2 + public const int DrawerArrowToggle_barLength = 2; + + // aapt resource value: 3 + public const int DrawerArrowToggle_color = 3; + + // aapt resource value: 4 + public const int DrawerArrowToggle_drawableSize = 4; + + // aapt resource value: 5 + public const int DrawerArrowToggle_gapBetweenBars = 5; + + // aapt resource value: 6 + public const int DrawerArrowToggle_spinBars = 6; + + // aapt resource value: 7 + public const int DrawerArrowToggle_thickness = 7; + + // aapt resource value: { 0x7F030034,0x7F030035,0x7F03003D,0x7F0300B5,0x7F0300C7,0x7F0300C8,0x7F0300E3,0x7F0300EB,0x7F030129,0x7F030143,0x7F03014D,0x7F030159,0x7F0301D0 } + public static int[] FloatingActionButton = new int[] { + 2130903092, + 2130903093, + 2130903101, + 2130903221, + 2130903239, + 2130903240, + 2130903267, + 2130903275, + 2130903337, + 2130903363, + 2130903373, + 2130903385, + 2130903504}; + + // aapt resource value: 0 + public const int FloatingActionButton_backgroundTint = 0; + + // aapt resource value: 1 + public const int FloatingActionButton_backgroundTintMode = 1; + + // aapt resource value: { 0x7F030037 } + public static int[] FloatingActionButton_Behavior_Layout = new int[] { + 2130903095}; + + // aapt resource value: 0 + public const int FloatingActionButton_Behavior_Layout_behavior_autoHide = 0; + + // aapt resource value: 2 + public const int FloatingActionButton_borderWidth = 2; + + // aapt resource value: 3 + public const int FloatingActionButton_elevation = 3; + + // aapt resource value: 4 + public const int FloatingActionButton_fabCustomSize = 4; + + // aapt resource value: 5 + public const int FloatingActionButton_fabSize = 5; + + // aapt resource value: 6 + public const int FloatingActionButton_hideMotionSpec = 6; + + // aapt resource value: 7 + public const int FloatingActionButton_hoveredFocusedTranslationZ = 7; + + // aapt resource value: 8 + public const int FloatingActionButton_maxImageSize = 8; + + // aapt resource value: 9 + public const int FloatingActionButton_pressedTranslationZ = 9; + + // aapt resource value: 10 + public const int FloatingActionButton_rippleColor = 10; + + // aapt resource value: 11 + public const int FloatingActionButton_showMotionSpec = 11; + + // aapt resource value: 12 + public const int FloatingActionButton_useCompatPadding = 12; + + // aapt resource value: { 0x7F030101,0x7F030117 } + public static int[] FlowLayout = new int[] { + 2130903297, + 2130903319}; + + // aapt resource value: 0 + public const int FlowLayout_itemSpacing = 0; + + // aapt resource value: 1 + public const int FlowLayout_lineSpacing = 1; + + // aapt resource value: { 0x7F0300D2,0x7F0300D3,0x7F0300D4,0x7F0300D5,0x7F0300D6,0x7F0300D7 } + public static int[] FontFamily = new int[] { + 2130903250, + 2130903251, + 2130903252, + 2130903253, + 2130903254, + 2130903255}; + + // aapt resource value: { 0x1010532,0x1010533,0x101053F,0x101056F,0x1010570,0x7F0300D0,0x7F0300D8,0x7F0300D9,0x7F0300DA,0x7F0301CF } + public static int[] FontFamilyFont = new int[] { + 16844082, + 16844083, + 16844095, + 16844143, + 16844144, + 2130903248, + 2130903256, + 2130903257, + 2130903258, + 2130903503}; + + // aapt resource value: 0 + public const int FontFamilyFont_android_font = 0; + + // aapt resource value: 2 + public const int FontFamilyFont_android_fontStyle = 2; + + // aapt resource value: 4 + public const int FontFamilyFont_android_fontVariationSettings = 4; + + // aapt resource value: 1 + public const int FontFamilyFont_android_fontWeight = 1; + + // aapt resource value: 3 + public const int FontFamilyFont_android_ttcIndex = 3; + + // aapt resource value: 5 + public const int FontFamilyFont_font = 5; + + // aapt resource value: 6 + public const int FontFamilyFont_fontStyle = 6; + + // aapt resource value: 7 + public const int FontFamilyFont_fontVariationSettings = 7; + + // aapt resource value: 8 + public const int FontFamilyFont_fontWeight = 8; + + // aapt resource value: 9 + public const int FontFamilyFont_ttcIndex = 9; + + // aapt resource value: 0 + public const int FontFamily_fontProviderAuthority = 0; + + // aapt resource value: 1 + public const int FontFamily_fontProviderCerts = 1; + + // aapt resource value: 2 + public const int FontFamily_fontProviderFetchStrategy = 2; + + // aapt resource value: 3 + public const int FontFamily_fontProviderFetchTimeout = 3; + + // aapt resource value: 4 + public const int FontFamily_fontProviderPackage = 4; + + // aapt resource value: 5 + public const int FontFamily_fontProviderQuery = 5; + + // aapt resource value: { 0x1010109,0x1010200,0x7F0300DB } + public static int[] ForegroundLinearLayout = new int[] { + 16843017, + 16843264, + 2130903259}; + + // aapt resource value: 0 + public const int ForegroundLinearLayout_android_foreground = 0; + + // aapt resource value: 1 + public const int ForegroundLinearLayout_android_foregroundGravity = 1; + + // aapt resource value: 2 + public const int ForegroundLinearLayout_foregroundInsidePadding = 2; + + // aapt resource value: { 0x101019D,0x101019E,0x10101A1,0x10101A2,0x10101A3,0x10101A4,0x1010201,0x101020B,0x1010510,0x1010511,0x1010512,0x1010513 } + public static int[] GradientColor = new int[] { + 16843165, + 16843166, + 16843169, + 16843170, + 16843171, + 16843172, + 16843265, + 16843275, + 16844048, + 16844049, + 16844050, + 16844051}; + + // aapt resource value: { 0x10101A5,0x1010514 } + public static int[] GradientColorItem = new int[] { + 16843173, + 16844052}; + + // aapt resource value: 0 + public const int GradientColorItem_android_color = 0; + + // aapt resource value: 1 + public const int GradientColorItem_android_offset = 1; + + // aapt resource value: 7 + public const int GradientColor_android_centerColor = 7; + + // aapt resource value: 3 + public const int GradientColor_android_centerX = 3; + + // aapt resource value: 4 + public const int GradientColor_android_centerY = 4; + + // aapt resource value: 1 + public const int GradientColor_android_endColor = 1; + + // aapt resource value: 10 + public const int GradientColor_android_endX = 10; + + // aapt resource value: 11 + public const int GradientColor_android_endY = 11; + + // aapt resource value: 5 + public const int GradientColor_android_gradientRadius = 5; + + // aapt resource value: 0 + public const int GradientColor_android_startColor = 0; + + // aapt resource value: 8 + public const int GradientColor_android_startX = 8; + + // aapt resource value: 9 + public const int GradientColor_android_startY = 9; + + // aapt resource value: 6 + public const int GradientColor_android_tileMode = 6; + + // aapt resource value: 2 + public const int GradientColor_android_type = 2; + + // aapt resource value: { 0x10100AF,0x10100C4,0x1010126,0x1010127,0x1010128,0x7F0300AA,0x7F0300AC,0x7F03012A,0x7F030158 } + public static int[] LinearLayoutCompat = new int[] { + 16842927, + 16842948, + 16843046, + 16843047, + 16843048, + 2130903210, + 2130903212, + 2130903338, + 2130903384}; + + // aapt resource value: 2 + public const int LinearLayoutCompat_android_baselineAligned = 2; + + // aapt resource value: 3 + public const int LinearLayoutCompat_android_baselineAlignedChildIndex = 3; + + // aapt resource value: 0 + public const int LinearLayoutCompat_android_gravity = 0; + + // aapt resource value: 1 + public const int LinearLayoutCompat_android_orientation = 1; + + // aapt resource value: 4 + public const int LinearLayoutCompat_android_weightSum = 4; + + // aapt resource value: 5 + public const int LinearLayoutCompat_divider = 5; + + // aapt resource value: 6 + public const int LinearLayoutCompat_dividerPadding = 6; + + // aapt resource value: { 0x10100B3,0x10100F4,0x10100F5,0x1010181 } + public static int[] LinearLayoutCompat_Layout = new int[] { + 16842931, + 16842996, + 16842997, + 16843137}; + + // aapt resource value: 0 + public const int LinearLayoutCompat_Layout_android_layout_gravity = 0; + + // aapt resource value: 2 + public const int LinearLayoutCompat_Layout_android_layout_height = 2; + + // aapt resource value: 3 + public const int LinearLayoutCompat_Layout_android_layout_weight = 3; + + // aapt resource value: 1 + public const int LinearLayoutCompat_Layout_android_layout_width = 1; + + // aapt resource value: 7 + public const int LinearLayoutCompat_measureWithLargestChild = 7; + + // aapt resource value: 8 + public const int LinearLayoutCompat_showDividers = 8; + + // aapt resource value: { 0x10102AC,0x10102AD } + public static int[] ListPopupWindow = new int[] { + 16843436, + 16843437}; + + // aapt resource value: 0 + public const int ListPopupWindow_android_dropDownHorizontalOffset = 0; + + // aapt resource value: 1 + public const int ListPopupWindow_android_dropDownVerticalOffset = 1; + + // aapt resource value: { 0x10101B7,0x10101B8,0x10101B9,0x10101BA,0x7F030034,0x7F030035,0x7F03009F,0x7F0300EC,0x7F0300EE,0x7F0300EF,0x7F0300F0,0x7F0300F2,0x7F0300F3,0x7F03014D,0x7F03016F,0x7F030170 } + public static int[] MaterialButton = new int[] { + 16843191, + 16843192, + 16843193, + 16843194, + 2130903092, + 2130903093, + 2130903199, + 2130903276, + 2130903278, + 2130903279, + 2130903280, + 2130903282, + 2130903283, + 2130903373, + 2130903407, + 2130903408}; + + // aapt resource value: 3 + public const int MaterialButton_android_insetBottom = 3; + + // aapt resource value: 0 + public const int MaterialButton_android_insetLeft = 0; + + // aapt resource value: 1 + public const int MaterialButton_android_insetRight = 1; + + // aapt resource value: 2 + public const int MaterialButton_android_insetTop = 2; + + // aapt resource value: 4 + public const int MaterialButton_backgroundTint = 4; + + // aapt resource value: 5 + public const int MaterialButton_backgroundTintMode = 5; + + // aapt resource value: 6 + public const int MaterialButton_cornerRadius = 6; + + // aapt resource value: 7 + public const int MaterialButton_icon = 7; + + // aapt resource value: 8 + public const int MaterialButton_iconGravity = 8; + + // aapt resource value: 9 + public const int MaterialButton_iconPadding = 9; + + // aapt resource value: 10 + public const int MaterialButton_iconSize = 10; + + // aapt resource value: 11 + public const int MaterialButton_iconTint = 11; + + // aapt resource value: 12 + public const int MaterialButton_iconTintMode = 12; + + // aapt resource value: 13 + public const int MaterialButton_rippleColor = 13; + + // aapt resource value: 14 + public const int MaterialButton_strokeColor = 14; + + // aapt resource value: 15 + public const int MaterialButton_strokeWidth = 15; + + // aapt resource value: { 0x7F03016F,0x7F030170 } + public static int[] MaterialCardView = new int[] { + 2130903407, + 2130903408}; + + // aapt resource value: 0 + public const int MaterialCardView_strokeColor = 0; + + // aapt resource value: 1 + public const int MaterialCardView_strokeWidth = 1; + + // aapt resource value: { 0x7F030041,0x7F030042,0x7F030068,0x7F030072,0x7F030076,0x7F030084,0x7F030085,0x7F03008B,0x7F03008C,0x7F03008D,0x7F0300B4,0x7F0300CF,0x7F030125,0x7F030126,0x7F030130,0x7F03014F,0x7F03015F,0x7F030192,0x7F030197,0x7F030198,0x7F030199,0x7F03019A,0x7F03019B,0x7F03019C,0x7F03019D,0x7F03019E,0x7F03019F,0x7F0301A0,0x7F0301A5,0x7F0301AA,0x7F0301AB,0x7F0301AF } + public static int[] MaterialComponentsTheme = new int[] { + 2130903105, + 2130903106, + 2130903144, + 2130903154, + 2130903158, + 2130903172, + 2130903173, + 2130903179, + 2130903180, + 2130903181, + 2130903220, + 2130903247, + 2130903333, + 2130903334, + 2130903344, + 2130903375, + 2130903391, + 2130903442, + 2130903447, + 2130903448, + 2130903449, + 2130903450, + 2130903451, + 2130903452, + 2130903453, + 2130903454, + 2130903455, + 2130903456, + 2130903461, + 2130903466, + 2130903467, + 2130903471}; + + // aapt resource value: 0 + public const int MaterialComponentsTheme_bottomSheetDialogTheme = 0; + + // aapt resource value: 1 + public const int MaterialComponentsTheme_bottomSheetStyle = 1; + + // aapt resource value: 2 + public const int MaterialComponentsTheme_chipGroupStyle = 2; + + // aapt resource value: 3 + public const int MaterialComponentsTheme_chipStandaloneStyle = 3; + + // aapt resource value: 4 + public const int MaterialComponentsTheme_chipStyle = 4; + + // aapt resource value: 5 + public const int MaterialComponentsTheme_colorAccent = 5; + + // aapt resource value: 6 + public const int MaterialComponentsTheme_colorBackgroundFloating = 6; + + // aapt resource value: 7 + public const int MaterialComponentsTheme_colorPrimary = 7; + + // aapt resource value: 8 + public const int MaterialComponentsTheme_colorPrimaryDark = 8; + + // aapt resource value: 9 + public const int MaterialComponentsTheme_colorSecondary = 9; + + // aapt resource value: 10 + public const int MaterialComponentsTheme_editTextStyle = 10; + + // aapt resource value: 11 + public const int MaterialComponentsTheme_floatingActionButtonStyle = 11; + + // aapt resource value: 12 + public const int MaterialComponentsTheme_materialButtonStyle = 12; + + // aapt resource value: 13 + public const int MaterialComponentsTheme_materialCardViewStyle = 13; + + // aapt resource value: 14 + public const int MaterialComponentsTheme_navigationViewStyle = 14; + + // aapt resource value: 15 + public const int MaterialComponentsTheme_scrimBackground = 15; + + // aapt resource value: 16 + public const int MaterialComponentsTheme_snackbarButtonStyle = 16; + + // aapt resource value: 17 + public const int MaterialComponentsTheme_tabStyle = 17; + + // aapt resource value: 18 + public const int MaterialComponentsTheme_textAppearanceBody1 = 18; + + // aapt resource value: 19 + public const int MaterialComponentsTheme_textAppearanceBody2 = 19; + + // aapt resource value: 20 + public const int MaterialComponentsTheme_textAppearanceButton = 20; + + // aapt resource value: 21 + public const int MaterialComponentsTheme_textAppearanceCaption = 21; + + // aapt resource value: 22 + public const int MaterialComponentsTheme_textAppearanceHeadline1 = 22; + + // aapt resource value: 23 + public const int MaterialComponentsTheme_textAppearanceHeadline2 = 23; + + // aapt resource value: 24 + public const int MaterialComponentsTheme_textAppearanceHeadline3 = 24; + + // aapt resource value: 25 + public const int MaterialComponentsTheme_textAppearanceHeadline4 = 25; + + // aapt resource value: 26 + public const int MaterialComponentsTheme_textAppearanceHeadline5 = 26; + + // aapt resource value: 27 + public const int MaterialComponentsTheme_textAppearanceHeadline6 = 27; + + // aapt resource value: 28 + public const int MaterialComponentsTheme_textAppearanceOverline = 28; + + // aapt resource value: 29 + public const int MaterialComponentsTheme_textAppearanceSubtitle1 = 29; + + // aapt resource value: 30 + public const int MaterialComponentsTheme_textAppearanceSubtitle2 = 30; + + // aapt resource value: 31 + public const int MaterialComponentsTheme_textInputStyle = 31; + + // aapt resource value: { 0x101000E,0x10100D0,0x1010194,0x10101DE,0x10101DF,0x10101E0 } + public static int[] MenuGroup = new int[] { + 16842766, + 16842960, + 16843156, + 16843230, + 16843231, + 16843232}; + + // aapt resource value: 5 + public const int MenuGroup_android_checkableBehavior = 5; + + // aapt resource value: 0 + public const int MenuGroup_android_enabled = 0; + + // aapt resource value: 1 + public const int MenuGroup_android_id = 1; + + // aapt resource value: 3 + public const int MenuGroup_android_menuCategory = 3; + + // aapt resource value: 4 + public const int MenuGroup_android_orderInCategory = 4; + + // aapt resource value: 2 + public const int MenuGroup_android_visible = 2; + + // aapt resource value: { 0x1010002,0x101000E,0x10100D0,0x1010106,0x1010194,0x10101DE,0x10101DF,0x10101E1,0x10101E2,0x10101E3,0x10101E4,0x10101E5,0x101026F,0x7F03000D,0x7F03001F,0x7F030020,0x7F030028,0x7F030090,0x7F0300F2,0x7F0300F3,0x7F030131,0x7F030157,0x7F0301CB } + public static int[] MenuItem = new int[] { + 16842754, + 16842766, + 16842960, + 16843014, + 16843156, + 16843230, + 16843231, + 16843233, + 16843234, + 16843235, + 16843236, + 16843237, + 16843375, + 2130903053, + 2130903071, + 2130903072, + 2130903080, + 2130903184, + 2130903282, + 2130903283, + 2130903345, + 2130903383, + 2130903499}; + + // aapt resource value: 13 + public const int MenuItem_actionLayout = 13; + + // aapt resource value: 14 + public const int MenuItem_actionProviderClass = 14; + + // aapt resource value: 15 + public const int MenuItem_actionViewClass = 15; + + // aapt resource value: 16 + public const int MenuItem_alphabeticModifiers = 16; + + // aapt resource value: 9 + public const int MenuItem_android_alphabeticShortcut = 9; + + // aapt resource value: 11 + public const int MenuItem_android_checkable = 11; + + // aapt resource value: 3 + public const int MenuItem_android_checked = 3; + + // aapt resource value: 1 + public const int MenuItem_android_enabled = 1; + + // aapt resource value: 0 + public const int MenuItem_android_icon = 0; + + // aapt resource value: 2 + public const int MenuItem_android_id = 2; + + // aapt resource value: 5 + public const int MenuItem_android_menuCategory = 5; + + // aapt resource value: 10 + public const int MenuItem_android_numericShortcut = 10; + + // aapt resource value: 12 + public const int MenuItem_android_onClick = 12; + + // aapt resource value: 6 + public const int MenuItem_android_orderInCategory = 6; + + // aapt resource value: 7 + public const int MenuItem_android_title = 7; + + // aapt resource value: 8 + public const int MenuItem_android_titleCondensed = 8; + + // aapt resource value: 4 + public const int MenuItem_android_visible = 4; + + // aapt resource value: 17 + public const int MenuItem_contentDescription = 17; + + // aapt resource value: 18 + public const int MenuItem_iconTint = 18; + + // aapt resource value: 19 + public const int MenuItem_iconTintMode = 19; + + // aapt resource value: 20 + public const int MenuItem_numericModifiers = 20; + + // aapt resource value: 21 + public const int MenuItem_showAsAction = 21; + + // aapt resource value: 22 + public const int MenuItem_tooltipText = 22; + + // aapt resource value: { 0x10100AE,0x101012C,0x101012D,0x101012E,0x101012F,0x1010130,0x1010131,0x7F030142,0x7F030171 } + public static int[] MenuView = new int[] { + 16842926, + 16843052, + 16843053, + 16843054, + 16843055, + 16843056, + 16843057, + 2130903362, + 2130903409}; + + // aapt resource value: 4 + public const int MenuView_android_headerBackground = 4; + + // aapt resource value: 2 + public const int MenuView_android_horizontalDivider = 2; + + // aapt resource value: 5 + public const int MenuView_android_itemBackground = 5; + + // aapt resource value: 6 + public const int MenuView_android_itemIconDisabledAlpha = 6; + + // aapt resource value: 1 + public const int MenuView_android_itemTextAppearance = 1; + + // aapt resource value: 3 + public const int MenuView_android_verticalDivider = 3; + + // aapt resource value: 0 + public const int MenuView_android_windowAnimationStyle = 0; + + // aapt resource value: 7 + public const int MenuView_preserveIconSpacing = 7; + + // aapt resource value: 8 + public const int MenuView_subMenuArrow = 8; + + // aapt resource value: { 0x10100D4,0x10100DD,0x101011F,0x7F0300B5,0x7F0300DE,0x7F0300FA,0x7F0300FB,0x7F0300FD,0x7F0300FF,0x7F030102,0x7F030105,0x7F03012B } + public static int[] NavigationView = new int[] { + 16842964, + 16842973, + 16843039, + 2130903221, + 2130903262, + 2130903290, + 2130903291, + 2130903293, + 2130903295, + 2130903298, + 2130903301, + 2130903339}; + + // aapt resource value: 0 + public const int NavigationView_android_background = 0; + + // aapt resource value: 1 + public const int NavigationView_android_fitsSystemWindows = 1; + + // aapt resource value: 2 + public const int NavigationView_android_maxWidth = 2; + + // aapt resource value: 3 + public const int NavigationView_elevation = 3; + + // aapt resource value: 4 + public const int NavigationView_headerLayout = 4; + + // aapt resource value: 5 + public const int NavigationView_itemBackground = 5; + + // aapt resource value: 6 + public const int NavigationView_itemHorizontalPadding = 6; + + // aapt resource value: 7 + public const int NavigationView_itemIconPadding = 7; + + // aapt resource value: 8 + public const int NavigationView_itemIconTint = 8; + + // aapt resource value: 9 + public const int NavigationView_itemTextAppearance = 9; + + // aapt resource value: 10 + public const int NavigationView_itemTextColor = 10; + + // aapt resource value: 11 + public const int NavigationView_menu = 11; + + // aapt resource value: { 0x1010176,0x10102C9,0x7F030132 } + public static int[] PopupWindow = new int[] { + 16843126, + 16843465, + 2130903346}; + + // aapt resource value: { 0x7F030168 } + public static int[] PopupWindowBackgroundState = new int[] { + 2130903400}; + + // aapt resource value: 0 + public const int PopupWindowBackgroundState_state_above_anchor = 0; + + // aapt resource value: 1 + public const int PopupWindow_android_popupAnimationStyle = 1; + + // aapt resource value: 0 + public const int PopupWindow_android_popupBackground = 0; + + // aapt resource value: 2 + public const int PopupWindow_overlapAnchor = 2; + + // aapt resource value: { 0x7F030133,0x7F030136 } + public static int[] RecycleListView = new int[] { + 2130903347, + 2130903350}; + + // aapt resource value: 0 + public const int RecycleListView_paddingBottomNoButtons = 0; + + // aapt resource value: 1 + public const int RecycleListView_paddingTopNoTitle = 1; + + // aapt resource value: { 0x10100C4,0x10100F1,0x7F0300C9,0x7F0300CA,0x7F0300CB,0x7F0300CC,0x7F0300CD,0x7F03010A,0x7F03014C,0x7F030161,0x7F030167 } + public static int[] RecyclerView = new int[] { + 16842948, + 16842993, + 2130903241, + 2130903242, + 2130903243, + 2130903244, + 2130903245, + 2130903306, + 2130903372, + 2130903393, + 2130903399}; + + // aapt resource value: 1 + public const int RecyclerView_android_descendantFocusability = 1; + + // aapt resource value: 0 + public const int RecyclerView_android_orientation = 0; + + // aapt resource value: 2 + public const int RecyclerView_fastScrollEnabled = 2; + + // aapt resource value: 3 + public const int RecyclerView_fastScrollHorizontalThumbDrawable = 3; + + // aapt resource value: 4 + public const int RecyclerView_fastScrollHorizontalTrackDrawable = 4; + + // aapt resource value: 5 + public const int RecyclerView_fastScrollVerticalThumbDrawable = 5; + + // aapt resource value: 6 + public const int RecyclerView_fastScrollVerticalTrackDrawable = 6; + + // aapt resource value: 7 + public const int RecyclerView_layoutManager = 7; + + // aapt resource value: 8 + public const int RecyclerView_reverseLayout = 8; + + // aapt resource value: 9 + public const int RecyclerView_spanCount = 9; + + // aapt resource value: 10 + public const int RecyclerView_stackFromEnd = 10; + + // aapt resource value: { 0x7F0300F8 } + public static int[] ScrimInsetsFrameLayout = new int[] { + 2130903288}; + + // aapt resource value: 0 + public const int ScrimInsetsFrameLayout_insetForeground = 0; + + // aapt resource value: { 0x7F03003A } + public static int[] ScrollingViewBehavior_Layout = new int[] { + 2130903098}; + + // aapt resource value: 0 + public const int ScrollingViewBehavior_Layout_behavior_overlapTop = 0; + + // aapt resource value: { 0x10100DA,0x101011F,0x1010220,0x1010264,0x7F030077,0x7F03008F,0x7F0300A5,0x7F0300DD,0x7F0300F4,0x7F030109,0x7F030146,0x7F030147,0x7F030151,0x7F030152,0x7F030172,0x7F030177,0x7F0301D2 } + public static int[] SearchView = new int[] { + 16842970, + 16843039, + 16843296, + 16843364, + 2130903159, + 2130903183, + 2130903205, + 2130903261, + 2130903284, + 2130903305, + 2130903366, + 2130903367, + 2130903377, + 2130903378, + 2130903410, + 2130903415, + 2130903506}; + + // aapt resource value: 0 + public const int SearchView_android_focusable = 0; + + // aapt resource value: 3 + public const int SearchView_android_imeOptions = 3; + + // aapt resource value: 2 + public const int SearchView_android_inputType = 2; + + // aapt resource value: 1 + public const int SearchView_android_maxWidth = 1; + + // aapt resource value: 4 + public const int SearchView_closeIcon = 4; + + // aapt resource value: 5 + public const int SearchView_commitIcon = 5; + + // aapt resource value: 6 + public const int SearchView_defaultQueryHint = 6; + + // aapt resource value: 7 + public const int SearchView_goIcon = 7; + + // aapt resource value: 8 + public const int SearchView_iconifiedByDefault = 8; + + // aapt resource value: 9 + public const int SearchView_layout = 9; + + // aapt resource value: 10 + public const int SearchView_queryBackground = 10; + + // aapt resource value: 11 + public const int SearchView_queryHint = 11; + + // aapt resource value: 12 + public const int SearchView_searchHintIcon = 12; + + // aapt resource value: 13 + public const int SearchView_searchIcon = 13; + + // aapt resource value: 14 + public const int SearchView_submitBackground = 14; + + // aapt resource value: 15 + public const int SearchView_suggestionRowLayout = 15; + + // aapt resource value: 16 + public const int SearchView_voiceIcon = 16; + + // aapt resource value: { 0x7F03015F,0x7F030160 } + public static int[] Snackbar = new int[] { + 2130903391, + 2130903392}; + + // aapt resource value: { 0x101011F,0x7F0300B5,0x7F030127 } + public static int[] SnackbarLayout = new int[] { + 16843039, + 2130903221, + 2130903335}; + + // aapt resource value: 0 + public const int SnackbarLayout_android_maxWidth = 0; + + // aapt resource value: 1 + public const int SnackbarLayout_elevation = 1; + + // aapt resource value: 2 + public const int SnackbarLayout_maxActionInlineWidth = 2; + + // aapt resource value: 0 + public const int Snackbar_snackbarButtonStyle = 0; + + // aapt resource value: 1 + public const int Snackbar_snackbarStyle = 1; + + // aapt resource value: { 0x10100B2,0x1010176,0x101017B,0x1010262,0x7F030140 } + public static int[] Spinner = new int[] { + 16842930, + 16843126, + 16843131, + 16843362, + 2130903360}; + + // aapt resource value: 3 + public const int Spinner_android_dropDownWidth = 3; + + // aapt resource value: 0 + public const int Spinner_android_entries = 0; + + // aapt resource value: 1 + public const int Spinner_android_popupBackground = 1; + + // aapt resource value: 2 + public const int Spinner_android_prompt = 2; + + // aapt resource value: 4 + public const int Spinner_popupTheme = 4; + + // aapt resource value: { 0x101011C,0x1010194,0x1010195,0x1010196,0x101030C,0x101030D } + public static int[] StateListDrawable = new int[] { + 16843036, + 16843156, + 16843157, + 16843158, + 16843532, + 16843533}; + + // aapt resource value: { 0x1010199 } + public static int[] StateListDrawableItem = new int[] { + 16843161}; + + // aapt resource value: 0 + public const int StateListDrawableItem_android_drawable = 0; + + // aapt resource value: 3 + public const int StateListDrawable_android_constantSize = 3; + + // aapt resource value: 0 + public const int StateListDrawable_android_dither = 0; + + // aapt resource value: 4 + public const int StateListDrawable_android_enterFadeDuration = 4; + + // aapt resource value: 5 + public const int StateListDrawable_android_exitFadeDuration = 5; + + // aapt resource value: 2 + public const int StateListDrawable_android_variablePadding = 2; + + // aapt resource value: 1 + public const int StateListDrawable_android_visible = 1; + + // aapt resource value: { 0x1010124,0x1010125,0x1010142,0x7F03015A,0x7F030165,0x7F030178,0x7F030179,0x7F03017B,0x7F0301B3,0x7F0301B4,0x7F0301B5,0x7F0301CC,0x7F0301CD,0x7F0301CE } + public static int[] SwitchCompat = new int[] { + 16843044, + 16843045, + 16843074, + 2130903386, + 2130903397, + 2130903416, + 2130903417, + 2130903419, + 2130903475, + 2130903476, + 2130903477, + 2130903500, + 2130903501, + 2130903502}; + + // aapt resource value: 1 + public const int SwitchCompat_android_textOff = 1; + + // aapt resource value: 0 + public const int SwitchCompat_android_textOn = 0; + + // aapt resource value: 2 + public const int SwitchCompat_android_thumb = 2; + + // aapt resource value: 3 + public const int SwitchCompat_showText = 3; + + // aapt resource value: 4 + public const int SwitchCompat_splitTrack = 4; + + // aapt resource value: 5 + public const int SwitchCompat_switchMinWidth = 5; + + // aapt resource value: 6 + public const int SwitchCompat_switchPadding = 6; + + // aapt resource value: 7 + public const int SwitchCompat_switchTextAppearance = 7; + + // aapt resource value: 8 + public const int SwitchCompat_thumbTextPadding = 8; + + // aapt resource value: 9 + public const int SwitchCompat_thumbTint = 9; + + // aapt resource value: 10 + public const int SwitchCompat_thumbTintMode = 10; + + // aapt resource value: 11 + public const int SwitchCompat_track = 11; + + // aapt resource value: 12 + public const int SwitchCompat_trackTint = 12; + + // aapt resource value: 13 + public const int SwitchCompat_trackTintMode = 13; + + // aapt resource value: { 0x1010002,0x10100F2,0x101014F } + public static int[] TabItem = new int[] { + 16842754, + 16842994, + 16843087}; + + // aapt resource value: 0 + public const int TabItem_android_icon = 0; + + // aapt resource value: 1 + public const int TabItem_android_layout = 1; + + // aapt resource value: 2 + public const int TabItem_android_text = 2; + + // aapt resource value: { 0x7F03017C,0x7F03017D,0x7F03017E,0x7F03017F,0x7F030180,0x7F030181,0x7F030182,0x7F030183,0x7F030184,0x7F030185,0x7F030186,0x7F030187,0x7F030188,0x7F030189,0x7F03018A,0x7F03018B,0x7F03018C,0x7F03018D,0x7F03018E,0x7F03018F,0x7F030190,0x7F030191,0x7F030193,0x7F030194,0x7F030195 } + public static int[] TabLayout = new int[] { + 2130903420, + 2130903421, + 2130903422, + 2130903423, + 2130903424, + 2130903425, + 2130903426, + 2130903427, + 2130903428, + 2130903429, + 2130903430, + 2130903431, + 2130903432, + 2130903433, + 2130903434, + 2130903435, + 2130903436, + 2130903437, + 2130903438, + 2130903439, + 2130903440, + 2130903441, + 2130903443, + 2130903444, + 2130903445}; + + // aapt resource value: 0 + public const int TabLayout_tabBackground = 0; + + // aapt resource value: 1 + public const int TabLayout_tabContentStart = 1; + + // aapt resource value: 2 + public const int TabLayout_tabGravity = 2; + + // aapt resource value: 3 + public const int TabLayout_tabIconTint = 3; + + // aapt resource value: 4 + public const int TabLayout_tabIconTintMode = 4; + + // aapt resource value: 5 + public const int TabLayout_tabIndicator = 5; + + // aapt resource value: 6 + public const int TabLayout_tabIndicatorAnimationDuration = 6; + + // aapt resource value: 7 + public const int TabLayout_tabIndicatorColor = 7; + + // aapt resource value: 8 + public const int TabLayout_tabIndicatorFullWidth = 8; + + // aapt resource value: 9 + public const int TabLayout_tabIndicatorGravity = 9; + + // aapt resource value: 10 + public const int TabLayout_tabIndicatorHeight = 10; + + // aapt resource value: 11 + public const int TabLayout_tabInlineLabel = 11; + + // aapt resource value: 12 + public const int TabLayout_tabMaxWidth = 12; + + // aapt resource value: 13 + public const int TabLayout_tabMinWidth = 13; + + // aapt resource value: 14 + public const int TabLayout_tabMode = 14; + + // aapt resource value: 15 + public const int TabLayout_tabPadding = 15; + + // aapt resource value: 16 + public const int TabLayout_tabPaddingBottom = 16; + + // aapt resource value: 17 + public const int TabLayout_tabPaddingEnd = 17; + + // aapt resource value: 18 + public const int TabLayout_tabPaddingStart = 18; + + // aapt resource value: 19 + public const int TabLayout_tabPaddingTop = 19; + + // aapt resource value: 20 + public const int TabLayout_tabRippleColor = 20; + + // aapt resource value: 21 + public const int TabLayout_tabSelectedTextColor = 21; + + // aapt resource value: 22 + public const int TabLayout_tabTextAppearance = 22; + + // aapt resource value: 23 + public const int TabLayout_tabTextColor = 23; + + // aapt resource value: 24 + public const int TabLayout_tabUnboundedRipple = 24; + + // aapt resource value: { 0x1010095,0x1010096,0x1010097,0x1010098,0x101009A,0x101009B,0x1010161,0x1010162,0x1010163,0x1010164,0x10103AC,0x7F0300D1,0x7F030196 } + public static int[] TextAppearance = new int[] { + 16842901, + 16842902, + 16842903, + 16842904, + 16842906, + 16842907, + 16843105, + 16843106, + 16843107, + 16843108, + 16843692, + 2130903249, + 2130903446}; + + // aapt resource value: 10 + public const int TextAppearance_android_fontFamily = 10; + + // aapt resource value: 6 + public const int TextAppearance_android_shadowColor = 6; + + // aapt resource value: 7 + public const int TextAppearance_android_shadowDx = 7; + + // aapt resource value: 8 + public const int TextAppearance_android_shadowDy = 8; + + // aapt resource value: 9 + public const int TextAppearance_android_shadowRadius = 9; + + // aapt resource value: 3 + public const int TextAppearance_android_textColor = 3; + + // aapt resource value: 4 + public const int TextAppearance_android_textColorHint = 4; + + // aapt resource value: 5 + public const int TextAppearance_android_textColorLink = 5; + + // aapt resource value: 0 + public const int TextAppearance_android_textSize = 0; + + // aapt resource value: 2 + public const int TextAppearance_android_textStyle = 2; + + // aapt resource value: 1 + public const int TextAppearance_android_typeface = 1; + + // aapt resource value: 11 + public const int TextAppearance_fontFamily = 11; + + // aapt resource value: 12 + public const int TextAppearance_textAllCaps = 12; + + // aapt resource value: { 0x101009A,0x1010150,0x7F030043,0x7F030044,0x7F030045,0x7F030046,0x7F030047,0x7F030048,0x7F030049,0x7F03004A,0x7F03004B,0x7F0300A0,0x7F0300A1,0x7F0300A2,0x7F0300A3,0x7F0300B8,0x7F0300B9,0x7F0300E0,0x7F0300E1,0x7F0300E2,0x7F0300E6,0x7F0300E7,0x7F0300E8,0x7F03013A,0x7F03013B,0x7F03013C,0x7F03013D,0x7F03013E } + public static int[] TextInputLayout = new int[] { + 16842906, + 16843088, + 2130903107, + 2130903108, + 2130903109, + 2130903110, + 2130903111, + 2130903112, + 2130903113, + 2130903114, + 2130903115, + 2130903200, + 2130903201, + 2130903202, + 2130903203, + 2130903224, + 2130903225, + 2130903264, + 2130903265, + 2130903266, + 2130903270, + 2130903271, + 2130903272, + 2130903354, + 2130903355, + 2130903356, + 2130903357, + 2130903358}; + + // aapt resource value: 1 + public const int TextInputLayout_android_hint = 1; + + // aapt resource value: 0 + public const int TextInputLayout_android_textColorHint = 0; + + // aapt resource value: 2 + public const int TextInputLayout_boxBackgroundColor = 2; + + // aapt resource value: 3 + public const int TextInputLayout_boxBackgroundMode = 3; + + // aapt resource value: 4 + public const int TextInputLayout_boxCollapsedPaddingTop = 4; + + // aapt resource value: 5 + public const int TextInputLayout_boxCornerRadiusBottomEnd = 5; + + // aapt resource value: 6 + public const int TextInputLayout_boxCornerRadiusBottomStart = 6; + + // aapt resource value: 7 + public const int TextInputLayout_boxCornerRadiusTopEnd = 7; + + // aapt resource value: 8 + public const int TextInputLayout_boxCornerRadiusTopStart = 8; + + // aapt resource value: 9 + public const int TextInputLayout_boxStrokeColor = 9; + + // aapt resource value: 10 + public const int TextInputLayout_boxStrokeWidth = 10; + + // aapt resource value: 11 + public const int TextInputLayout_counterEnabled = 11; + + // aapt resource value: 12 + public const int TextInputLayout_counterMaxLength = 12; + + // aapt resource value: 13 + public const int TextInputLayout_counterOverflowTextAppearance = 13; + + // aapt resource value: 14 + public const int TextInputLayout_counterTextAppearance = 14; + + // aapt resource value: 15 + public const int TextInputLayout_errorEnabled = 15; + + // aapt resource value: 16 + public const int TextInputLayout_errorTextAppearance = 16; + + // aapt resource value: 17 + public const int TextInputLayout_helperText = 17; + + // aapt resource value: 18 + public const int TextInputLayout_helperTextEnabled = 18; + + // aapt resource value: 19 + public const int TextInputLayout_helperTextTextAppearance = 19; + + // aapt resource value: 20 + public const int TextInputLayout_hintAnimationEnabled = 20; + + // aapt resource value: 21 + public const int TextInputLayout_hintEnabled = 21; + + // aapt resource value: 22 + public const int TextInputLayout_hintTextAppearance = 22; + + // aapt resource value: 23 + public const int TextInputLayout_passwordToggleContentDescription = 23; + + // aapt resource value: 24 + public const int TextInputLayout_passwordToggleDrawable = 24; + + // aapt resource value: 25 + public const int TextInputLayout_passwordToggleEnabled = 25; + + // aapt resource value: 26 + public const int TextInputLayout_passwordToggleTint = 26; + + // aapt resource value: 27 + public const int TextInputLayout_passwordToggleTintMode = 27; + + // aapt resource value: { 0x1010034,0x7F0300B6,0x7F0300B7 } + public static int[] ThemeEnforcement = new int[] { + 16842804, + 2130903222, + 2130903223}; + + // aapt resource value: 0 + public const int ThemeEnforcement_android_textAppearance = 0; + + // aapt resource value: 1 + public const int ThemeEnforcement_enforceMaterialTheme = 1; + + // aapt resource value: 2 + public const int ThemeEnforcement_enforceTextAppearance = 2; + + // aapt resource value: { 0x10100AF,0x1010140,0x7F030051,0x7F03007F,0x7F030080,0x7F030091,0x7F030092,0x7F030093,0x7F030094,0x7F030095,0x7F030096,0x7F030123,0x7F030124,0x7F030128,0x7F03012D,0x7F03012E,0x7F030140,0x7F030173,0x7F030174,0x7F030175,0x7F0301BB,0x7F0301BD,0x7F0301BE,0x7F0301BF,0x7F0301C0,0x7F0301C1,0x7F0301C2,0x7F0301C3,0x7F0301C4 } + public static int[] Toolbar = new int[] { + 16842927, + 16843072, + 2130903121, + 2130903167, + 2130903168, + 2130903185, + 2130903186, + 2130903187, + 2130903188, + 2130903189, + 2130903190, + 2130903331, + 2130903332, + 2130903336, + 2130903341, + 2130903342, + 2130903360, + 2130903411, + 2130903412, + 2130903413, + 2130903483, + 2130903485, + 2130903486, + 2130903487, + 2130903488, + 2130903489, + 2130903490, + 2130903491, + 2130903492}; + + // aapt resource value: 0 + public const int Toolbar_android_gravity = 0; + + // aapt resource value: 1 + public const int Toolbar_android_minHeight = 1; + + // aapt resource value: 2 + public const int Toolbar_buttonGravity = 2; + + // aapt resource value: 3 + public const int Toolbar_collapseContentDescription = 3; + + // aapt resource value: 4 + public const int Toolbar_collapseIcon = 4; + + // aapt resource value: 5 + public const int Toolbar_contentInsetEnd = 5; + + // aapt resource value: 6 + public const int Toolbar_contentInsetEndWithActions = 6; + + // aapt resource value: 7 + public const int Toolbar_contentInsetLeft = 7; + + // aapt resource value: 8 + public const int Toolbar_contentInsetRight = 8; + + // aapt resource value: 9 + public const int Toolbar_contentInsetStart = 9; + + // aapt resource value: 10 + public const int Toolbar_contentInsetStartWithNavigation = 10; + + // aapt resource value: 11 + public const int Toolbar_logo = 11; + + // aapt resource value: 12 + public const int Toolbar_logoDescription = 12; + + // aapt resource value: 13 + public const int Toolbar_maxButtonHeight = 13; + + // aapt resource value: 14 + public const int Toolbar_navigationContentDescription = 14; + + // aapt resource value: 15 + public const int Toolbar_navigationIcon = 15; + + // aapt resource value: 16 + public const int Toolbar_popupTheme = 16; + + // aapt resource value: 17 + public const int Toolbar_subtitle = 17; + + // aapt resource value: 18 + public const int Toolbar_subtitleTextAppearance = 18; + + // aapt resource value: 19 + public const int Toolbar_subtitleTextColor = 19; + + // aapt resource value: 20 + public const int Toolbar_title = 20; + + // aapt resource value: 21 + public const int Toolbar_titleMargin = 21; + + // aapt resource value: 22 + public const int Toolbar_titleMarginBottom = 22; + + // aapt resource value: 23 + public const int Toolbar_titleMarginEnd = 23; + + // aapt resource value: 26 + public const int Toolbar_titleMargins = 26; + + // aapt resource value: 24 + public const int Toolbar_titleMarginStart = 24; + + // aapt resource value: 25 + public const int Toolbar_titleMarginTop = 25; + + // aapt resource value: 27 + public const int Toolbar_titleTextAppearance = 27; + + // aapt resource value: 28 + public const int Toolbar_titleTextColor = 28; + + // aapt resource value: { 0x1010000,0x10100DA,0x7F030134,0x7F030135,0x7F0301B1 } + public static int[] View = new int[] { + 16842752, + 16842970, + 2130903348, + 2130903349, + 2130903473}; + + // aapt resource value: { 0x10100D4,0x7F030034,0x7F030035 } + public static int[] ViewBackgroundHelper = new int[] { + 16842964, + 2130903092, + 2130903093}; + + // aapt resource value: 0 + public const int ViewBackgroundHelper_android_background = 0; + + // aapt resource value: 1 + public const int ViewBackgroundHelper_backgroundTint = 1; + + // aapt resource value: 2 + public const int ViewBackgroundHelper_backgroundTintMode = 2; + + // aapt resource value: { 0x10100D0,0x10100F2,0x10100F3 } + public static int[] ViewStubCompat = new int[] { + 16842960, + 16842994, + 16842995}; + + // aapt resource value: 0 + public const int ViewStubCompat_android_id = 0; + + // aapt resource value: 2 + public const int ViewStubCompat_android_inflatedId = 2; + + // aapt resource value: 1 + public const int ViewStubCompat_android_layout = 1; + + // aapt resource value: 1 + public const int View_android_focusable = 1; + + // aapt resource value: 0 + public const int View_android_theme = 0; + + // aapt resource value: 2 + public const int View_paddingEnd = 2; + + // aapt resource value: 3 + public const int View_paddingStart = 3; + + // aapt resource value: 4 + public const int View_theme = 4; + + static Styleable() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Styleable() + { + } + } + + public partial class Xml + { + + // aapt resource value: 0x7F100000 + public const int xamarin_essentials_fileprovider_file_paths = 2131755008; + + static Xml() + { + global::Android.Runtime.ResourceIdManager.UpdateIdValues(); + } + + private Xml() + { + } + } + } +} +#pragma warning restore 1591 diff --git a/examples/csharp/HelloworldXamarin/HelloworldXamarin.iOS/AppDelegate.cs b/examples/csharp/HelloworldXamarin/HelloworldXamarin.iOS/AppDelegate.cs new file mode 100644 index 00000000..4adb6aeb --- /dev/null +++ b/examples/csharp/HelloworldXamarin/HelloworldXamarin.iOS/AppDelegate.cs @@ -0,0 +1,47 @@ +#region Copyright notice and license +// Copyright 2020 The gRPC Authors +// +// 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. +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; + +using Foundation; +using UIKit; + +namespace HelloworldXamarin.iOS +{ + // The UIApplicationDelegate for the application. This class is responsible for launching the + // User Interface of the application, as well as listening (and optionally responding) to + // application events from iOS. + [Register("AppDelegate")] + public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate + { + // + // This method is invoked when the application has loaded and is ready to run. In this + // method you should instantiate the window, load the UI into it and then make the window + // visible. + // + // You have 17 seconds to return from this method, or iOS will terminate your application. + // + public override bool FinishedLaunching(UIApplication app, NSDictionary options) + { + global::Xamarin.Forms.Forms.Init(); + LoadApplication(new App()); + + return base.FinishedLaunching(app, options); + } + } +} diff --git a/examples/csharp/HelloworldXamarin/HelloworldXamarin.iOS/Main.cs b/examples/csharp/HelloworldXamarin/HelloworldXamarin.iOS/Main.cs new file mode 100644 index 00000000..7e826fb8 --- /dev/null +++ b/examples/csharp/HelloworldXamarin/HelloworldXamarin.iOS/Main.cs @@ -0,0 +1,36 @@ +#region Copyright notice and license +// Copyright 2020 The gRPC Authors +// +// 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. +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; + +using Foundation; +using UIKit; + +namespace HelloworldXamarin.iOS +{ + public class Application + { + // This is the main entry point of the application. + static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, "AppDelegate"); + } + } +} diff --git a/examples/csharp/HelloworldXamarin/HelloworldXamarin.iOS/Properties/AssemblyInfo.cs b/examples/csharp/HelloworldXamarin/HelloworldXamarin.iOS/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..8cc293a2 --- /dev/null +++ b/examples/csharp/HelloworldXamarin/HelloworldXamarin.iOS/Properties/AssemblyInfo.cs @@ -0,0 +1,52 @@ +#region Copyright notice and license +// Copyright 2020 The gRPC Authors +// +// 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. +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("HelloworldXamarin.iOS")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("HelloworldXamarin.iOS")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("72bdc44f-c588-44f3-b6df-9aace7daafdd")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/examples/csharp/HelloworldXamarin/HelloworldXamarin/App.xaml.cs b/examples/csharp/HelloworldXamarin/HelloworldXamarin/App.xaml.cs new file mode 100644 index 00000000..9ae7a8cb --- /dev/null +++ b/examples/csharp/HelloworldXamarin/HelloworldXamarin/App.xaml.cs @@ -0,0 +1,44 @@ +#region Copyright notice and license +// Copyright 2020 The gRPC Authors +// +// 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. +#endregion + +using System; +using Xamarin.Forms; +using Xamarin.Forms.Xaml; + +namespace HelloworldXamarin +{ + public partial class App : Application + { + public App() + { + InitializeComponent(); + + MainPage = new MainPage(); + } + + protected override void OnStart() + { + } + + protected override void OnSleep() + { + } + + protected override void OnResume() + { + } + } +} diff --git a/examples/csharp/HelloworldXamarin/HelloworldXamarin/AssemblyInfo.cs b/examples/csharp/HelloworldXamarin/HelloworldXamarin/AssemblyInfo.cs new file mode 100644 index 00000000..aeb826cd --- /dev/null +++ b/examples/csharp/HelloworldXamarin/HelloworldXamarin/AssemblyInfo.cs @@ -0,0 +1,19 @@ +#region Copyright notice and license +// Copyright 2020 The gRPC Authors +// +// 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. +#endregion + +using Xamarin.Forms.Xaml; + +[assembly: XamlCompilation(XamlCompilationOptions.Compile)] diff --git a/examples/csharp/HelloworldXamarin/HelloworldXamarin/Helloworld.cs b/examples/csharp/HelloworldXamarin/HelloworldXamarin/Helloworld.cs new file mode 100644 index 00000000..ecfc8e13 --- /dev/null +++ b/examples/csharp/HelloworldXamarin/HelloworldXamarin/Helloworld.cs @@ -0,0 +1,286 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: helloworld.proto +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Helloworld { + + /// Holder for reflection information generated from helloworld.proto + public static partial class HelloworldReflection { + + #region Descriptor + /// File descriptor for helloworld.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static HelloworldReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChBoZWxsb3dvcmxkLnByb3RvEgpoZWxsb3dvcmxkIhwKDEhlbGxvUmVxdWVz", + "dBIMCgRuYW1lGAEgASgJIh0KCkhlbGxvUmVwbHkSDwoHbWVzc2FnZRgBIAEo", + "CTJJCgdHcmVldGVyEj4KCFNheUhlbGxvEhguaGVsbG93b3JsZC5IZWxsb1Jl", + "cXVlc3QaFi5oZWxsb3dvcmxkLkhlbGxvUmVwbHkiAEI2Chtpby5ncnBjLmV4", + "YW1wbGVzLmhlbGxvd29ybGRCD0hlbGxvV29ybGRQcm90b1ABogIDSExXYgZw", + "cm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloRequest), global::Helloworld.HelloRequest.Parser, new[]{ "Name" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloReply), global::Helloworld.HelloReply.Parser, new[]{ "Message" }, null, null, null) + })); + } + #endregion + + } + #region Messages + /// + /// The request message containing the user's name. + /// + public sealed partial class HelloRequest : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HelloRequest()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Helloworld.HelloworldReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloRequest(HelloRequest other) : this() { + name_ = other.name_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloRequest Clone() { + return new HelloRequest(this); + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 1; + private string name_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as HelloRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(HelloRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Name != other.Name) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Name.Length != 0) hash ^= Name.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(HelloRequest other) { + if (other == null) { + return; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + Name = input.ReadString(); + break; + } + } + } + } + + } + + /// + /// The response message containing the greetings + /// + public sealed partial class HelloReply : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HelloReply()); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Helloworld.HelloworldReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloReply() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloReply(HelloReply other) : this() { + message_ = other.message_; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public HelloReply Clone() { + return new HelloReply(this); + } + + /// Field number for the "message" field. + public const int MessageFieldNumber = 1; + private string message_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Message { + get { return message_; } + set { + message_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as HelloReply); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(HelloReply other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Message != other.Message) return false; + return true; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Message.Length != 0) hash ^= Message.GetHashCode(); + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + if (Message.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Message); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Message.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Message); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(HelloReply other) { + if (other == null) { + return; + } + if (other.Message.Length != 0) { + Message = other.Message; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + Message = input.ReadString(); + break; + } + } + } + } + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/examples/csharp/HelloworldXamarin/HelloworldXamarin/HelloworldGrpc.cs b/examples/csharp/HelloworldXamarin/HelloworldXamarin/HelloworldGrpc.cs new file mode 100644 index 00000000..c808884e --- /dev/null +++ b/examples/csharp/HelloworldXamarin/HelloworldXamarin/HelloworldGrpc.cs @@ -0,0 +1,150 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: helloworld.proto +// Original file comments: +// Copyright 2015 gRPC authors. +// +// 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. +// +#pragma warning disable 1591 +#region Designer generated code + +using System; +using System.Threading; +using System.Threading.Tasks; +using grpc = global::Grpc.Core; + +namespace Helloworld { + /// + /// The greeting service definition. + /// + public static partial class Greeter + { + static readonly string __ServiceName = "helloworld.Greeter"; + + static readonly grpc::Marshaller __Marshaller_HelloRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloRequest.Parser.ParseFrom); + static readonly grpc::Marshaller __Marshaller_HelloReply = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloReply.Parser.ParseFrom); + + static readonly grpc::Method __Method_SayHello = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "SayHello", + __Marshaller_HelloRequest, + __Marshaller_HelloReply); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Helloworld.HelloworldReflection.Descriptor.Services[0]; } + } + + /// Base class for server-side implementations of Greeter + public abstract partial class GreeterBase + { + /// + /// Sends a greeting + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + public virtual global::System.Threading.Tasks.Task SayHello(global::Helloworld.HelloRequest request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for Greeter + public partial class GreeterClient : grpc::ClientBase + { + /// Creates a new client for Greeter + /// The channel to use to make remote calls. + public GreeterClient(grpc::Channel channel) : base(channel) + { + } + /// Creates a new client for Greeter that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + public GreeterClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + protected GreeterClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + protected GreeterClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// Sends a greeting + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return SayHello(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Sends a greeting + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_SayHello, null, options, request); + } + /// + /// Sends a greeting + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + public virtual grpc::AsyncUnaryCall SayHelloAsync(global::Helloworld.HelloRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return SayHelloAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Sends a greeting + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + public virtual grpc::AsyncUnaryCall SayHelloAsync(global::Helloworld.HelloRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_SayHello, null, options, request); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + protected override GreeterClient NewInstance(ClientBaseConfiguration configuration) + { + return new GreeterClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + public static grpc::ServerServiceDefinition BindService(GreeterBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_SayHello, serviceImpl.SayHello).Build(); + } + + } +} +#endregion diff --git a/examples/csharp/HelloworldXamarin/HelloworldXamarin/MainPage.xaml.cs b/examples/csharp/HelloworldXamarin/HelloworldXamarin/MainPage.xaml.cs new file mode 100644 index 00000000..de4f63de --- /dev/null +++ b/examples/csharp/HelloworldXamarin/HelloworldXamarin/MainPage.xaml.cs @@ -0,0 +1,79 @@ +#region Copyright notice and license +// Copyright 2020 The gRPC Authors +// +// 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. +#endregion + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xamarin.Forms; +using Grpc.Core; +using Helloworld; + +namespace HelloworldXamarin +{ + public partial class MainPage : ContentPage + { + const int Port = 30051; + int count = 1; + + public MainPage() + { + InitializeComponent(); + } + + private void Button_Clicked(object sender, EventArgs e) + { + SayHello(sender as Button); + } + + private void SayHello(Button button) + { + Server server = new Server + { + Services = { Greeter.BindService(new GreeterImpl()) }, + Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } + }; + server.Start(); + + // use loopback on host machine: https://developer.android.com/studio/run/emulator-networking + // 10.0.2.2:30051 + Channel channel = new Channel("localhost:30051", ChannelCredentials.Insecure); + + var client = new Greeter.GreeterClient(channel); + string user = "Xamarin " + count; + + var reply = client.SayHello(new HelloRequest { Name = user }); + + button.Text = "Greeting: " + reply.Message; + + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + + count++; + } + + class GreeterImpl : Greeter.GreeterBase + { + // Server side handler of the SayHello RPC + public override Task SayHello(HelloRequest request, ServerCallContext context) + { + return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); + } + } + } +} diff --git a/examples/csharp/RouteGuide/RouteGuide/RouteGuideUtil.cs b/examples/csharp/RouteGuide/RouteGuide/RouteGuideUtil.cs new file mode 100644 index 00000000..29cd6b9b --- /dev/null +++ b/examples/csharp/RouteGuide/RouteGuide/RouteGuideUtil.cs @@ -0,0 +1,139 @@ +// Copyright 2015 gRPC authors. +// +// 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. + +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace Routeguide +{ + /// + /// Utility methods for the route guide example. + /// + public static class RouteGuideUtil + { + public const string DefaultFeaturesResourceName = "RouteGuide.route_guide_db.json"; + + private const double CoordFactor = 1e7; + + /// + /// Indicates whether the given feature exists (i.e. has a valid name). + /// + public static bool Exists(this Feature feature) + { + return feature != null && (feature.Name.Length != 0); + } + + public static double GetLatitude(this Point point) + { + return point.Latitude / CoordFactor; + } + + public static double GetLongitude(this Point point) + { + return point.Longitude / CoordFactor; + } + + /// + /// Calculate the distance between two points using the "haversine" formula. + /// The formula is based on http://mathforum.org/library/drmath/view/51879.html + /// + /// the starting point + /// the end point + /// the distance between the points in meters + public static double GetDistance(this Point start, Point end) + { + int r = 6371000; // earth radius in metres + double lat1 = ToRadians(start.GetLatitude()); + double lat2 = ToRadians(end.GetLatitude()); + double lon1 = ToRadians(start.GetLongitude()); + double lon2 = ToRadians(end.GetLongitude()); + double deltalat = lat2 - lat1; + double deltalon = lon2 - lon1; + + double a = Math.Sin(deltalat / 2) * Math.Sin(deltalat / 2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Sin(deltalon / 2) * Math.Sin(deltalon / 2); + double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); + return r * c; + } + + /// + /// Returns true if rectangular area contains given point. + /// + public static bool Contains(this Rectangle rectangle, Point point) + { + int left = Math.Min(rectangle.Lo.Longitude, rectangle.Hi.Longitude); + int right = Math.Max(rectangle.Lo.Longitude, rectangle.Hi.Longitude); + int top = Math.Max(rectangle.Lo.Latitude, rectangle.Hi.Latitude); + int bottom = Math.Min(rectangle.Lo.Latitude, rectangle.Hi.Latitude); + return (point.Longitude >= left && point.Longitude <= right && point.Latitude >= bottom && point.Latitude <= top); + } + + private static double ToRadians(double val) + { + return (Math.PI / 180) * val; + } + + /// + /// Parses features from an embedded resource. + /// + public static List LoadFeatures() + { + var features = new List(); + var jsonFeatures = JsonConvert.DeserializeObject>(ReadFeaturesFromResource()); + + foreach(var jsonFeature in jsonFeatures) + { + features.Add(new Feature + { + Name = jsonFeature.name, + Location = new Point { Longitude = jsonFeature.location.longitude, Latitude = jsonFeature.location.latitude} + }); + } + return features; + } + + private static string ReadFeaturesFromResource() + { + var stream = typeof(RouteGuideUtil).GetTypeInfo().Assembly.GetManifestResourceStream(DefaultFeaturesResourceName); + if (stream == null) + { + throw new IOException(string.Format("Error loading the embedded resource \"{0}\"", DefaultFeaturesResourceName)); + } + using (var streamReader = new StreamReader(stream)) + { + return streamReader.ReadToEnd(); + } + } + +#pragma warning disable 0649 // Suppresses "Field 'x' is never assigned to". + private class JsonFeature + { + public string name; + public JsonLocation location; + } + + private class JsonLocation + { + public int longitude; + public int latitude; + } +#pragma warning restore 0649 + } +} diff --git a/examples/csharp/RouteGuide/RouteGuideClient/Program.cs b/examples/csharp/RouteGuide/RouteGuideClient/Program.cs new file mode 100644 index 00000000..4c718a53 --- /dev/null +++ b/examples/csharp/RouteGuide/RouteGuideClient/Program.cs @@ -0,0 +1,241 @@ +// Copyright 2015 gRPC authors. +// +// 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. + +using Grpc.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Routeguide +{ + class Program + { + /// + /// Sample client code that makes gRPC calls to the server. + /// + public class RouteGuideClient + { + readonly RouteGuide.RouteGuideClient client; + + public RouteGuideClient(RouteGuide.RouteGuideClient client) + { + this.client = client; + } + + /// + /// Blocking unary call example. Calls GetFeature and prints the response. + /// + public void GetFeature(int lat, int lon) + { + try + { + Log("*** GetFeature: lat={0} lon={1}", lat, lon); + + Point request = new Point { Latitude = lat, Longitude = lon }; + + Feature feature = client.GetFeature(request); + if (feature.Exists()) + { + Log("Found feature called \"{0}\" at {1}, {2}", + feature.Name, feature.Location.GetLatitude(), feature.Location.GetLongitude()); + } + else + { + Log("Found no feature at {0}, {1}", + feature.Location.GetLatitude(), feature.Location.GetLongitude()); + } + } + catch (RpcException e) + { + Log("RPC failed " + e); + throw; + } + } + + + /// + /// Server-streaming example. Calls listFeatures with a rectangle of interest. Prints each response feature as it arrives. + /// + public async Task ListFeatures(int lowLat, int lowLon, int hiLat, int hiLon) + { + try + { + Log("*** ListFeatures: lowLat={0} lowLon={1} hiLat={2} hiLon={3}", lowLat, lowLon, hiLat, + hiLon); + + Rectangle request = new Rectangle + { + Lo = new Point { Latitude = lowLat, Longitude = lowLon }, + Hi = new Point { Latitude = hiLat, Longitude = hiLon } + }; + + using (var call = client.ListFeatures(request)) + { + var responseStream = call.ResponseStream; + StringBuilder responseLog = new StringBuilder("Result: "); + + while (await responseStream.MoveNext()) + { + Feature feature = responseStream.Current; + responseLog.Append(feature.ToString()); + } + Log(responseLog.ToString()); + } + } + catch (RpcException e) + { + Log("RPC failed " + e); + throw; + } + } + + /// + /// Client-streaming example. Sends numPoints randomly chosen points from features + /// with a variable delay in between. Prints the statistics when they are sent from the server. + /// + public async Task RecordRoute(List features, int numPoints) + { + try + { + Log("*** RecordRoute"); + using (var call = client.RecordRoute()) + { + // Send numPoints points randomly selected from the features list. + StringBuilder numMsg = new StringBuilder(); + Random rand = new Random(); + for (int i = 0; i < numPoints; ++i) + { + int index = rand.Next(features.Count); + Point point = features[index].Location; + Log("Visiting point {0}, {1}", point.GetLatitude(), point.GetLongitude()); + + await call.RequestStream.WriteAsync(point); + + // A bit of delay before sending the next one. + await Task.Delay(rand.Next(1000) + 500); + } + await call.RequestStream.CompleteAsync(); + + RouteSummary summary = await call.ResponseAsync; + Log("Finished trip with {0} points. Passed {1} features. " + + "Travelled {2} meters. It took {3} seconds.", summary.PointCount, + summary.FeatureCount, summary.Distance, summary.ElapsedTime); + + Log("Finished RecordRoute"); + } + } + catch (RpcException e) + { + Log("RPC failed", e); + throw; + } + } + + /// + /// Bi-directional streaming example. Send some chat messages, and print any + /// chat messages that are sent from the server. + /// + public async Task RouteChat() + { + try + { + Log("*** RouteChat"); + var requests = new List + { + NewNote("First message", 0, 0), + NewNote("Second message", 0, 1), + NewNote("Third message", 1, 0), + NewNote("Fourth message", 0, 0) + }; + + using (var call = client.RouteChat()) + { + var responseReaderTask = Task.Run(async () => + { + while (await call.ResponseStream.MoveNext()) + { + var note = call.ResponseStream.Current; + Log("Got message \"{0}\" at {1}, {2}", note.Message, + note.Location.Latitude, note.Location.Longitude); + } + }); + + foreach (RouteNote request in requests) + { + Log("Sending message \"{0}\" at {1}, {2}", request.Message, + request.Location.Latitude, request.Location.Longitude); + + await call.RequestStream.WriteAsync(request); + } + await call.RequestStream.CompleteAsync(); + await responseReaderTask; + + Log("Finished RouteChat"); + } + } + catch (RpcException e) + { + Log("RPC failed", e); + throw; + } + } + + private void Log(string s, params object[] args) + { + Console.WriteLine(string.Format(s, args)); + } + + private void Log(string s) + { + Console.WriteLine(s); + } + + private RouteNote NewNote(string message, int lat, int lon) + { + return new RouteNote + { + Message = message, + Location = new Point { Latitude = lat, Longitude = lon } + }; + } + } + + static void Main(string[] args) + { + var channel = new Channel("127.0.0.1:30052", ChannelCredentials.Insecure); + var client = new RouteGuideClient(new RouteGuide.RouteGuideClient(channel)); + + // Looking for a valid feature + client.GetFeature(409146138, -746188906); + + // Feature missing. + client.GetFeature(0, 0); + + // Looking for features between 40, -75 and 42, -73. + client.ListFeatures(400000000, -750000000, 420000000, -730000000).Wait(); + + // Record a few randomly selected points from the features file. + client.RecordRoute(RouteGuideUtil.LoadFeatures(), 10).Wait(); + + // Send and receive some notes. + client.RouteChat().Wait(); + + channel.ShutdownAsync().Wait(); + Console.WriteLine("Press any key to exit..."); + Console.ReadKey(); + } + } +} diff --git a/examples/csharp/RouteGuide/RouteGuideServer/Program.cs b/examples/csharp/RouteGuide/RouteGuideServer/Program.cs new file mode 100644 index 00000000..dff6486e --- /dev/null +++ b/examples/csharp/RouteGuide/RouteGuideServer/Program.cs @@ -0,0 +1,46 @@ +// Copyright 2015 gRPC authors. +// +// 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. + +using Grpc.Core; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Routeguide +{ + class Program + { + static void Main(string[] args) + { + const int Port = 30052; + + var features = RouteGuideUtil.LoadFeatures(); + + Server server = new Server + { + Services = { RouteGuide.BindService(new RouteGuideImpl(features)) }, + Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) } + }; + server.Start(); + + Console.WriteLine("RouteGuide server listening on port " + Port); + Console.WriteLine("Press any key to stop the server..."); + Console.ReadKey(); + + server.ShutdownAsync().Wait(); + } + } +} diff --git a/examples/csharp/RouteGuide/RouteGuideServer/RouteGuideImpl.cs b/examples/csharp/RouteGuide/RouteGuideServer/RouteGuideImpl.cs new file mode 100644 index 00000000..f157ca08 --- /dev/null +++ b/examples/csharp/RouteGuide/RouteGuideServer/RouteGuideImpl.cs @@ -0,0 +1,153 @@ +// Copyright 2015 gRPC authors. +// +// 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. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Core.Utils; + +namespace Routeguide +{ + /// + /// Example implementation of RouteGuide server. + /// + public class RouteGuideImpl : RouteGuide.RouteGuideBase + { + readonly List features; + readonly object myLock = new object(); + readonly Dictionary> routeNotes = new Dictionary>(); + + public RouteGuideImpl(List features) + { + this.features = features; + } + + /// + /// Gets the feature at the requested point. If no feature at that location + /// exists, an unnammed feature is returned at the provided location. + /// + public override Task GetFeature(Point request, ServerCallContext context) + { + return Task.FromResult(CheckFeature(request)); + } + + /// + /// Gets all features contained within the given bounding rectangle. + /// + public override async Task ListFeatures(Rectangle request, IServerStreamWriter responseStream, ServerCallContext context) + { + var responses = features.FindAll( (feature) => feature.Exists() && request.Contains(feature.Location) ); + foreach (var response in responses) + { + await responseStream.WriteAsync(response); + } + } + + /// + /// Gets a stream of points, and responds with statistics about the "trip": number of points, + /// number of known features visited, total distance traveled, and total time spent. + /// + public override async Task RecordRoute(IAsyncStreamReader requestStream, ServerCallContext context) + { + int pointCount = 0; + int featureCount = 0; + int distance = 0; + Point previous = null; + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + while (await requestStream.MoveNext()) + { + var point = requestStream.Current; + pointCount++; + if (CheckFeature(point).Exists()) + { + featureCount++; + } + if (previous != null) + { + distance += (int) previous.GetDistance(point); + } + previous = point; + } + + stopwatch.Stop(); + + return new RouteSummary + { + PointCount = pointCount, + FeatureCount = featureCount, + Distance = distance, + ElapsedTime = (int)(stopwatch.ElapsedMilliseconds / 1000) + }; + } + + /// + /// Receives a stream of message/location pairs, and responds with a stream of all previous + /// messages at each of those locations. + /// + public override async Task RouteChat(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + { + while (await requestStream.MoveNext()) + { + var note = requestStream.Current; + List prevNotes = AddNoteForLocation(note.Location, note); + foreach (var prevNote in prevNotes) + { + await responseStream.WriteAsync(prevNote); + } + } + } + + /// + /// Adds a note for location and returns a list of pre-existing notes for that location (not containing the newly added note). + /// + private List AddNoteForLocation(Point location, RouteNote note) + { + lock (myLock) + { + List notes; + if (!routeNotes.TryGetValue(location, out notes)) { + notes = new List(); + routeNotes.Add(location, notes); + } + var preexistingNotes = new List(notes); + notes.Add(note); + return preexistingNotes; + } + } + + /// + /// Gets the feature at the given point. + /// + /// the location to check + /// The feature object at the point Note that an empty name indicates no feature. + private Feature CheckFeature(Point location) + { + var result = features.FirstOrDefault((feature) => feature.Location.Equals(location)); + if (result == null) + { + // No feature was found, return an unnamed feature. + return new Feature { Name = "", Location = location }; + } + return result; + } + } +} diff --git a/examples/csharp/Xds/GreeterClient/Program.cs b/examples/csharp/Xds/GreeterClient/Program.cs new file mode 100644 index 00000000..7d1286ab --- /dev/null +++ b/examples/csharp/Xds/GreeterClient/Program.cs @@ -0,0 +1,51 @@ +// Copyright 2015 gRPC authors. +// +// 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. + +using System; +using Grpc.Core; +using Helloworld; +using CommandLine; + +namespace GreeterClient +{ + class Program + { + private class Options + { + [Option("server", Default = "localhost:30051", HelpText = "The address of the server")] + public string Server { get; set; } + } + + public static void Main(string[] args) + { + Parser.Default.ParseArguments(args) + .WithParsed(options => RunClient(options)); + } + + private static void RunClient(Options options) + { + Channel channel = new Channel(options.Server, ChannelCredentials.Insecure); + + var client = new Greeter.GreeterClient(channel); + String user = "you"; + + var reply = client.SayHello(new HelloRequest { Name = user }); + Console.WriteLine("Greeter client received: " + reply.Message); + + channel.ShutdownAsync().Wait(); + Console.WriteLine("Press any key to exit..."); + Console.ReadKey(); + } + } +} diff --git a/examples/csharp/Xds/GreeterServer/Program.cs b/examples/csharp/Xds/GreeterServer/Program.cs new file mode 100644 index 00000000..5ef9b64e --- /dev/null +++ b/examples/csharp/Xds/GreeterServer/Program.cs @@ -0,0 +1,93 @@ +// Copyright 2020 The gRPC Authors +// +// 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. + +using System; +using System.Net; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.HealthCheck; +using Helloworld; +using Grpc.Health; +using Grpc.Health.V1; +using Grpc.Reflection; +using Grpc.Reflection.V1Alpha; +using CommandLine; + +namespace GreeterServer +{ + class GreeterImpl : Greeter.GreeterBase + { + private string hostname; + + public GreeterImpl(string hostname) + { + this.hostname = hostname; + } + + // Server side handler of the SayHello RPC + public override Task SayHello(HelloRequest request, ServerCallContext context) + { + return Task.FromResult(new HelloReply { Message = $"Hello {request.Name} from {hostname}!"}); + } + } + + class Program + { + class Options + { + [Option("port", Default = 30051, HelpText = "The port to listen on.")] + public int Port { get; set; } + + [Option("hostname", Required = false, HelpText = "The name clients will see in responses. If not specified, machine's hostname will obtain automatically.")] + public string Hostname { get; set; } + } + + public static void Main(string[] args) + { + Parser.Default.ParseArguments(args) + .WithParsed(options => RunServer(options)); + } + + private static void RunServer(Options options) + { + var hostName = options.Hostname ?? Dns.GetHostName(); + + var serviceDescriptors = new [] {Greeter.Descriptor, Health.Descriptor, ServerReflection.Descriptor}; + var greeterImpl = new GreeterImpl(hostName); + var healthServiceImpl = new HealthServiceImpl(); + var reflectionImpl = new ReflectionServiceImpl(serviceDescriptors); + + Server server = new Server + { + Services = { Greeter.BindService(greeterImpl), Health.BindService(healthServiceImpl), ServerReflection.BindService(reflectionImpl) }, + Ports = { new ServerPort("[::]", options.Port, ServerCredentials.Insecure) } + }; + server.Start(); + + // Mark all services as healthy. + foreach (var serviceDescriptor in serviceDescriptors) + { + healthServiceImpl.SetStatus(serviceDescriptor.FullName, HealthCheckResponse.Types.ServingStatus.Serving); + } + // Mark overall server status as healthy. + healthServiceImpl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving); + + Console.WriteLine("Greeter server listening on port " + options.Port); + Console.WriteLine("Press any key to stop the server..."); + Console.ReadKey(); + + server.ShutdownAsync().Wait(); + } + } +} diff --git a/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs b/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs new file mode 100644 index 00000000..89b7aa70 --- /dev/null +++ b/src/csharp/Grpc.Auth/GoogleAuthInterceptors.cs @@ -0,0 +1,111 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Threading; +using System.Threading.Tasks; + +using Google.Apis.Auth.OAuth2; +using Grpc.Core; +using Grpc.Core.Utils; + +namespace Grpc.Auth +{ + /// + /// Factory methods to create authorization interceptors for Google credentials. + /// + /// + public static class GoogleAuthInterceptors + { + private const string AuthorizationHeader = "Authorization"; + private const string Schema = "Bearer"; + + /// + /// Creates an that will obtain access token from any credential type that implements + /// ITokenAccess. (e.g. GoogleCredential). + /// + /// The credential to use to obtain access tokens. + /// The interceptor. + public static AsyncAuthInterceptor FromCredential(ITokenAccess credential) + { + if (credential is ITokenAccessWithHeaders credentialWithHeaders) + { + return FromCredential(credentialWithHeaders); + } + + return new AsyncAuthInterceptor(async (context, metadata) => + { + var accessToken = await credential.GetAccessTokenForRequestAsync(context.ServiceUrl, CancellationToken.None).ConfigureAwait(false); + metadata.Add(CreateBearerTokenHeader(accessToken)); + }); + } + + /// + /// Creates an that will obtain access token and associated information + /// from any credential type that implements + /// + /// The credential to use to obtain access tokens. + /// The interceptor. + public static AsyncAuthInterceptor FromCredential(ITokenAccessWithHeaders credential) + { + return new AsyncAuthInterceptor(async (context, metadata) => + { + AccessTokenWithHeaders tokenAndHeaders = await credential.GetAccessTokenWithHeadersForRequestAsync(context.ServiceUrl, CancellationToken.None).ConfigureAwait(false); + metadata.Add(CreateBearerTokenHeader(tokenAndHeaders.AccessToken)); + foreach (var header in tokenAndHeaders.Headers) + { + foreach (var headerValue in header.Value) + { + metadata.Add(new Metadata.Entry(header.Key, headerValue)); + } + } + }); + } + + /// + /// Creates an that will use given access token as authorization. + /// + /// OAuth2 access token. + /// The interceptor. + public static AsyncAuthInterceptor FromAccessToken(string accessToken) + { + GrpcPreconditions.CheckNotNull(accessToken); + return new AsyncAuthInterceptor((context, metadata) => + { + metadata.Add(CreateBearerTokenHeader(accessToken)); + return GetCompletedTask(); + }); + } + + private static Metadata.Entry CreateBearerTokenHeader(string accessToken) + { + return new Metadata.Entry(AuthorizationHeader, Schema + " " + accessToken); + } + + /// + /// Framework independent equivalent of Task.CompletedTask. + /// + private static Task GetCompletedTask() + { +#if NETSTANDARD + return Task.CompletedTask; +#else + return Task.FromResult(null); // for .NET45, emulate the functionality +#endif + } + } +} diff --git a/src/csharp/Grpc.Auth/GoogleGrpcCredentials.cs b/src/csharp/Grpc.Auth/GoogleGrpcCredentials.cs new file mode 100644 index 00000000..a979b0d8 --- /dev/null +++ b/src/csharp/Grpc.Auth/GoogleGrpcCredentials.cs @@ -0,0 +1,81 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading; +using System.Threading.Tasks; + +using Google.Apis.Auth.OAuth2; +using Grpc.Core; +using Grpc.Core.Utils; + +namespace Grpc.Auth +{ + /// + /// Factory/extension methods to create instances of and classes + /// based on credential objects originating from Google auth library. + /// + public static class GoogleGrpcCredentials + { + /// + /// Retrieves an instance of Google's Application Default Credentials using + /// GoogleCredential.GetApplicationDefaultAsync() and converts them + /// into a gRPC that use the default SSL credentials. + /// + /// The ChannelCredentials instance. + public static async Task GetApplicationDefaultAsync() + { + var googleCredential = await GoogleCredential.GetApplicationDefaultAsync().ConfigureAwait(false); + return googleCredential.ToChannelCredentials(); + } + + /// + /// Creates an instance of that will use given access token to authenticate + /// with a gRPC service. + /// + /// OAuth2 access token. + /// /// The MetadataCredentials instance. + public static CallCredentials FromAccessToken(string accessToken) + { + return CallCredentials.FromInterceptor(GoogleAuthInterceptors.FromAccessToken(accessToken)); + } + + /// + /// Converts a ITokenAccess (e.g. GoogleCredential) object + /// into a gRPC object. + /// + /// The credential to use to obtain access tokens. + /// The CallCredentials instance. + public static CallCredentials ToCallCredentials(this ITokenAccess credential) + { + return CallCredentials.FromInterceptor(GoogleAuthInterceptors.FromCredential(credential)); + } + + /// + /// Converts a ITokenAccess (e.g. GoogleCredential) object + /// into a gRPC object. + /// Default SSL credentials are used. + /// + /// The credential to use to obtain access tokens. + /// >The ChannelCredentials instance. + public static ChannelCredentials ToChannelCredentials(this ITokenAccess googleCredential) + { + return ChannelCredentials.Create(new SslCredentials(), googleCredential.ToCallCredentials()); + } + } +} diff --git a/src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..4f433a30 --- /dev/null +++ b/src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.Auth")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.Core.Api/AsyncAuthInterceptor.cs b/src/csharp/Grpc.Core.Api/AsyncAuthInterceptor.cs new file mode 100644 index 00000000..caa3a6be --- /dev/null +++ b/src/csharp/Grpc.Core.Api/AsyncAuthInterceptor.cs @@ -0,0 +1,69 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Asynchronous authentication interceptor for . + /// + /// The interceptor context. + /// Metadata to populate with entries that will be added to outgoing call's headers. + /// + public delegate Task AsyncAuthInterceptor(AuthInterceptorContext context, Metadata metadata); + + /// + /// Context for an RPC being intercepted by . + /// + public class AuthInterceptorContext + { + readonly string serviceUrl; + readonly string methodName; + + /// + /// Initializes a new instance of AuthInterceptorContext. + /// + public AuthInterceptorContext(string serviceUrl, string methodName) + { + this.serviceUrl = GrpcPreconditions.CheckNotNull(serviceUrl); + this.methodName = GrpcPreconditions.CheckNotNull(methodName); + } + + /// + /// The fully qualified service URL for the RPC being called. + /// + public string ServiceUrl + { + get { return serviceUrl; } + } + + /// + /// The method name of the RPC being called. + /// + public string MethodName + { + get { return methodName; } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/AsyncCallState.cs b/src/csharp/Grpc.Core.Api/AsyncCallState.cs new file mode 100644 index 00000000..02e2e2cc --- /dev/null +++ b/src/csharp/Grpc.Core.Api/AsyncCallState.cs @@ -0,0 +1,98 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + + +using System; +using System.Threading.Tasks; + +namespace Grpc.Core +{ + /// + /// Provides an abstraction over the callback providers + /// used by AsyncUnaryCall, AsyncDuplexStreamingCall, etc + /// + internal struct AsyncCallState + { + readonly object responseHeadersAsync; // Task or Func> + readonly object getStatusFunc; // Func or Func + readonly object getTrailersFunc; // Func or Func + readonly object disposeAction; // Action or Action + readonly object callbackState; // arg0 for the callbacks above, if needed + + internal AsyncCallState( + Func> responseHeadersAsync, + Func getStatusFunc, + Func getTrailersFunc, + Action disposeAction, + object callbackState) + { + this.responseHeadersAsync = responseHeadersAsync; + this.getStatusFunc = getStatusFunc; + this.getTrailersFunc = getTrailersFunc; + this.disposeAction = disposeAction; + this.callbackState = callbackState; + } + + internal AsyncCallState( + Task responseHeadersAsync, + Func getStatusFunc, + Func getTrailersFunc, + Action disposeAction) + { + this.responseHeadersAsync = responseHeadersAsync; + this.getStatusFunc = getStatusFunc; + this.getTrailersFunc = getTrailersFunc; + this.disposeAction = disposeAction; + this.callbackState = null; + } + + internal Task ResponseHeadersAsync() + { + var withState = responseHeadersAsync as Func>; + return withState != null ? withState(callbackState) + : (Task)responseHeadersAsync; + } + + internal Status GetStatus() + { + var withState = getStatusFunc as Func; + return withState != null ? withState(callbackState) + : ((Func)getStatusFunc)(); + } + + internal Metadata GetTrailers() + { + var withState = getTrailersFunc as Func; + return withState != null ? withState(callbackState) + : ((Func)getTrailersFunc)(); + } + + internal void Dispose() + { + var withState = disposeAction as Action; + if (withState != null) + { + withState(callbackState); + } + else + { + ((Action)disposeAction)(); + } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/AsyncClientStreamingCall.cs b/src/csharp/Grpc.Core.Api/AsyncClientStreamingCall.cs new file mode 100644 index 00000000..bc63d8a0 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/AsyncClientStreamingCall.cs @@ -0,0 +1,155 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +namespace Grpc.Core +{ + /// + /// Return type for client streaming calls. + /// + /// Request message type for this call. + /// Response message type for this call. + public sealed class AsyncClientStreamingCall : IDisposable + { + readonly IClientStreamWriter requestStream; + readonly Task responseAsync; + readonly AsyncCallState callState; + + /// + /// Creates a new AsyncClientStreamingCall object with the specified properties. + /// + /// Stream of request values. + /// The response of the asynchronous call. + /// Response headers of the asynchronous call. + /// Delegate returning the status of the call. + /// Delegate returning the trailing metadata of the call. + /// Delegate to invoke when Dispose is called on the call object. + public AsyncClientStreamingCall(IClientStreamWriter requestStream, + Task responseAsync, + Task responseHeadersAsync, + Func getStatusFunc, + Func getTrailersFunc, + Action disposeAction) + { + this.requestStream = requestStream; + this.responseAsync = responseAsync; + this.callState = new AsyncCallState(responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction); + } + + /// + /// Creates a new AsyncClientStreamingCall object with the specified properties. + /// + /// Stream of request values. + /// The response of the asynchronous call. + /// Response headers of the asynchronous call. + /// Delegate returning the status of the call. + /// Delegate returning the trailing metadata of the call. + /// Delegate to invoke when Dispose is called on the call object. + /// State object for use with the callback parameters. + public AsyncClientStreamingCall(IClientStreamWriter requestStream, + Task responseAsync, + Func> responseHeadersAsync, + Func getStatusFunc, + Func getTrailersFunc, + Action disposeAction, + object state) + { + this.requestStream = requestStream; + this.responseAsync = responseAsync; + this.callState = new AsyncCallState(responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction, state); + } + + /// + /// Asynchronous call result. + /// + public Task ResponseAsync + { + get + { + return this.responseAsync; + } + } + + /// + /// Asynchronous access to response headers. + /// + public Task ResponseHeadersAsync + { + get + { + return callState.ResponseHeadersAsync(); + } + } + + /// + /// Async stream to send streaming requests. + /// + public IClientStreamWriter RequestStream + { + get + { + return requestStream; + } + } + + /// + /// Allows awaiting this object directly. + /// + /// + public TaskAwaiter GetAwaiter() + { + return responseAsync.GetAwaiter(); + } + + /// + /// Gets the call status if the call has already finished. + /// Throws InvalidOperationException otherwise. + /// + public Status GetStatus() + { + return callState.GetStatus(); + } + + /// + /// Gets the call trailing metadata if the call has already finished. + /// Throws InvalidOperationException otherwise. + /// + public Metadata GetTrailers() + { + return callState.GetTrailers(); + } + + /// + /// Provides means to cleanup after the call. + /// If the call has already finished normally (request stream has been completed and call result has been received), doesn't do anything. + /// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call. + /// As a result, all resources being used by the call should be released eventually. + /// + /// + /// Normally, there is no need for you to dispose the call unless you want to utilize the + /// "Cancel" semantics of invoking Dispose. + /// + public void Dispose() + { + callState.Dispose(); + } + } +} diff --git a/src/csharp/Grpc.Core.Api/AsyncDuplexStreamingCall.cs b/src/csharp/Grpc.Core.Api/AsyncDuplexStreamingCall.cs new file mode 100644 index 00000000..99660ab7 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/AsyncDuplexStreamingCall.cs @@ -0,0 +1,145 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading.Tasks; + +namespace Grpc.Core +{ + /// + /// Return type for bidirectional streaming calls. + /// + /// Request message type for this call. + /// Response message type for this call. + public sealed class AsyncDuplexStreamingCall : IDisposable + { + readonly IClientStreamWriter requestStream; + readonly IAsyncStreamReader responseStream; + readonly AsyncCallState callState; + + /// + /// Creates a new AsyncDuplexStreamingCall object with the specified properties. + /// + /// Stream of request values. + /// Stream of response values. + /// Response headers of the asynchronous call. + /// Delegate returning the status of the call. + /// Delegate returning the trailing metadata of the call. + /// Delegate to invoke when Dispose is called on the call object. + public AsyncDuplexStreamingCall(IClientStreamWriter requestStream, + IAsyncStreamReader responseStream, + Task responseHeadersAsync, + Func getStatusFunc, + Func getTrailersFunc, + Action disposeAction) + { + this.requestStream = requestStream; + this.responseStream = responseStream; + this.callState = new AsyncCallState(responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction); + } + + /// + /// Creates a new AsyncDuplexStreamingCall object with the specified properties. + /// + /// Stream of request values. + /// Stream of response values. + /// Response headers of the asynchronous call. + /// Delegate returning the status of the call. + /// Delegate returning the trailing metadata of the call. + /// Delegate to invoke when Dispose is called on the call object. + /// State object for use with the callback parameters. + public AsyncDuplexStreamingCall(IClientStreamWriter requestStream, + IAsyncStreamReader responseStream, + Func> responseHeadersAsync, + Func getStatusFunc, + Func getTrailersFunc, + Action disposeAction, + object state) + { + this.requestStream = requestStream; + this.responseStream = responseStream; + this.callState = new AsyncCallState(responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction, state); + } + + /// + /// Async stream to read streaming responses. + /// + public IAsyncStreamReader ResponseStream + { + get + { + return responseStream; + } + } + + /// + /// Async stream to send streaming requests. + /// + public IClientStreamWriter RequestStream + { + get + { + return requestStream; + } + } + + /// + /// Asynchronous access to response headers. + /// + public Task ResponseHeadersAsync + { + get + { + return callState.ResponseHeadersAsync(); + } + } + + /// + /// Gets the call status if the call has already finished. + /// Throws InvalidOperationException otherwise. + /// + public Status GetStatus() + { + return callState.GetStatus(); + } + + /// + /// Gets the call trailing metadata if the call has already finished. + /// Throws InvalidOperationException otherwise. + /// + public Metadata GetTrailers() + { + return callState.GetTrailers(); + } + + /// + /// Provides means to cleanup after the call. + /// If the call has already finished normally (request stream has been completed and response stream has been fully read), doesn't do anything. + /// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call. + /// As a result, all resources being used by the call should be released eventually. + /// + /// + /// Normally, there is no need for you to dispose the call unless you want to utilize the + /// "Cancel" semantics of invoking Dispose. + /// + public void Dispose() + { + callState.Dispose(); + } + } +} diff --git a/src/csharp/Grpc.Core.Api/AsyncServerStreamingCall.cs b/src/csharp/Grpc.Core.Api/AsyncServerStreamingCall.cs new file mode 100644 index 00000000..360482d9 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/AsyncServerStreamingCall.cs @@ -0,0 +1,126 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading.Tasks; + +namespace Grpc.Core +{ + /// + /// Return type for server streaming calls. + /// + /// Response message type for this call. + public sealed class AsyncServerStreamingCall : IDisposable + { + readonly IAsyncStreamReader responseStream; + readonly AsyncCallState callState; + + /// + /// Creates a new AsyncDuplexStreamingCall object with the specified properties. + /// + /// Stream of response values. + /// Response headers of the asynchronous call. + /// Delegate returning the status of the call. + /// Delegate returning the trailing metadata of the call. + /// Delegate to invoke when Dispose is called on the call object. + public AsyncServerStreamingCall(IAsyncStreamReader responseStream, + Task responseHeadersAsync, + Func getStatusFunc, + Func getTrailersFunc, + Action disposeAction) + { + this.responseStream = responseStream; + this.callState = new AsyncCallState(responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction); + } + + /// + /// Creates a new AsyncDuplexStreamingCall object with the specified properties. + /// + /// Stream of response values. + /// Response headers of the asynchronous call. + /// Delegate returning the status of the call. + /// Delegate returning the trailing metadata of the call. + /// Delegate to invoke when Dispose is called on the call object. + /// State object for use with the callback parameters. + public AsyncServerStreamingCall(IAsyncStreamReader responseStream, + Func> responseHeadersAsync, + Func getStatusFunc, + Func getTrailersFunc, + Action disposeAction, + object state) + { + this.responseStream = responseStream; + this.callState = new AsyncCallState(responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction, state); + } + + /// + /// Async stream to read streaming responses. + /// + public IAsyncStreamReader ResponseStream + { + get + { + return responseStream; + } + } + + /// + /// Asynchronous access to response headers. + /// + public Task ResponseHeadersAsync + { + get + { + return callState.ResponseHeadersAsync(); + } + } + + /// + /// Gets the call status if the call has already finished. + /// Throws InvalidOperationException otherwise. + /// + public Status GetStatus() + { + return callState.GetStatus(); + } + + /// + /// Gets the call trailing metadata if the call has already finished. + /// Throws InvalidOperationException otherwise. + /// + public Metadata GetTrailers() + { + return callState.GetTrailers(); + } + + /// + /// Provides means to cleanup after the call. + /// If the call has already finished normally (response stream has been fully read), doesn't do anything. + /// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call. + /// As a result, all resources being used by the call should be released eventually. + /// + /// + /// Normally, there is no need for you to dispose the call unless you want to utilize the + /// "Cancel" semantics of invoking Dispose. + /// + public void Dispose() + { + callState.Dispose(); + } + } +} diff --git a/src/csharp/Grpc.Core.Api/AsyncStreamReaderExtensions.cs b/src/csharp/Grpc.Core.Api/AsyncStreamReaderExtensions.cs new file mode 100644 index 00000000..a1f89572 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/AsyncStreamReaderExtensions.cs @@ -0,0 +1,50 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Grpc.Core +{ + /// + /// Extension methods for . + /// + public static class AsyncStreamReaderExtensions + { + /// + /// Advances the stream reader to the next element in the sequence, returning the result asynchronously. + /// + /// The message type. + /// The stream reader. + /// + /// Task containing the result of the operation: true if the reader was successfully advanced + /// to the next element; false if the reader has passed the end of the sequence. + /// + public static Task MoveNext(this IAsyncStreamReader streamReader) + where T : class + { + if (streamReader == null) + { + throw new ArgumentNullException(nameof(streamReader)); + } + + return streamReader.MoveNext(CancellationToken.None); + } + } +} diff --git a/src/csharp/Grpc.Core.Api/AsyncUnaryCall.cs b/src/csharp/Grpc.Core.Api/AsyncUnaryCall.cs new file mode 100644 index 00000000..13e2e3b1 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/AsyncUnaryCall.cs @@ -0,0 +1,136 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; + +namespace Grpc.Core +{ + /// + /// Return type for single request - single response call. + /// + /// Response message type for this call. + public sealed class AsyncUnaryCall : IDisposable + { + readonly Task responseAsync; + readonly AsyncCallState callState; + + + /// + /// Creates a new AsyncUnaryCall object with the specified properties. + /// + /// The response of the asynchronous call. + /// Response headers of the asynchronous call. + /// Delegate returning the status of the call. + /// Delegate returning the trailing metadata of the call. + /// Delegate to invoke when Dispose is called on the call object. + public AsyncUnaryCall(Task responseAsync, + Task responseHeadersAsync, + Func getStatusFunc, + Func getTrailersFunc, + Action disposeAction) + { + this.responseAsync = responseAsync; + this.callState = new AsyncCallState(responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction); + } + + /// + /// Creates a new AsyncUnaryCall object with the specified properties. + /// + /// The response of the asynchronous call. + /// Response headers of the asynchronous call. + /// Delegate returning the status of the call. + /// Delegate returning the trailing metadata of the call. + /// Delegate to invoke when Dispose is called on the call object. + /// State object for use with the callback parameters. + public AsyncUnaryCall(Task responseAsync, + Func> responseHeadersAsync, + Func getStatusFunc, + Func getTrailersFunc, + Action disposeAction, + object state) + { + this.responseAsync = responseAsync; + callState = new AsyncCallState(responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction, state); + } + + /// + /// Asynchronous call result. + /// + public Task ResponseAsync + { + get + { + return this.responseAsync; + } + } + + /// + /// Asynchronous access to response headers. + /// + public Task ResponseHeadersAsync + { + get + { + return callState.ResponseHeadersAsync(); + } + } + + /// + /// Allows awaiting this object directly. + /// + public TaskAwaiter GetAwaiter() + { + return responseAsync.GetAwaiter(); + } + + /// + /// Gets the call status if the call has already finished. + /// Throws InvalidOperationException otherwise. + /// + public Status GetStatus() + { + return callState.GetStatus(); + } + + /// + /// Gets the call trailing metadata if the call has already finished. + /// Throws InvalidOperationException otherwise. + /// + public Metadata GetTrailers() + { + return callState.GetTrailers(); + } + + /// + /// Provides means to cleanup after the call. + /// If the call has already finished normally (request stream has been completed and call result has been received), doesn't do anything. + /// Otherwise, requests cancellation of the call which should terminate all pending async operations associated with the call. + /// As a result, all resources being used by the call should be released eventually. + /// + /// + /// Normally, there is no need for you to dispose the call unless you want to utilize the + /// "Cancel" semantics of invoking Dispose. + /// + public void Dispose() + { + callState.Dispose(); + } + } +} diff --git a/src/csharp/Grpc.Core.Api/AuthContext.cs b/src/csharp/Grpc.Core.Api/AuthContext.cs new file mode 100644 index 00000000..fbec5001 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/AuthContext.cs @@ -0,0 +1,112 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Authentication context for a call. + /// AuthContext is the only reliable source of truth when it comes to authenticating calls. + /// Using any other call/context properties for authentication purposes is wrong and inherently unsafe. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public class AuthContext + { + string peerIdentityPropertyName; + Dictionary> properties; + + /// + /// Initializes a new instance of the class. + /// + /// Peer identity property name. + /// Multimap of auth properties by name. + public AuthContext(string peerIdentityPropertyName, Dictionary> properties) + { + this.peerIdentityPropertyName = peerIdentityPropertyName; + this.properties = GrpcPreconditions.CheckNotNull(properties); + } + + /// + /// Returns true if the peer is authenticated. + /// + public bool IsPeerAuthenticated + { + get + { + return peerIdentityPropertyName != null; + } + } + + /// + /// Gets the name of the property that indicates the peer identity. Returns null + /// if the peer is not authenticated. + /// + public string PeerIdentityPropertyName + { + get + { + return peerIdentityPropertyName; + } + } + + /// + /// Gets properties that represent the peer identity (there can be more than one). Returns an empty collection + /// if the peer is not authenticated. + /// + public IEnumerable PeerIdentity + { + get + { + if (peerIdentityPropertyName == null) + { + return Enumerable.Empty(); + } + return properties[peerIdentityPropertyName]; + } + } + + /// + /// Gets the auth properties of this context. + /// + public IEnumerable Properties + { + get + { + return properties.Values.SelectMany(v => v); + } + } + + /// + /// Returns the auth properties with given name (there can be more than one). + /// If no properties of given name exist, an empty collection will be returned. + /// + public IEnumerable FindPropertiesByName(string propertyName) + { + List result; + if (!properties.TryGetValue(propertyName, out result)) + { + return Enumerable.Empty(); + } + return result; + } + } +} diff --git a/src/csharp/Grpc.Core.Api/AuthProperty.cs b/src/csharp/Grpc.Core.Api/AuthProperty.cs new file mode 100644 index 00000000..c208cee0 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/AuthProperty.cs @@ -0,0 +1,109 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Text; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// A property of an . + /// Note: experimental API that can change or be removed without any prior notice. + /// + public class AuthProperty + { + static readonly Encoding EncodingUTF8 = System.Text.Encoding.UTF8; + string name; + byte[] valueBytes; + string lazyValue; + + private AuthProperty(string name, byte[] valueBytes) + { + this.name = GrpcPreconditions.CheckNotNull(name); + this.valueBytes = GrpcPreconditions.CheckNotNull(valueBytes); + } + + /// + /// Gets the name of the property. + /// + public string Name + { + get + { + return name; + } + } + + /// + /// Gets the string value of the property. + /// + public string Value + { + get + { + return lazyValue ?? (lazyValue = EncodingUTF8.GetString(this.valueBytes)); + } + } + + /// + /// Gets the binary value of the property. + /// + public byte[] ValueBytes + { + get + { + var valueCopy = new byte[valueBytes.Length]; + Buffer.BlockCopy(valueBytes, 0, valueCopy, 0, valueBytes.Length); + return valueCopy; + } + } + + /// + /// Creates an instance of AuthProperty. + /// + /// the name + /// the binary value of the property + public static AuthProperty Create(string name, byte[] valueBytes) + { + GrpcPreconditions.CheckNotNull(valueBytes); + var valueCopy = new byte[valueBytes.Length]; + Buffer.BlockCopy(valueBytes, 0, valueCopy, 0, valueBytes.Length); + return new AuthProperty(name, valueCopy); + } + + /// + /// Gets the binary value of the property (without making a defensive copy). + /// + internal byte[] ValueBytesUnsafe + { + get + { + return valueBytes; + } + } + + /// + /// Creates and instance of AuthProperty without making a defensive copy of valueBytes. + /// + internal static AuthProperty CreateUnsafe(string name, byte[] valueBytes) + { + return new AuthProperty(name, valueBytes); + } + } +} diff --git a/src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs b/src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs new file mode 100644 index 00000000..59802e30 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs @@ -0,0 +1,59 @@ +#region Copyright notice and license +// Copyright 2019 The gRPC Authors +// +// 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. +#endregion + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Grpc.Core +{ + /// + /// Specifies the location of the service bind method for a gRPC service. + /// The bind method is typically generated code and is used to register a service's + /// methods with the server on startup. + /// + /// The bind method signature takes a and an optional + /// instance of the service base class, e.g. static void BindService(ServiceBinderBase, GreeterService). + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class BindServiceMethodAttribute : Attribute + { + // grpc-dotnet uses reflection to find the bind service method. + // DynamicallyAccessedMembersAttribute instructs the linker to never trim the method. + private const DynamicallyAccessedMemberTypes ServiceBinderAccessibility = DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods; + + /// + /// Initializes a new instance of the class. + /// + /// The type the service bind method is defined on. + /// The name of the service bind method. + public BindServiceMethodAttribute([DynamicallyAccessedMembers(ServiceBinderAccessibility)] Type bindType, string bindMethodName) + { + BindType = bindType; + BindMethodName = bindMethodName; + } + + /// + /// Gets the type the service bind method is defined on. + /// + [DynamicallyAccessedMembers(ServiceBinderAccessibility)] + public Type BindType { get; } + + /// + /// Gets the name of the service bind method. + /// + public string BindMethodName { get; } + } +} diff --git a/src/csharp/Grpc.Core.Api/CallCredentials.cs b/src/csharp/Grpc.Core.Api/CallCredentials.cs new file mode 100644 index 00000000..47b84e03 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/CallCredentials.cs @@ -0,0 +1,90 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Collections.Generic; +using System.Collections.ObjectModel; + +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Client-side call credentials. Provide authorization with per-call granularity. + /// + public abstract class CallCredentials + { + /// + /// Composes multiple CallCredentials objects into + /// a single CallCredentials object. + /// + /// credentials to compose + /// The new CompositeCallCredentials + public static CallCredentials Compose(params CallCredentials[] credentials) + { + return new CompositeCallCredentials(credentials); + } + + /// + /// Creates a new instance of CallCredentials class from an + /// interceptor that can attach metadata to outgoing calls. + /// + /// authentication interceptor + public static CallCredentials FromInterceptor(AsyncAuthInterceptor interceptor) + { + return new AsyncAuthInterceptorCredentials(interceptor); + } + + /// + /// Populates call credentials configurator with this instance's configuration. + /// End users never need to invoke this method as it is part of internal implementation. + /// + public abstract void InternalPopulateConfiguration(CallCredentialsConfiguratorBase configurator, object state); + + private class CompositeCallCredentials : CallCredentials + { + readonly IReadOnlyList credentials; + + public CompositeCallCredentials(CallCredentials[] credentials) + { + GrpcPreconditions.CheckArgument(credentials.Length >= 2, "Composite credentials object can only be created from 2 or more credentials."); + this.credentials = new List(credentials).AsReadOnly(); + } + + public override void InternalPopulateConfiguration(CallCredentialsConfiguratorBase configurator, object state) + { + configurator.SetCompositeCredentials(state, credentials); + } + } + + private class AsyncAuthInterceptorCredentials : CallCredentials + { + readonly AsyncAuthInterceptor interceptor; + + public AsyncAuthInterceptorCredentials(AsyncAuthInterceptor interceptor) + { + this.interceptor = GrpcPreconditions.CheckNotNull(interceptor); + } + + public override void InternalPopulateConfiguration(CallCredentialsConfiguratorBase configurator, object state) + { + configurator.SetAsyncAuthInterceptorCredentials(state, interceptor); + } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/CallCredentialsConfiguratorBase.cs b/src/csharp/Grpc.Core.Api/CallCredentialsConfiguratorBase.cs new file mode 100644 index 00000000..51f8d729 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/CallCredentialsConfiguratorBase.cs @@ -0,0 +1,39 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System.Collections.Generic; + +namespace Grpc.Core +{ + /// + /// Base class for objects that can consume configuration from CallCredentials objects. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public abstract class CallCredentialsConfiguratorBase + { + /// + /// Consumes configuration for composite call credentials. + /// + public abstract void SetCompositeCredentials(object state, IReadOnlyList credentials); + + /// + /// Consumes configuration for call credentials created from AsyncAuthInterceptor + /// + public abstract void SetAsyncAuthInterceptorCredentials(object state, AsyncAuthInterceptor interceptor); + } +} diff --git a/src/csharp/Grpc.Core.Api/CallFlags.cs b/src/csharp/Grpc.Core.Api/CallFlags.cs new file mode 100644 index 00000000..7c03afc4 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/CallFlags.cs @@ -0,0 +1,45 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; + +namespace Grpc.Core.Internal +{ + /// + /// Flags to enable special call behaviors (client-side only). + /// + [Flags] + internal enum CallFlags + { + /// + /// The call is idempotent (retrying the call doesn't change the outcome of the operation). + /// + IdempotentRequest = 0x10, + + /// + /// If channel is in ChannelState.TransientFailure, attempt waiting for the channel to recover + /// instead of failing the call immediately. + /// + WaitForReady = 0x20, + + /// + /// The call is cacheable. gRPC is free to use GET verb */ + /// + CacheableRequest = 0x40 + } +} diff --git a/src/csharp/Grpc.Core.Api/CallInvoker.cs b/src/csharp/Grpc.Core.Api/CallInvoker.cs new file mode 100644 index 00000000..8a84a521 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/CallInvoker.cs @@ -0,0 +1,67 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System.Threading.Tasks; + +namespace Grpc.Core +{ + /// + /// Abstraction of client-side RPC invocation. + /// + public abstract class CallInvoker + { + /// + /// Invokes a simple remote call in a blocking fashion. + /// + public abstract TResponse BlockingUnaryCall(Method method, string host, CallOptions options, TRequest request) + where TRequest : class + where TResponse : class; + + /// + /// Invokes a simple remote call asynchronously. + /// + public abstract AsyncUnaryCall AsyncUnaryCall(Method method, string host, CallOptions options, TRequest request) + where TRequest : class + where TResponse : class; + + /// + /// Invokes a server streaming call asynchronously. + /// In server streaming scenario, client sends on request and server responds with a stream of responses. + /// + public abstract AsyncServerStreamingCall AsyncServerStreamingCall(Method method, string host, CallOptions options, TRequest request) + where TRequest : class + where TResponse : class; + + /// + /// Invokes a client streaming call asynchronously. + /// In client streaming scenario, client sends a stream of requests and server responds with a single response. + /// + public abstract AsyncClientStreamingCall AsyncClientStreamingCall(Method method, string host, CallOptions options) + where TRequest : class + where TResponse : class; + + /// + /// Invokes a duplex streaming call asynchronously. + /// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses. + /// The response stream is completely independent and both side can be sending messages at the same time. + /// + public abstract AsyncDuplexStreamingCall AsyncDuplexStreamingCall(Method method, string host, CallOptions options) + where TRequest : class + where TResponse : class; + } +} diff --git a/src/csharp/Grpc.Core.Api/CallOptions.cs b/src/csharp/Grpc.Core.Api/CallOptions.cs new file mode 100644 index 00000000..5d46851e --- /dev/null +++ b/src/csharp/Grpc.Core.Api/CallOptions.cs @@ -0,0 +1,230 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading; + +using Grpc.Core.Internal; + +namespace Grpc.Core +{ + /// + /// Options for calls made by client. + /// + public struct CallOptions + { + Metadata headers; + DateTime? deadline; + CancellationToken cancellationToken; + WriteOptions writeOptions; + ContextPropagationToken propagationToken; + CallCredentials credentials; + CallFlags flags; + + /// + /// Creates a new instance of CallOptions struct. + /// + /// Headers to be sent with the call. + /// Deadline for the call to finish. null means no deadline. + /// Can be used to request cancellation of the call. + /// Write options that will be used for this call. + /// Context propagation token obtained from . + /// Credentials to use for this call. + public CallOptions(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken), + WriteOptions writeOptions = null, ContextPropagationToken propagationToken = null, CallCredentials credentials = null) + { + this.headers = headers; + this.deadline = deadline; + this.cancellationToken = cancellationToken; + this.writeOptions = writeOptions; + this.propagationToken = propagationToken; + this.credentials = credentials; + this.flags = default(CallFlags); + } + + /// + /// Headers to send at the beginning of the call. + /// + public Metadata Headers + { + get { return headers; } + } + + /// + /// Call deadline. + /// + public DateTime? Deadline + { + get { return deadline; } + } + + /// + /// Token that can be used for cancelling the call on the client side. + /// Cancelling the token will request cancellation + /// of the remote call. Best effort will be made to deliver the cancellation + /// notification to the server and interaction of the call with the server side + /// will be terminated. Unless the call finishes before the cancellation could + /// happen (there is an inherent race), + /// the call will finish with StatusCode.Cancelled status. + /// + public CancellationToken CancellationToken + { + get { return cancellationToken; } + } + + /// + /// Write options that will be used for this call. + /// + public WriteOptions WriteOptions + { + get { return this.writeOptions; } + } + + /// + /// Token for propagating parent call context. + /// + public ContextPropagationToken PropagationToken + { + get { return this.propagationToken; } + } + + /// + /// Credentials to use for this call. + /// + public CallCredentials Credentials + { + get { return this.credentials; } + } + + /// + /// If true and channel is in ChannelState.TransientFailure, the call will attempt waiting for the channel to recover + /// instead of failing immediately (which is the default "FailFast" semantics). + /// Note: experimental API that can change or be removed without any prior notice. + /// + public bool IsWaitForReady + { + get { return (this.flags & CallFlags.WaitForReady) == CallFlags.WaitForReady; } + } + + /// + /// Flags to use for this call. + /// + internal CallFlags Flags + { + get { return this.flags; } + } + + /// + /// Returns new instance of with + /// Headers set to the value provided. Values of all other fields are preserved. + /// + /// The headers. + public CallOptions WithHeaders(Metadata headers) + { + var newOptions = this; + newOptions.headers = headers; + return newOptions; + } + + /// + /// Returns new instance of with + /// Deadline set to the value provided. Values of all other fields are preserved. + /// + /// The deadline. + public CallOptions WithDeadline(DateTime deadline) + { + var newOptions = this; + newOptions.deadline = deadline; + return newOptions; + } + + /// + /// Returns new instance of with + /// CancellationToken set to the value provided. Values of all other fields are preserved. + /// + /// The cancellation token. + public CallOptions WithCancellationToken(CancellationToken cancellationToken) + { + var newOptions = this; + newOptions.cancellationToken = cancellationToken; + return newOptions; + } + + /// + /// Returns new instance of with + /// WriteOptions set to the value provided. Values of all other fields are preserved. + /// + /// The write options. + public CallOptions WithWriteOptions(WriteOptions writeOptions) + { + var newOptions = this; + newOptions.writeOptions = writeOptions; + return newOptions; + } + + /// + /// Returns new instance of with + /// PropagationToken set to the value provided. Values of all other fields are preserved. + /// + /// The context propagation token. + public CallOptions WithPropagationToken(ContextPropagationToken propagationToken) + { + var newOptions = this; + newOptions.propagationToken = propagationToken; + return newOptions; + } + + /// + /// Returns new instance of with + /// Credentials set to the value provided. Values of all other fields are preserved. + /// + /// The call credentials. + public CallOptions WithCredentials(CallCredentials credentials) + { + var newOptions = this; + newOptions.credentials = credentials; + return newOptions; + } + + /// + /// Returns new instance of with "WaitForReady" semantics enabled/disabled. + /// . + /// Note: experimental API that can change or be removed without any prior notice. + /// + public CallOptions WithWaitForReady(bool waitForReady = true) + { + if (waitForReady) + { + return WithFlags(this.flags | CallFlags.WaitForReady); + } + return WithFlags(this.flags & ~CallFlags.WaitForReady); + } + + /// + /// Returns new instance of with + /// Flags set to the value provided. Values of all other fields are preserved. + /// + /// The call flags. + internal CallOptions WithFlags(CallFlags flags) + { + var newOptions = this; + newOptions.flags = flags; + return newOptions; + } + } +} diff --git a/src/csharp/Grpc.Core.Api/ChannelBase.cs b/src/csharp/Grpc.Core.Api/ChannelBase.cs new file mode 100644 index 00000000..d6a5481d --- /dev/null +++ b/src/csharp/Grpc.Core.Api/ChannelBase.cs @@ -0,0 +1,82 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Threading.Tasks; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Base class for gRPC channel. Channels are an abstraction of long-lived connections to remote servers. + /// + public abstract class ChannelBase + { + private readonly string target; + + /// + /// Initializes a new instance of class that connects to a specific host. + /// + /// Target of the channel. + protected ChannelBase(string target) + { + this.target = GrpcPreconditions.CheckNotNull(target, nameof(target)); + } + + /// The original target used to create the channel. + public string Target + { + get { return this.target; } + } + + /// + /// Create a new for the channel. + /// + /// A new . + public abstract CallInvoker CreateCallInvoker(); + + /// + /// Shuts down the channel cleanly. It is strongly recommended to shutdown + /// the channel once you stopped using it. + /// + /// + /// Guidance for implementors: + /// This method doesn't wait for all calls on this channel to finish (nor does + /// it have to explicitly cancel all outstanding calls). It is user's responsibility to make sure + /// all the calls on this channel have finished (successfully or with an error) + /// before shutting down the channel to ensure channel shutdown won't impact + /// the outcome of those remote calls. + /// + public Task ShutdownAsync() + { + return ShutdownAsyncCore(); + } + + /// Provides implementation of a non-virtual public member. + #pragma warning disable 1998 + protected virtual async Task ShutdownAsyncCore() + { + // default implementation is no-op for backwards compatibility, but all implementations + // are expected to override this method. + + // warning 1998 is disabled to avoid needing TaskUtils.CompletedTask, which is + // only available in Grpc.Core + } + #pragma warning restore 1998 + } +} diff --git a/src/csharp/Grpc.Core.Api/ChannelCredentials.cs b/src/csharp/Grpc.Core.Api/ChannelCredentials.cs new file mode 100644 index 00000000..4d6ede3b --- /dev/null +++ b/src/csharp/Grpc.Core.Api/ChannelCredentials.cs @@ -0,0 +1,134 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Client-side channel credentials. Used for creation of a secure channel. + /// + public abstract class ChannelCredentials + { + static readonly ChannelCredentials InsecureInstance = new InsecureCredentials(); + static readonly ChannelCredentials SecureSslInstance = new SslCredentials(); + + /// + /// Creates a new instance of channel credentials + /// + public ChannelCredentials() + { + } + + /// + /// Returns instance of credentials that provides no security and + /// will result in creating an unsecure channel with no encryption whatsoever. + /// + public static ChannelCredentials Insecure + { + get + { + return InsecureInstance; + } + } + + /// + /// Returns instance of credentials that provides SSL security. + /// + /// These credentials are the same as creating without parameters. + /// Apps that are using Grpc.Core can create directly to customize + /// the secure SSL credentials. + /// + /// + public static ChannelCredentials SecureSsl + { + get + { + return SecureSslInstance; + } + } + + /// + /// Creates a new instance of ChannelCredentials class by composing + /// given channel credentials with call credentials. + /// + /// Channel credentials. + /// Call credentials. + /// The new composite ChannelCredentials + public static ChannelCredentials Create(ChannelCredentials channelCredentials, CallCredentials callCredentials) + { + return new CompositeChannelCredentials(channelCredentials, callCredentials); + } + + /// + /// Populates channel credentials configurator with this instance's configuration. + /// End users never need to invoke this method as it is part of internal implementation. + /// + public abstract void InternalPopulateConfiguration(ChannelCredentialsConfiguratorBase configurator, object state); + + /// + /// Returns true if this credential type allows being composed by CompositeCredentials. + /// + internal virtual bool IsComposable => false; + + private sealed class InsecureCredentials : ChannelCredentials + { + public override void InternalPopulateConfiguration(ChannelCredentialsConfiguratorBase configurator, object state) + { + configurator.SetInsecureCredentials(state); + } + } + + /// + /// Credentials that allow composing one object and + /// one or more objects into a single . + /// + private sealed class CompositeChannelCredentials : ChannelCredentials + { + readonly ChannelCredentials channelCredentials; + readonly CallCredentials callCredentials; + + /// + /// Initializes a new instance of CompositeChannelCredentials class. + /// The resulting credentials object will be composite of all the credentials specified as parameters. + /// + /// channelCredentials to compose + /// channelCredentials to compose + public CompositeChannelCredentials(ChannelCredentials channelCredentials, CallCredentials callCredentials) + { + this.channelCredentials = GrpcPreconditions.CheckNotNull(channelCredentials); + this.callCredentials = GrpcPreconditions.CheckNotNull(callCredentials); + + if (!channelCredentials.IsComposable) + { + throw new ArgumentException(string.Format("CallCredentials can't be composed with {0}. CallCredentials must be used with secure channel credentials like SslCredentials.", channelCredentials.GetType().Name)); + } + } + + public override void InternalPopulateConfiguration(ChannelCredentialsConfiguratorBase configurator, object state) + { + configurator.SetCompositeCredentials(state, channelCredentials, callCredentials); + } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/ChannelCredentialsConfiguratorBase.cs b/src/csharp/Grpc.Core.Api/ChannelCredentialsConfiguratorBase.cs new file mode 100644 index 00000000..5c779bc6 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/ChannelCredentialsConfiguratorBase.cs @@ -0,0 +1,44 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System.Collections.Generic; + +namespace Grpc.Core +{ + /// + /// Base class for objects that can consume configuration from CallCredentials objects. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public abstract class ChannelCredentialsConfiguratorBase + { + /// + /// Configures the credentials to use insecure credentials. + /// + public abstract void SetInsecureCredentials(object state); + + /// + /// Configures the credentials to use SslCredentials. + /// + public abstract void SetSslCredentials(object state, string rootCertificates, KeyCertificatePair keyCertificatePair, VerifyPeerCallback verifyPeerCallback); + + /// + /// Configures the credentials to use composite channel credentials (a composite of channel credentials and call credentials). + /// + public abstract void SetCompositeCredentials(object state, ChannelCredentials channelCredentials, CallCredentials callCredentials); + } +} diff --git a/src/csharp/Grpc.Core.Api/ClientBase.cs b/src/csharp/Grpc.Core.Api/ClientBase.cs new file mode 100644 index 00000000..243c35e2 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/ClientBase.cs @@ -0,0 +1,231 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.Core.Interceptors; +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Generic base class for client-side stubs. + /// + public abstract class ClientBase : ClientBase + where T : ClientBase + { + /// + /// Initializes a new instance of ClientBase class that + /// throws NotImplementedException upon invocation of any RPC. + /// This constructor is only provided to allow creation of test doubles + /// for client classes (e.g. mocking requires a parameterless constructor). + /// + protected ClientBase() : base() + { + } + + /// + /// Initializes a new instance of ClientBase class. + /// + /// The configuration. + protected ClientBase(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// Initializes a new instance of ClientBase class. + /// + /// The channel to use for remote call invocation. + public ClientBase(ChannelBase channel) : base(channel) + { + } + + /// + /// Initializes a new instance of ClientBase class. + /// + /// The CallInvoker for remote call invocation. + public ClientBase(CallInvoker callInvoker) : base(callInvoker) + { + } + + /// + /// Creates a new client that sets host field for calls explicitly. + /// gRPC supports multiple "hosts" being served by a single server. + /// By default (if a client was not created by calling this method), + /// host null with the meaning "use default host" is used. + /// + public T WithHost(string host) + { + var newConfiguration = this.Configuration.WithHost(host); + return NewInstance(newConfiguration); + } + + /// + /// Creates a new instance of client from given ClientBaseConfiguration. + /// + protected abstract T NewInstance(ClientBaseConfiguration configuration); + } + + /// + /// Base class for client-side stubs. + /// + public abstract class ClientBase + { + readonly ClientBaseConfiguration configuration; + readonly CallInvoker callInvoker; + + /// + /// Initializes a new instance of ClientBase class that + /// throws NotImplementedException upon invocation of any RPC. + /// This constructor is only provided to allow creation of test doubles + /// for client classes (e.g. mocking requires a parameterless constructor). + /// + protected ClientBase() : this(new UnimplementedCallInvoker()) + { + } + + /// + /// Initializes a new instance of ClientBase class. + /// + /// The configuration. + protected ClientBase(ClientBaseConfiguration configuration) + { + this.configuration = GrpcPreconditions.CheckNotNull(configuration, "configuration"); + this.callInvoker = configuration.CreateDecoratedCallInvoker(); + } + + /// + /// Initializes a new instance of ClientBase class. + /// + /// The channel to use for remote call invocation. + public ClientBase(ChannelBase channel) : this(channel.CreateCallInvoker()) + { + } + + /// + /// Initializes a new instance of ClientBase class. + /// + /// The CallInvoker for remote call invocation. + public ClientBase(CallInvoker callInvoker) : this(new ClientBaseConfiguration(callInvoker, null)) + { + } + + /// + /// Gets the call invoker. + /// + protected CallInvoker CallInvoker + { + get { return this.callInvoker; } + } + + /// + /// Gets the configuration. + /// + internal ClientBaseConfiguration Configuration + { + get { return this.configuration; } + } + + /// + /// Represents configuration of ClientBase. The class itself is visible to + /// subclasses, but contents are marked as internal to make the instances opaque. + /// The verbose name of this class was chosen to make name clash in generated code + /// less likely. + /// + protected internal class ClientBaseConfiguration + { + private class ClientBaseConfigurationInterceptor : Interceptor + { + readonly Func interceptor; + + /// + /// Creates a new instance of ClientBaseConfigurationInterceptor given the specified header and host interceptor function. + /// + public ClientBaseConfigurationInterceptor(Func interceptor) + { + this.interceptor = GrpcPreconditions.CheckNotNull(interceptor, nameof(interceptor)); + } + + private ClientInterceptorContext GetNewContext(ClientInterceptorContext context) + where TRequest : class + where TResponse : class + { + var newHostAndCallOptions = interceptor(context.Method, context.Host, context.Options); + return new ClientInterceptorContext(context.Method, newHostAndCallOptions.Host, newHostAndCallOptions.CallOptions); + } + + public override TResponse BlockingUnaryCall(TRequest request, ClientInterceptorContext context, BlockingUnaryCallContinuation continuation) + { + return continuation(request, GetNewContext(context)); + } + + public override AsyncUnaryCall AsyncUnaryCall(TRequest request, ClientInterceptorContext context, AsyncUnaryCallContinuation continuation) + { + return continuation(request, GetNewContext(context)); + } + + public override AsyncServerStreamingCall AsyncServerStreamingCall(TRequest request, ClientInterceptorContext context, AsyncServerStreamingCallContinuation continuation) + { + return continuation(request, GetNewContext(context)); + } + + public override AsyncClientStreamingCall AsyncClientStreamingCall(ClientInterceptorContext context, AsyncClientStreamingCallContinuation continuation) + { + return continuation(GetNewContext(context)); + } + + public override AsyncDuplexStreamingCall AsyncDuplexStreamingCall(ClientInterceptorContext context, AsyncDuplexStreamingCallContinuation continuation) + { + return continuation(GetNewContext(context)); + } + } + + internal struct ClientBaseConfigurationInfo + { + internal readonly string Host; + internal readonly CallOptions CallOptions; + + internal ClientBaseConfigurationInfo(string host, CallOptions callOptions) + { + Host = host; + CallOptions = callOptions; + } + } + + readonly CallInvoker undecoratedCallInvoker; + readonly string host; + + internal ClientBaseConfiguration(CallInvoker undecoratedCallInvoker, string host) + { + this.undecoratedCallInvoker = GrpcPreconditions.CheckNotNull(undecoratedCallInvoker); + this.host = host; + } + + internal CallInvoker CreateDecoratedCallInvoker() + { + return undecoratedCallInvoker.Intercept(new ClientBaseConfigurationInterceptor((method, host, options) => new ClientBaseConfigurationInfo(this.host, options))); + } + + internal ClientBaseConfiguration WithHost(string host) + { + GrpcPreconditions.CheckNotNull(host, nameof(host)); + return new ClientBaseConfiguration(this.undecoratedCallInvoker, host); + } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/ContextPropagationOptions.cs b/src/csharp/Grpc.Core.Api/ContextPropagationOptions.cs new file mode 100644 index 00000000..160d10dc --- /dev/null +++ b/src/csharp/Grpc.Core.Api/ContextPropagationOptions.cs @@ -0,0 +1,59 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; + +namespace Grpc.Core +{ + /// + /// Options for . + /// + public class ContextPropagationOptions + { + /// + /// The context propagation options that will be used by default. + /// + public static readonly ContextPropagationOptions Default = new ContextPropagationOptions(); + + bool propagateDeadline; + bool propagateCancellation; + + /// + /// Creates new context propagation options. + /// + /// If set to true parent call's deadline will be propagated to the child call. + /// If set to true parent call's cancellation token will be propagated to the child call. + public ContextPropagationOptions(bool propagateDeadline = true, bool propagateCancellation = true) + { + this.propagateDeadline = propagateDeadline; + this.propagateCancellation = propagateCancellation; + } + + /// true if parent call's deadline should be propagated to the child call. + public bool IsPropagateDeadline + { + get { return this.propagateDeadline; } + } + + /// true if parent call's cancellation token should be propagated to the child call. + public bool IsPropagateCancellation + { + get { return this.propagateCancellation; } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/ContextPropagationToken.cs b/src/csharp/Grpc.Core.Api/ContextPropagationToken.cs new file mode 100644 index 00000000..60e407dc --- /dev/null +++ b/src/csharp/Grpc.Core.Api/ContextPropagationToken.cs @@ -0,0 +1,35 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +namespace Grpc.Core +{ + /// + /// Token for propagating context of server side handlers to child calls. + /// In situations when a backend is making calls to another backend, + /// it makes sense to propagate properties like deadline and cancellation + /// token of the server call to the child call. + /// Underlying gRPC implementation may provide other "opaque" contexts (like tracing context) that + /// are not explicitly accesible via the public C# API, but this token still allows propagating them. + /// + public abstract class ContextPropagationToken + { + internal ContextPropagationToken() + { + } + } +} diff --git a/src/csharp/Grpc.Core.Api/DeserializationContext.cs b/src/csharp/Grpc.Core.Api/DeserializationContext.cs new file mode 100644 index 00000000..b0c3badb --- /dev/null +++ b/src/csharp/Grpc.Core.Api/DeserializationContext.cs @@ -0,0 +1,66 @@ +#region Copyright notice and license + +// Copyright 2018 The gRPC Authors +// +// 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. + +#endregion + +using System; + +namespace Grpc.Core +{ + /// + /// Provides access to the payload being deserialized when deserializing messages. + /// + public abstract class DeserializationContext + { + /// + /// Get the total length of the payload in bytes. + /// + public abstract int PayloadLength { get; } + + /// + /// Gets the entire payload as a newly allocated byte array. + /// Once the byte array is returned, the byte array becomes owned by the caller and won't be ever accessed or reused by gRPC again. + /// NOTE: Obtaining the buffer as a newly allocated byte array is the simplest way of accessing the payload, + /// but it can have important consequences in high-performance scenarios. + /// In particular, using this method usually requires copying of the entire buffer one extra time. + /// Also, allocating a new buffer each time can put excessive pressure on GC, especially if + /// the payload is more than 86700 bytes large (which means the newly allocated buffer will be placed in LOH, + /// and LOH object can only be garbage collected via a full ("stop the world") GC run). + /// NOTE: Deserializers are expected not to call this method (or other payload accessor methods) more than once per received message + /// (as there is no practical reason for doing so) and DeserializationContext implementations are free to assume so. + /// + /// byte array containing the entire payload. + public virtual byte[] PayloadAsNewBuffer() + { + throw new NotImplementedException(); + } + + /// + /// Gets the entire payload as a ReadOnlySequence. + /// The ReadOnlySequence is only valid for the duration of the deserializer routine and the caller must not access it after the deserializer returns. + /// Using the read only sequence is the most efficient way to access the message payload. Where possible it allows directly + /// accessing the received payload without needing to perform any buffer copying or buffer allocations. + /// NOTE: When using this method, it is recommended to use C# 7.2 compiler to make it more useful (using Span type directly from your code requires C# 7.2)." + /// NOTE: Deserializers are expected not to call this method (or other payload accessor methods) more than once per received message + /// (as there is no practical reason for doing so) and DeserializationContext implementations are free to assume so. + /// + /// read only sequence containing the entire payload. + public virtual System.Buffers.ReadOnlySequence PayloadAsReadOnlySequence() + { + throw new NotImplementedException(); + } + } +} diff --git a/src/csharp/Grpc.Core.Api/IAsyncStreamReader.cs b/src/csharp/Grpc.Core.Api/IAsyncStreamReader.cs new file mode 100644 index 00000000..373613f6 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/IAsyncStreamReader.cs @@ -0,0 +1,66 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Threading; +using System.Threading.Tasks; + +namespace Grpc.Core +{ + /// + /// A stream of messages to be read. + /// Messages can be awaited await reader.MoveNext(), that returns true + /// if there is a message available and false if there are no more messages + /// (i.e. the stream has been closed). + /// + /// On the client side, the last invocation of MoveNext() either returns false + /// if the call has finished successfully or throws RpcException if call finished + /// with an error. Once the call finishes, subsequent invocations of MoveNext() will + /// continue yielding the same result (returning false or throwing an exception). + /// + /// + /// On the server side, MoveNext() does not throw exceptions. + /// In case of a failure, the request stream will appear to be finished + /// (MoveNext will return false) and the CancellationToken + /// associated with the call will be cancelled to signal the failure. + /// + /// + /// MoveNext() operations can be cancelled via a cancellation token. Cancelling + /// an individual read operation has the same effect as cancelling the entire call + /// (which will also result in the read operation returning prematurely), but the per-read cancellation + /// tokens passed to MoveNext() only result in cancelling the call if the read operation haven't finished + /// yet. + /// + /// + /// The message type. + public interface IAsyncStreamReader + { + /// + /// Gets the current element in the iteration. + /// + T Current { get; } + + /// + /// Advances the reader to the next element in the sequence, returning the result asynchronously. + /// + /// Cancellation token that can be used to cancel the operation. + /// + /// Task containing the result of the operation: true if the reader was successfully advanced + /// to the next element; false if the reader has passed the end of the sequence. + Task MoveNext(CancellationToken cancellationToken); + } +} diff --git a/src/csharp/Grpc.Core.Api/IAsyncStreamWriter.cs b/src/csharp/Grpc.Core.Api/IAsyncStreamWriter.cs new file mode 100644 index 00000000..ccf04685 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/IAsyncStreamWriter.cs @@ -0,0 +1,47 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Grpc.Core +{ + /// + /// A writable stream of messages. + /// + /// The message type. + public interface IAsyncStreamWriter + { + /// + /// Writes a message asynchronously. Only one write can be pending at a time. + /// + /// The message to be written. Cannot be null. + Task WriteAsync(T message); + + /// + /// Write options that will be used for the next write. + /// If null, default options will be used. + /// Once set, this property maintains its value across subsequent + /// writes. + /// + WriteOptions WriteOptions { get; set; } + } +} diff --git a/src/csharp/Grpc.Core.Api/IClientStreamWriter.cs b/src/csharp/Grpc.Core.Api/IClientStreamWriter.cs new file mode 100644 index 00000000..6060e832 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/IClientStreamWriter.cs @@ -0,0 +1,38 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Grpc.Core +{ + /// + /// Client-side writable stream of messages with Close capability. + /// + /// The message type. + public interface IClientStreamWriter : IAsyncStreamWriter + { + /// + /// Completes/closes the stream. Can only be called once there is no pending write. No writes should follow calling this. + /// + Task CompleteAsync(); + } +} diff --git a/src/csharp/Grpc.Core.Api/IServerStreamWriter.cs b/src/csharp/Grpc.Core.Api/IServerStreamWriter.cs new file mode 100644 index 00000000..9b735265 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/IServerStreamWriter.cs @@ -0,0 +1,34 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Grpc.Core +{ + /// + /// A writable stream of messages that is used in server-side handlers. + /// + public interface IServerStreamWriter : IAsyncStreamWriter + { + // TODO(jtattermusch): consider just using IAsyncStreamWriter instead of this interface. + } +} diff --git a/src/csharp/Grpc.Core.Api/Interceptors/CallInvokerExtensions.cs b/src/csharp/Grpc.Core.Api/Interceptors/CallInvokerExtensions.cs new file mode 100644 index 00000000..39c24d01 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Interceptors/CallInvokerExtensions.cs @@ -0,0 +1,143 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Linq; +using Grpc.Core.Utils; + +namespace Grpc.Core.Interceptors +{ + /// + /// Extends the CallInvoker class to provide the interceptor facility on the client side. + /// + public static class CallInvokerExtensions + { + /// + /// Returns a instance that intercepts + /// the invoker with the given interceptor. + /// + /// The underlying invoker to intercept. + /// The interceptor to intercept calls to the invoker with. + /// + /// Multiple interceptors can be added on top of each other by calling + /// "invoker.Intercept(a, b, c)". The order of invocation will be "a", "b", and then "c". + /// Interceptors can be later added to an existing intercepted CallInvoker, effectively + /// building a chain like "invoker.Intercept(c).Intercept(b).Intercept(a)". Note that + /// in this case, the last interceptor added will be the first to take control. + /// + public static CallInvoker Intercept(this CallInvoker invoker, Interceptor interceptor) + { + return new InterceptingCallInvoker(invoker, interceptor); + } + + /// + /// Returns a instance that intercepts + /// the invoker with the given interceptors. + /// + /// The channel to intercept. + /// + /// An array of interceptors to intercept the calls to the invoker with. + /// Control is passed to the interceptors in the order specified. + /// + /// + /// Multiple interceptors can be added on top of each other by calling + /// "invoker.Intercept(a, b, c)". The order of invocation will be "a", "b", and then "c". + /// Interceptors can be later added to an existing intercepted CallInvoker, effectively + /// building a chain like "invoker.Intercept(c).Intercept(b).Intercept(a)". Note that + /// in this case, the last interceptor added will be the first to take control. + /// + public static CallInvoker Intercept(this CallInvoker invoker, params Interceptor[] interceptors) + { + GrpcPreconditions.CheckNotNull(invoker, nameof(invoker)); + GrpcPreconditions.CheckNotNull(interceptors, nameof(interceptors)); + + foreach (var interceptor in interceptors.Reverse()) + { + invoker = Intercept(invoker, interceptor); + } + + return invoker; + } + + /// + /// Returns a instance that intercepts + /// the invoker with the given interceptor. + /// + /// The underlying invoker to intercept. + /// + /// An interceptor delegate that takes the request metadata to be sent with an outgoing call + /// and returns a instance that will replace the existing + /// invocation metadata. + /// + /// + /// Multiple interceptors can be added on top of each other by + /// building a chain like "invoker.Intercept(c).Intercept(b).Intercept(a)". Note that + /// in this case, the last interceptor added will be the first to take control. + /// + public static CallInvoker Intercept(this CallInvoker invoker, Func interceptor) + { + return new InterceptingCallInvoker(invoker, new MetadataInterceptor(interceptor)); + } + + private class MetadataInterceptor : Interceptor + { + readonly Func interceptor; + + /// + /// Creates a new instance of MetadataInterceptor given the specified interceptor function. + /// + public MetadataInterceptor(Func interceptor) + { + this.interceptor = GrpcPreconditions.CheckNotNull(interceptor, nameof(interceptor)); + } + + private ClientInterceptorContext GetNewContext(ClientInterceptorContext context) + where TRequest : class + where TResponse : class + { + var metadata = context.Options.Headers ?? new Metadata(); + return new ClientInterceptorContext(context.Method, context.Host, context.Options.WithHeaders(interceptor(metadata))); + } + + public override TResponse BlockingUnaryCall(TRequest request, ClientInterceptorContext context, BlockingUnaryCallContinuation continuation) + { + return continuation(request, GetNewContext(context)); + } + + public override AsyncUnaryCall AsyncUnaryCall(TRequest request, ClientInterceptorContext context, AsyncUnaryCallContinuation continuation) + { + return continuation(request, GetNewContext(context)); + } + + public override AsyncServerStreamingCall AsyncServerStreamingCall(TRequest request, ClientInterceptorContext context, AsyncServerStreamingCallContinuation continuation) + { + return continuation(request, GetNewContext(context)); + } + + public override AsyncClientStreamingCall AsyncClientStreamingCall(ClientInterceptorContext context, AsyncClientStreamingCallContinuation continuation) + { + return continuation(GetNewContext(context)); + } + + public override AsyncDuplexStreamingCall AsyncDuplexStreamingCall(ClientInterceptorContext context, AsyncDuplexStreamingCallContinuation continuation) + { + return continuation(GetNewContext(context)); + } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/Interceptors/ChannelExtensions.cs b/src/csharp/Grpc.Core.Api/Interceptors/ChannelExtensions.cs new file mode 100644 index 00000000..fe3b5168 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Interceptors/ChannelExtensions.cs @@ -0,0 +1,87 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System; + +namespace Grpc.Core.Interceptors +{ + /// + /// Provides extension methods to make it easy to register interceptors on Channel objects. + /// + public static class ChannelExtensions + { + /// + /// Returns a instance that intercepts + /// the channel with the given interceptor. + /// + /// The channel to intercept. + /// The interceptor to intercept the channel with. + /// + /// Multiple interceptors can be added on top of each other by calling + /// "channel.Intercept(a, b, c)". The order of invocation will be "a", "b", and then "c". + /// Interceptors can be later added to an existing intercepted channel, effectively + /// building a chain like "channel.Intercept(c).Intercept(b).Intercept(a)". Note that + /// in this case, the last interceptor added will be the first to take control. + /// + public static CallInvoker Intercept(this ChannelBase channel, Interceptor interceptor) + { + return channel.CreateCallInvoker().Intercept(interceptor); + } + + /// + /// Returns a instance that intercepts + /// the channel with the given interceptors. + /// + /// The channel to intercept. + /// + /// An array of interceptors to intercept the channel with. + /// Control is passed to the interceptors in the order specified. + /// + /// + /// Multiple interceptors can be added on top of each other by calling + /// "channel.Intercept(a, b, c)". The order of invocation will be "a", "b", and then "c". + /// Interceptors can be later added to an existing intercepted channel, effectively + /// building a chain like "channel.Intercept(c).Intercept(b).Intercept(a)". Note that + /// in this case, the last interceptor added will be the first to take control. + /// + public static CallInvoker Intercept(this ChannelBase channel, params Interceptor[] interceptors) + { + return channel.CreateCallInvoker().Intercept(interceptors); + } + + /// + /// Returns a instance that intercepts + /// the invoker with the given interceptor. + /// + /// The channel to intercept. + /// + /// An interceptor delegate that takes the request metadata to be sent with an outgoing call + /// and returns a instance that will replace the existing + /// invocation metadata. + /// + /// + /// Multiple interceptors can be added on top of each other by + /// building a chain like "channel.Intercept(c).Intercept(b).Intercept(a)". Note that + /// in this case, the last interceptor added will be the first to take control. + /// + public static CallInvoker Intercept(this ChannelBase channel, Func interceptor) + { + return channel.CreateCallInvoker().Intercept(interceptor); + } + } +} diff --git a/src/csharp/Grpc.Core.Api/Interceptors/ClientInterceptorContext.cs b/src/csharp/Grpc.Core.Api/Interceptors/ClientInterceptorContext.cs new file mode 100644 index 00000000..4665fc55 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Interceptors/ClientInterceptorContext.cs @@ -0,0 +1,64 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Reflection; +using System.Threading.Tasks; +using Grpc.Core.Internal; + +namespace Grpc.Core.Interceptors +{ + /// + /// Carries along the context associated with intercepted invocations on the client side. + /// + public struct ClientInterceptorContext + where TRequest : class + where TResponse : class + { + /// + /// Creates a new instance of + /// with the specified method, host, and call options. + /// + /// A object representing the method to be invoked. + /// The host to dispatch the current call to. + /// A instance containing the call options of the current call. + public ClientInterceptorContext(Method method, string host, CallOptions options) + { + Method = method; + Host = host; + Options = options; + } + + /// + /// Gets the instance + /// representing the method to be invoked. + /// + public Method Method { get; } + + /// + /// Gets the host that the currect invocation will be dispatched to. + /// + public string Host { get; } + + /// + /// Gets the structure representing the + /// call options associated with the current invocation. + /// + public CallOptions Options { get; } + } +} diff --git a/src/csharp/Grpc.Core.Api/Interceptors/InterceptingCallInvoker.cs b/src/csharp/Grpc.Core.Api/Interceptors/InterceptingCallInvoker.cs new file mode 100644 index 00000000..84d2a0b9 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Interceptors/InterceptingCallInvoker.cs @@ -0,0 +1,96 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.Core.Utils; + +namespace Grpc.Core.Interceptors +{ + /// + /// Decorates an underlying to + /// intercept calls through a given interceptor. + /// + internal class InterceptingCallInvoker : CallInvoker + { + readonly CallInvoker invoker; + readonly Interceptor interceptor; + + /// + /// Creates a new instance of + /// with the given underlying invoker and interceptor instances. + /// + public InterceptingCallInvoker(CallInvoker invoker, Interceptor interceptor) + { + this.invoker = GrpcPreconditions.CheckNotNull(invoker, nameof(invoker)); + this.interceptor = GrpcPreconditions.CheckNotNull(interceptor, nameof(interceptor)); + } + + /// + /// Intercepts a simple blocking call with the registered interceptor. + /// + public override TResponse BlockingUnaryCall(Method method, string host, CallOptions options, TRequest request) + { + return interceptor.BlockingUnaryCall( + request, + new ClientInterceptorContext(method, host, options), + (req, ctx) => invoker.BlockingUnaryCall(ctx.Method, ctx.Host, ctx.Options, req)); + } + + /// + /// Intercepts a simple asynchronous call with the registered interceptor. + /// + public override AsyncUnaryCall AsyncUnaryCall(Method method, string host, CallOptions options, TRequest request) + { + return interceptor.AsyncUnaryCall( + request, + new ClientInterceptorContext(method, host, options), + (req, ctx) => invoker.AsyncUnaryCall(ctx.Method, ctx.Host, ctx.Options, req)); + } + + /// + /// Intercepts an asynchronous server streaming call with the registered interceptor. + /// + public override AsyncServerStreamingCall AsyncServerStreamingCall(Method method, string host, CallOptions options, TRequest request) + { + return interceptor.AsyncServerStreamingCall( + request, + new ClientInterceptorContext(method, host, options), + (req, ctx) => invoker.AsyncServerStreamingCall(ctx.Method, ctx.Host, ctx.Options, req)); + } + + /// + /// Intercepts an asynchronous client streaming call with the registered interceptor. + /// + public override AsyncClientStreamingCall AsyncClientStreamingCall(Method method, string host, CallOptions options) + { + return interceptor.AsyncClientStreamingCall( + new ClientInterceptorContext(method, host, options), + ctx => invoker.AsyncClientStreamingCall(ctx.Method, ctx.Host, ctx.Options)); + } + + /// + /// Intercepts an asynchronous duplex streaming call with the registered interceptor. + /// + public override AsyncDuplexStreamingCall AsyncDuplexStreamingCall(Method method, string host, CallOptions options) + { + return interceptor.AsyncDuplexStreamingCall( + new ClientInterceptorContext(method, host, options), + ctx => invoker.AsyncDuplexStreamingCall(ctx.Method, ctx.Host, ctx.Options)); + } + } +} diff --git a/src/csharp/Grpc.Core.Api/Interceptors/Interceptor.cs b/src/csharp/Grpc.Core.Api/Interceptors/Interceptor.cs new file mode 100644 index 00000000..ab708034 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Interceptors/Interceptor.cs @@ -0,0 +1,405 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Reflection; +using System.Threading.Tasks; +using Grpc.Core.Internal; + +namespace Grpc.Core.Interceptors +{ + /// + /// Serves as the base class for gRPC interceptors. + /// + public abstract class Interceptor + { + /// + /// Represents a continuation for intercepting simple blocking invocations. + /// A delegate of this type is passed to the BlockingUnaryCall method + /// when an outgoing invocation is being intercepted and calling the + /// delegate will invoke the next interceptor in the chain, or the underlying + /// call invoker if called from the last interceptor. The interceptor is + /// allowed to call it zero, one, or multiple times, passing it the appropriate + /// context and request values as it sees fit. + /// + /// Request message type for this invocation. + /// Response message type for this invocation. + /// The request value to continue the invocation with. + /// + /// The + /// instance to pass to the next step in the invocation process. + /// + /// + /// The response value of the invocation to return to the caller. + /// The interceptor can choose to return the return value of the + /// continuation delegate or an arbitrary value as it sees fit. + /// + public delegate TResponse BlockingUnaryCallContinuation(TRequest request, ClientInterceptorContext context) + where TRequest : class + where TResponse : class; + + /// + /// Represents a continuation for intercepting simple asynchronous invocations. + /// A delegate of this type is passed to the AsyncUnaryCall method + /// when an outgoing invocation is being intercepted and calling the + /// delegate will invoke the next interceptor in the chain, or the underlying + /// call invoker if called from the last interceptor. The interceptor is + /// allowed to call it zero, one, or multiple times, passing it the appropriate + /// request value and context as it sees fit. + /// + /// Request message type for this invocation. + /// Response message type for this invocation. + /// The request value to continue the invocation with. + /// + /// The + /// instance to pass to the next step in the invocation process. + /// + /// + /// An instance of + /// representing an asynchronous invocation of a unary RPC. + /// The interceptor can choose to return the same object returned from + /// the continuation delegate or an arbitrarily constructed instance as it sees fit. + /// + public delegate AsyncUnaryCall AsyncUnaryCallContinuation(TRequest request, ClientInterceptorContext context) + where TRequest : class + where TResponse : class; + + /// + /// Represents a continuation for intercepting asynchronous server-streaming invocations. + /// A delegate of this type is passed to the AsyncServerStreamingCall method + /// when an outgoing invocation is being intercepted and calling the + /// delegate will invoke the next interceptor in the chain, or the underlying + /// call invoker if called from the last interceptor. The interceptor is + /// allowed to call it zero, one, or multiple times, passing it the appropriate + /// request value and context as it sees fit. + /// + /// Request message type for this invocation. + /// Response message type for this invocation. + /// The request value to continue the invocation with. + /// + /// The + /// instance to pass to the next step in the invocation process. + /// + /// + /// An instance of + /// representing an asynchronous invocation of a server-streaming RPC. + /// The interceptor can choose to return the same object returned from + /// the continuation delegate or an arbitrarily constructed instance as it sees fit. + /// + public delegate AsyncServerStreamingCall AsyncServerStreamingCallContinuation(TRequest request, ClientInterceptorContext context) + where TRequest : class + where TResponse : class; + + /// + /// Represents a continuation for intercepting asynchronous client-streaming invocations. + /// A delegate of this type is passed to the AsyncClientStreamingCall method + /// when an outgoing invocation is being intercepted and calling the + /// delegate will invoke the next interceptor in the chain, or the underlying + /// call invoker if called from the last interceptor. The interceptor is + /// allowed to call it zero, one, or multiple times, passing it the appropriate + /// request value and context as it sees fit. + /// + /// Request message type for this invocation. + /// Response message type for this invocation. + /// + /// The + /// instance to pass to the next step in the invocation process. + /// + /// + /// An instance of + /// representing an asynchronous invocation of a client-streaming RPC. + /// The interceptor can choose to return the same object returned from + /// the continuation delegate or an arbitrarily constructed instance as it sees fit. + /// + public delegate AsyncClientStreamingCall AsyncClientStreamingCallContinuation(ClientInterceptorContext context) + where TRequest : class + where TResponse : class; + + /// + /// Represents a continuation for intercepting asynchronous duplex invocations. + /// A delegate of this type is passed to the AsyncDuplexStreamingCall method + /// when an outgoing invocation is being intercepted and calling the + /// delegate will invoke the next interceptor in the chain, or the underlying + /// call invoker if called from the last interceptor. The interceptor is + /// allowed to call it zero, one, or multiple times, passing it the appropriate + /// request value and context as it sees fit. + /// + /// + /// The + /// instance to pass to the next step in the invocation process. + /// + /// + /// An instance of + /// representing an asynchronous invocation of a duplex-streaming RPC. + /// The interceptor can choose to return the same object returned from + /// the continuation delegate or an arbitrarily constructed instance as it sees fit. + /// + public delegate AsyncDuplexStreamingCall AsyncDuplexStreamingCallContinuation(ClientInterceptorContext context) + where TRequest : class + where TResponse : class; + + /// + /// Intercepts a blocking invocation of a simple remote call. + /// + /// The request message of the invocation. + /// + /// The + /// associated with the current invocation. + /// + /// + /// The callback that continues the invocation process. + /// This can be invoked zero or more times by the interceptor. + /// The interceptor can invoke the continuation passing the given + /// request value and context arguments, or substitute them as it sees fit. + /// + /// + /// The response message of the current invocation. + /// The interceptor can simply return the return value of the + /// continuation delegate passed to it intact, or an arbitrary + /// value as it sees fit. + /// + public virtual TResponse BlockingUnaryCall(TRequest request, ClientInterceptorContext context, BlockingUnaryCallContinuation continuation) + where TRequest : class + where TResponse : class + { + return continuation(request, context); + } + + /// + /// Intercepts an asynchronous invocation of a simple remote call. + /// + /// The request message of the invocation. + /// + /// The + /// associated with the current invocation. + /// + /// + /// The callback that continues the invocation process. + /// This can be invoked zero or more times by the interceptor. + /// The interceptor can invoke the continuation passing the given + /// request value and context arguments, or substitute them as it sees fit. + /// + /// + /// An instance of + /// representing an asynchronous unary invocation. + /// The interceptor can simply return the return value of the + /// continuation delegate passed to it intact, or construct its + /// own substitute as it sees fit. + /// + public virtual AsyncUnaryCall AsyncUnaryCall(TRequest request, ClientInterceptorContext context, AsyncUnaryCallContinuation continuation) + where TRequest : class + where TResponse : class + { + return continuation(request, context); + } + + /// + /// Intercepts an asynchronous invocation of a streaming remote call. + /// + /// The request message of the invocation. + /// + /// The + /// associated with the current invocation. + /// + /// + /// The callback that continues the invocation process. + /// This can be invoked zero or more times by the interceptor. + /// The interceptor can invoke the continuation passing the given + /// request value and context arguments, or substitute them as it sees fit. + /// + /// + /// An instance of + /// representing an asynchronous server-streaming invocation. + /// The interceptor can simply return the return value of the + /// continuation delegate passed to it intact, or construct its + /// own substitute as it sees fit. + /// + public virtual AsyncServerStreamingCall AsyncServerStreamingCall(TRequest request, ClientInterceptorContext context, AsyncServerStreamingCallContinuation continuation) + where TRequest : class + where TResponse : class + { + return continuation(request, context); + } + + /// + /// Intercepts an asynchronous invocation of a client streaming call. + /// + /// + /// The + /// associated with the current invocation. + /// + /// + /// The callback that continues the invocation process. + /// This can be invoked zero or more times by the interceptor. + /// The interceptor can invoke the continuation passing the given + /// context argument, or substitute as it sees fit. + /// + /// + /// An instance of + /// representing an asynchronous client-streaming invocation. + /// The interceptor can simply return the return value of the + /// continuation delegate passed to it intact, or construct its + /// own substitute as it sees fit. + /// + public virtual AsyncClientStreamingCall AsyncClientStreamingCall(ClientInterceptorContext context, AsyncClientStreamingCallContinuation continuation) + where TRequest : class + where TResponse : class + { + return continuation(context); + } + + /// + /// Intercepts an asynchronous invocation of a duplex streaming call. + /// + /// + /// The + /// associated with the current invocation. + /// + /// + /// The callback that continues the invocation process. + /// This can be invoked zero or more times by the interceptor. + /// The interceptor can invoke the continuation passing the given + /// context argument, or substitute as it sees fit. + /// + /// + /// An instance of + /// representing an asynchronous duplex-streaming invocation. + /// The interceptor can simply return the return value of the + /// continuation delegate passed to it intact, or construct its + /// own substitute as it sees fit. + /// + public virtual AsyncDuplexStreamingCall AsyncDuplexStreamingCall(ClientInterceptorContext context, AsyncDuplexStreamingCallContinuation continuation) + where TRequest : class + where TResponse : class + { + return continuation(context); + } + + /// + /// Server-side handler for intercepting and incoming unary call. + /// + /// Request message type for this method. + /// Response message type for this method. + /// The request value of the incoming invocation. + /// + /// An instance of representing + /// the context of the invocation. + /// + /// + /// A delegate that asynchronously proceeds with the invocation, calling + /// the next interceptor in the chain, or the service request handler, + /// in case of the last interceptor and return the response value of + /// the RPC. The interceptor can choose to call it zero or more times + /// at its discretion. + /// + /// + /// A future representing the response value of the RPC. The interceptor + /// can simply return the return value from the continuation intact, + /// or an arbitrary response value as it sees fit. + /// + public virtual Task UnaryServerHandler(TRequest request, ServerCallContext context, UnaryServerMethod continuation) + where TRequest : class + where TResponse : class + { + return continuation(request, context); + } + + /// + /// Server-side handler for intercepting client streaming call. + /// + /// Request message type for this method. + /// Response message type for this method. + /// The request stream of the incoming invocation. + /// + /// An instance of representing + /// the context of the invocation. + /// + /// + /// A delegate that asynchronously proceeds with the invocation, calling + /// the next interceptor in the chain, or the service request handler, + /// in case of the last interceptor and return the response value of + /// the RPC. The interceptor can choose to call it zero or more times + /// at its discretion. + /// + /// + /// A future representing the response value of the RPC. The interceptor + /// can simply return the return value from the continuation intact, + /// or an arbitrary response value as it sees fit. The interceptor has + /// the ability to wrap or substitute the request stream when calling + /// the continuation. + /// + public virtual Task ClientStreamingServerHandler(IAsyncStreamReader requestStream, ServerCallContext context, ClientStreamingServerMethod continuation) + where TRequest : class + where TResponse : class + { + return continuation(requestStream, context); + } + + /// + /// Server-side handler for intercepting server streaming call. + /// + /// Request message type for this method. + /// Response message type for this method. + /// The request value of the incoming invocation. + /// The response stream of the incoming invocation. + /// + /// An instance of representing + /// the context of the invocation. + /// + /// + /// A delegate that asynchronously proceeds with the invocation, calling + /// the next interceptor in the chain, or the service request handler, + /// in case of the last interceptor and the interceptor can choose to + /// call it zero or more times at its discretion. The interceptor has + /// the ability to wrap or substitute the request value and the response stream + /// when calling the continuation. + /// + public virtual Task ServerStreamingServerHandler(TRequest request, IServerStreamWriter responseStream, ServerCallContext context, ServerStreamingServerMethod continuation) + where TRequest : class + where TResponse : class + { + return continuation(request, responseStream, context); + } + + /// + /// Server-side handler for intercepting bidirectional streaming calls. + /// + /// Request message type for this method. + /// Response message type for this method. + /// The request stream of the incoming invocation. + /// The response stream of the incoming invocation. + /// + /// An instance of representing + /// the context of the invocation. + /// + /// + /// A delegate that asynchronously proceeds with the invocation, calling + /// the next interceptor in the chain, or the service request handler, + /// in case of the last interceptor and the interceptor can choose to + /// call it zero or more times at its discretion. The interceptor has + /// the ability to wrap or substitute the request and response streams + /// when calling the continuation. + /// + public virtual Task DuplexStreamingServerHandler(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context, DuplexStreamingServerMethod continuation) + where TRequest : class + where TResponse : class + { + return continuation(requestStream, responseStream, context); + } + } +} diff --git a/src/csharp/Grpc.Core.Api/Internal/CodeAnalysisAttributes.cs b/src/csharp/Grpc.Core.Api/Internal/CodeAnalysisAttributes.cs new file mode 100644 index 00000000..962d5808 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Internal/CodeAnalysisAttributes.cs @@ -0,0 +1,151 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +// Content of this file is copied with permission from: +// https://github.com/dotnet/runtime/tree/e2e43f44f1032780fa7c2bb965153c9da615c3d0/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis +// These types are intented to be added as internalized source to libraries and apps that want to +// use them without requiring a dependency on .NET 5. + +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Indicates that certain members on a specified are accessed dynamically, + /// for example through . + /// + /// + /// This allows tools to understand which members are being accessed during the execution + /// of a program. + /// + /// This attribute is valid on members whose type is or . + /// + /// When this attribute is applied to a location of type , the assumption is + /// that the string represents a fully qualified type name. + /// + /// If the attribute is applied to a method it's treated as a special case and it implies + /// the attribute should be applied to the "this" parameter of the method. As such the attribute + /// should only be used on instance methods of types assignable to System.Type (or string, but no methods + /// will use it there). + /// + [AttributeUsage( + AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter | + AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Method, + Inherited = false)] + internal sealed class DynamicallyAccessedMembersAttribute : Attribute + { + /// + /// Initializes a new instance of the class + /// with the specified member types. + /// + /// The types of members dynamically accessed. + public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes) + { + MemberTypes = memberTypes; + } + + /// + /// Gets the which specifies the type + /// of members dynamically accessed. + /// + public DynamicallyAccessedMemberTypes MemberTypes { get; } + } + + /// + /// Specifies the types of members that are dynamically accessed. + /// + /// This enumeration has a attribute that allows a + /// bitwise combination of its member values. + /// + [Flags] + internal enum DynamicallyAccessedMemberTypes + { + /// + /// Specifies no members. + /// + None = 0, + + /// + /// Specifies the default, parameterless public constructor. + /// + PublicParameterlessConstructor = 0x0001, + + /// + /// Specifies all public constructors. + /// + PublicConstructors = 0x0002 | PublicParameterlessConstructor, + + /// + /// Specifies all non-public constructors. + /// + NonPublicConstructors = 0x0004, + + /// + /// Specifies all public methods. + /// + PublicMethods = 0x0008, + + /// + /// Specifies all non-public methods. + /// + NonPublicMethods = 0x0010, + + /// + /// Specifies all public fields. + /// + PublicFields = 0x0020, + + /// + /// Specifies all non-public fields. + /// + NonPublicFields = 0x0040, + + /// + /// Specifies all public nested types. + /// + PublicNestedTypes = 0x0080, + + /// + /// Specifies all non-public nested types. + /// + NonPublicNestedTypes = 0x0100, + + /// + /// Specifies all public properties. + /// + PublicProperties = 0x0200, + + /// + /// Specifies all non-public properties. + /// + NonPublicProperties = 0x0400, + + /// + /// Specifies all public events. + /// + PublicEvents = 0x0800, + + /// + /// Specifies all non-public events. + /// + NonPublicEvents = 0x1000, + + /// + /// Specifies all members. + /// + All = ~None + } +} diff --git a/src/csharp/Grpc.Core.Api/Internal/UnimplementedCallInvoker.cs b/src/csharp/Grpc.Core.Api/Internal/UnimplementedCallInvoker.cs new file mode 100644 index 00000000..c7be74ec --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Internal/UnimplementedCallInvoker.cs @@ -0,0 +1,60 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Call invoker that throws NotImplementedException for all requests. + /// + internal class UnimplementedCallInvoker : CallInvoker + { + public UnimplementedCallInvoker() + { + } + + public override TResponse BlockingUnaryCall(Method method, string host, CallOptions options, TRequest request) + { + throw new NotImplementedException(); + } + + public override AsyncUnaryCall AsyncUnaryCall(Method method, string host, CallOptions options, TRequest request) + { + throw new NotImplementedException(); + } + + public override AsyncServerStreamingCall AsyncServerStreamingCall(Method method, string host, CallOptions options, TRequest request) + { + throw new NotImplementedException(); + } + + public override AsyncClientStreamingCall AsyncClientStreamingCall(Method method, string host, CallOptions options) + { + throw new NotImplementedException(); + } + + public override AsyncDuplexStreamingCall AsyncDuplexStreamingCall(Method method, string host, CallOptions options) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/csharp/Grpc.Core.Api/KeyCertificatePair.cs b/src/csharp/Grpc.Core.Api/KeyCertificatePair.cs new file mode 100644 index 00000000..2ebe2fb8 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/KeyCertificatePair.cs @@ -0,0 +1,68 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; + +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Key certificate pair (in PEM encoding). + /// + public sealed class KeyCertificatePair + { + readonly string certificateChain; + readonly string privateKey; + + /// + /// Creates a new certificate chain - private key pair. + /// + /// PEM encoded certificate chain. + /// PEM encoded private key. + public KeyCertificatePair(string certificateChain, string privateKey) + { + this.certificateChain = GrpcPreconditions.CheckNotNull(certificateChain, "certificateChain"); + this.privateKey = GrpcPreconditions.CheckNotNull(privateKey, "privateKey"); + } + + /// + /// PEM encoded certificate chain. + /// + public string CertificateChain + { + get + { + return certificateChain; + } + } + + /// + /// PEM encoded private key. + /// + public string PrivateKey + { + get + { + return privateKey; + } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/Marshaller.cs b/src/csharp/Grpc.Core.Api/Marshaller.cs new file mode 100644 index 00000000..34a1849c --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Marshaller.cs @@ -0,0 +1,138 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Encapsulates the logic for serializing and deserializing messages. + /// + public class Marshaller + { + readonly Func serializer; + readonly Func deserializer; + + readonly Action contextualSerializer; + readonly Func contextualDeserializer; + + /// + /// Initializes a new marshaller from simple serialize/deserialize functions. + /// + /// Function that will be used to serialize messages. + /// Function that will be used to deserialize messages. + public Marshaller(Func serializer, Func deserializer) + { + this.serializer = GrpcPreconditions.CheckNotNull(serializer, nameof(serializer)); + this.deserializer = GrpcPreconditions.CheckNotNull(deserializer, nameof(deserializer)); + // contextual serialization/deserialization is emulated to make the marshaller + // usable with the grpc library (required for backward compatibility). + this.contextualSerializer = EmulateContextualSerializer; + this.contextualDeserializer = EmulateContextualDeserializer; + } + + /// + /// Initializes a new marshaller from serialize/deserialize fuctions that can access serialization and deserialization + /// context. Compared to the simple serializer/deserializer functions, using the contextual version provides more + /// flexibility and can lead to increased efficiency (and better performance). + /// Note: This constructor is part of an experimental API that can change or be removed without any prior notice. + /// + /// Function that will be used to serialize messages. + /// Function that will be used to deserialize messages. + public Marshaller(Action serializer, Func deserializer) + { + this.contextualSerializer = GrpcPreconditions.CheckNotNull(serializer, nameof(serializer)); + this.contextualDeserializer = GrpcPreconditions.CheckNotNull(deserializer, nameof(deserializer)); + // gRPC only uses contextual serializer/deserializer internally, so emulating the legacy + // (de)serializer is not necessary. + this.serializer = (msg) => { throw new NotImplementedException(); }; + this.deserializer = (payload) => { throw new NotImplementedException(); }; + } + + /// + /// Gets the serializer function. + /// + public Func Serializer => this.serializer; + + /// + /// Gets the deserializer function. + /// + public Func Deserializer => this.deserializer; + + /// + /// Gets the serializer function. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public Action ContextualSerializer => this.contextualSerializer; + + /// + /// Gets the serializer function. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public Func ContextualDeserializer => this.contextualDeserializer; + + // for backward compatibility, emulate the contextual serializer using the simple one + private void EmulateContextualSerializer(T message, SerializationContext context) + { + var payload = this.serializer(message); + context.Complete(payload); + } + + // for backward compatibility, emulate the contextual deserializer using the simple one + private T EmulateContextualDeserializer(DeserializationContext context) + { + return this.deserializer(context.PayloadAsNewBuffer()); + } + } + + /// + /// Utilities for creating marshallers. + /// + public static class Marshallers + { + /// + /// Creates a marshaller from specified serializer and deserializer. + /// + public static Marshaller Create(Func serializer, Func deserializer) + { + return new Marshaller(serializer, deserializer); + } + + /// + /// Creates a marshaller from specified contextual serializer and deserializer. + /// Note: This method is part of an experimental API that can change or be removed without any prior notice. + /// + public static Marshaller Create(Action serializer, Func deserializer) + { + return new Marshaller(serializer, deserializer); + } + + /// + /// Returns a marshaller for string type. This is useful for testing. + /// + public static Marshaller StringMarshaller + { + get + { + return new Marshaller(System.Text.Encoding.UTF8.GetBytes, + System.Text.Encoding.UTF8.GetString); + } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/Metadata.cs b/src/csharp/Grpc.Core.Api/Metadata.cs new file mode 100644 index 00000000..50b8fd56 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Metadata.cs @@ -0,0 +1,497 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using Grpc.Core.Api.Utils; + +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// A collection of metadata entries that can be exchanged during a call. + /// gRPC supports these types of metadata: + /// + /// Request headersare sent by the client at the beginning of a remote call before any request messages are sent. + /// Response headersare sent by the server at the beginning of a remote call handler before any response messages are sent. + /// Response trailersare sent by the server at the end of a remote call along with resulting call status. + /// + /// + public sealed class Metadata : IList + { + /// + /// All binary headers should have this suffix. + /// + public const string BinaryHeaderSuffix = "-bin"; + + /// + /// An read-only instance of metadata containing no entries. + /// + public static readonly Metadata Empty = new Metadata().Freeze(); + + /// + /// To be used in initial metadata to request specific compression algorithm + /// for given call. Direct selection of compression algorithms is an internal + /// feature and is not part of public API. + /// + internal const string CompressionRequestAlgorithmMetadataKey = "grpc-internal-encoding-request"; + static readonly Encoding EncodingASCII = System.Text.Encoding.ASCII; + + readonly List entries; + bool readOnly; + + /// + /// Initializes a new instance of Metadata. + /// + public Metadata() + { + this.entries = new List(); + } + + /// + /// Makes this object read-only. + /// + /// this object + internal Metadata Freeze() + { + this.readOnly = true; + return this; + } + + /// + /// Gets the last metadata entry with the specified key. + /// If there are no matching entries then null is returned. + /// + public Entry Get(string key) + { + for (int i = entries.Count - 1; i >= 0; i--) + { + if (entries[i].KeyEqualsIgnoreCase(key)) + { + return entries[i]; + } + } + + return null; + } + + /// + /// Gets the string value of the last metadata entry with the specified key. + /// If the metadata entry is binary then an exception is thrown. + /// If there are no matching entries then null is returned. + /// + public string GetValue(string key) + { + return Get(key)?.Value; + } + + /// + /// Gets the bytes value of the last metadata entry with the specified key. + /// If the metadata entry is not binary the string value will be returned as ASCII encoded bytes. + /// If there are no matching entries then null is returned. + /// + public byte[] GetValueBytes(string key) + { + return Get(key)?.ValueBytes; + } + + /// + /// Gets all metadata entries with the specified key. + /// + public IEnumerable GetAll(string key) + { + for (int i = 0; i < entries.Count; i++) + { + if (entries[i].KeyEqualsIgnoreCase(key)) + { + yield return entries[i]; + } + } + } + + /// + /// Adds a new ASCII-valued metadata entry. See Metadata.Entry constructor for params. + /// + public void Add(string key, string value) + { + Add(new Entry(key, value)); + } + + /// + /// Adds a new binary-valued metadata entry. See Metadata.Entry constructor for params. + /// + public void Add(string key, byte[] valueBytes) + { + Add(new Entry(key, valueBytes)); + } + + #region IList members + + + /// + /// + /// + public int IndexOf(Metadata.Entry item) + { + return entries.IndexOf(item); + } + + /// + /// + /// + public void Insert(int index, Metadata.Entry item) + { + GrpcPreconditions.CheckNotNull(item); + CheckWriteable(); + entries.Insert(index, item); + } + + /// + /// + /// + public void RemoveAt(int index) + { + CheckWriteable(); + entries.RemoveAt(index); + } + + /// + /// + /// + public Metadata.Entry this[int index] + { + get + { + return entries[index]; + } + + set + { + GrpcPreconditions.CheckNotNull(value); + CheckWriteable(); + entries[index] = value; + } + } + + /// + /// + /// + public void Add(Metadata.Entry item) + { + GrpcPreconditions.CheckNotNull(item); + CheckWriteable(); + entries.Add(item); + } + + /// + /// + /// + public void Clear() + { + CheckWriteable(); + entries.Clear(); + } + + /// + /// + /// + public bool Contains(Metadata.Entry item) + { + return entries.Contains(item); + } + + /// + /// + /// + public void CopyTo(Metadata.Entry[] array, int arrayIndex) + { + entries.CopyTo(array, arrayIndex); + } + + /// + /// + /// + public int Count + { + get { return entries.Count; } + } + + /// + /// + /// + public bool IsReadOnly + { + get { return readOnly; } + } + + /// + /// + /// + public bool Remove(Metadata.Entry item) + { + CheckWriteable(); + return entries.Remove(item); + } + + /// + /// + /// + public IEnumerator GetEnumerator() + { + return entries.GetEnumerator(); + } + + IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return entries.GetEnumerator(); + } + + private void CheckWriteable() + { + GrpcPreconditions.CheckState(!readOnly, "Object is read only"); + } + + #endregion + + /// + /// Metadata entry + /// + public class Entry + { + readonly string key; + readonly string value; + readonly byte[] valueBytes; + + private Entry(string key, string value, byte[] valueBytes) + { + this.key = key; + this.value = value; + this.valueBytes = valueBytes; + } + + /// + /// Initializes a new instance of the struct with a binary value. + /// + /// Metadata key. Gets converted to lowercase. Needs to have suffix indicating a binary valued metadata entry. Can only contain lowercase alphanumeric characters, underscores, hyphens and dots. + /// Value bytes. + public Entry(string key, byte[] valueBytes) + { + this.key = NormalizeKey(key); + GrpcPreconditions.CheckArgument(HasBinaryHeaderSuffix(this.key), + "Key for binary valued metadata entry needs to have suffix indicating binary value."); + this.value = null; + GrpcPreconditions.CheckNotNull(valueBytes, "valueBytes"); + this.valueBytes = new byte[valueBytes.Length]; + Buffer.BlockCopy(valueBytes, 0, this.valueBytes, 0, valueBytes.Length); // defensive copy to guarantee immutability + } + + /// + /// Initializes a new instance of the struct with an ASCII value. + /// + /// Metadata key. Gets converted to lowercase. Must not use suffix indicating a binary valued metadata entry. Can only contain lowercase alphanumeric characters, underscores, hyphens and dots. + /// Value string. Only ASCII characters are allowed. + public Entry(string key, string value) + { + this.key = NormalizeKey(key); + GrpcPreconditions.CheckArgument(!HasBinaryHeaderSuffix(this.key), + "Key for ASCII valued metadata entry cannot have suffix indicating binary value."); + this.value = GrpcPreconditions.CheckNotNull(value, "value"); + this.valueBytes = null; + } + + /// + /// Gets the metadata entry key. + /// + public string Key + { + get + { + return this.key; + } + } + + /// + /// Gets the binary value of this metadata entry. + /// If the metadata entry is not binary the string value will be returned as ASCII encoded bytes. + /// + public byte[] ValueBytes + { + get + { + if (valueBytes == null) + { + return EncodingASCII.GetBytes(value); + } + + // defensive copy to guarantee immutability + var bytes = new byte[valueBytes.Length]; + Buffer.BlockCopy(valueBytes, 0, bytes, 0, valueBytes.Length); + return bytes; + } + } + + /// + /// Gets the string value of this metadata entry. + /// If the metadata entry is binary then an exception is thrown. + /// + public string Value + { + get + { + GrpcPreconditions.CheckState(!IsBinary, "Cannot access string value of a binary metadata entry"); + return value; + } + } + + /// + /// Returns true if this entry is a binary-value entry. + /// + public bool IsBinary + { + get + { + return value == null; + } + } + + /// + /// Returns a that represents the current . + /// + public override string ToString() + { + if (IsBinary) + { + return string.Format("[Entry: key={0}, valueBytes={1}]", key, valueBytes); + } + + return string.Format("[Entry: key={0}, value={1}]", key, value); + } + + /// + /// Gets the serialized value for this entry. For binary metadata entries, this leaks + /// the internal valueBytes byte array and caller must not change contents of it. + /// + internal byte[] GetSerializedValueUnsafe() + { + return valueBytes ?? EncodingASCII.GetBytes(value); + } + + internal bool KeyEqualsIgnoreCase(string key) + { + // NormalizeKey() uses ToLowerInvariant() to lowercase keys, so we'd like to use the same invariant culture + // for comparisons to get valid results. StringComparison.InvariantCultureIgnoreCase isn't available + // on all the frameworks we're targeting, but since we know that the Entry's key has already + // been checked by IsValidKey and it only contains a subset of ASCII, using StringComparison.OrdinalIgnoreCase + // is also fine. + return string.Equals(this.key, key, StringComparison.OrdinalIgnoreCase); + } + + /// + /// Creates a binary value or ascii value metadata entry from data received from the native layer. + /// We trust C core to give us well-formed data, so we don't perform any checks or defensive copying. + /// + internal static Entry CreateUnsafe(string key, IntPtr source, int length) + { + if (HasBinaryHeaderSuffix(key)) + { + byte[] arr; + if (length == 0) + { + arr = EmptyByteArray; + } + else + { // create a local copy in a fresh array + arr = new byte[length]; + Marshal.Copy(source, arr, 0, length); + } + return new Entry(key, null, arr); + } + else + { + string s = EncodingASCII.GetString(source, length); + return new Entry(key, s, null); + } + } + + static readonly byte[] EmptyByteArray = new byte[0]; + + private static string NormalizeKey(string key) + { + GrpcPreconditions.CheckNotNull(key, "key"); + + GrpcPreconditions.CheckArgument(IsValidKey(key, out bool isLowercase), + "Metadata entry key not valid. Keys can only contain lowercase alphanumeric characters, underscores, hyphens and dots."); + if (isLowercase) + { + // save allocation of a new string if already lowercase + return key; + } + + return key.ToLowerInvariant(); + } + + private static bool IsValidKey(string input, out bool isLowercase) + { + isLowercase = true; + for (int i = 0; i < input.Length; i++) + { + char c = input[i]; + if ('a' <= c && c <= 'z' || + '0' <= c && c <= '9' || + c == '.' || + c == '_' || + c == '-' ) + continue; + + if ('A' <= c && c <= 'Z') + { + isLowercase = false; + continue; + } + + return false; + } + + return true; + } + + /// + /// Returns true if the key has "-bin" binary header suffix. + /// + private static bool HasBinaryHeaderSuffix(string key) + { + // We don't use just string.EndsWith because its implementation is extremely slow + // on CoreCLR and we've seen significant differences in gRPC benchmarks caused by it. + // See https://github.com/dotnet/coreclr/issues/5612 + + int len = key.Length; + if (len >= 4 && + key[len - 4] == '-' && + key[len - 3] == 'b' && + key[len - 2] == 'i' && + key[len - 1] == 'n') + { + return true; + } + return false; + } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/Method.cs b/src/csharp/Grpc.Core.Api/Method.cs new file mode 100644 index 00000000..8353e6af --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Method.cs @@ -0,0 +1,176 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Method types supported by gRPC. + /// + public enum MethodType + { + /// Single request sent from client, single response received from server. + Unary, + + /// Stream of request sent from client, single response received from server. + ClientStreaming, + + /// Single request sent from client, stream of responses received from server. + ServerStreaming, + + /// Both server and client can stream arbitrary number of requests and responses simultaneously. + DuplexStreaming + } + + /// + /// A non-generic representation of a remote method. + /// + public interface IMethod + { + /// + /// Gets the type of the method. + /// + MethodType Type { get; } + + /// + /// Gets the name of the service to which this method belongs. + /// + string ServiceName { get; } + + /// + /// Gets the unqualified name of the method. + /// + string Name { get; } + + /// + /// Gets the fully qualified name of the method. On the server side, methods are dispatched + /// based on this name. + /// + string FullName { get; } + } + + /// + /// A description of a remote method. + /// + /// Request message type for this method. + /// Response message type for this method. + public class Method : IMethod + { + readonly MethodType type; + readonly string serviceName; + readonly string name; + readonly Marshaller requestMarshaller; + readonly Marshaller responseMarshaller; + readonly string fullName; + + /// + /// Initializes a new instance of the Method class. + /// + /// Type of method. + /// Name of service this method belongs to. + /// Unqualified name of the method. + /// Marshaller used for request messages. + /// Marshaller used for response messages. + public Method(MethodType type, string serviceName, string name, Marshaller requestMarshaller, Marshaller responseMarshaller) + { + this.type = type; + this.serviceName = GrpcPreconditions.CheckNotNull(serviceName, "serviceName"); + this.name = GrpcPreconditions.CheckNotNull(name, "name"); + this.requestMarshaller = GrpcPreconditions.CheckNotNull(requestMarshaller, "requestMarshaller"); + this.responseMarshaller = GrpcPreconditions.CheckNotNull(responseMarshaller, "responseMarshaller"); + this.fullName = GetFullName(serviceName, name); + } + + /// + /// Gets the type of the method. + /// + public MethodType Type + { + get + { + return this.type; + } + } + + /// + /// Gets the name of the service to which this method belongs. + /// + public string ServiceName + { + get + { + return this.serviceName; + } + } + + /// + /// Gets the unqualified name of the method. + /// + public string Name + { + get + { + return this.name; + } + } + + /// + /// Gets the marshaller used for request messages. + /// + public Marshaller RequestMarshaller + { + get + { + return this.requestMarshaller; + } + } + + /// + /// Gets the marshaller used for response messages. + /// + public Marshaller ResponseMarshaller + { + get + { + return this.responseMarshaller; + } + } + + /// + /// Gets the fully qualified name of the method. On the server side, methods are dispatched + /// based on this name. + /// + public string FullName + { + get + { + return this.fullName; + } + } + + /// + /// Gets full name of the method including the service name. + /// + internal static string GetFullName(string serviceName, string methodName) + { + return "/" + serviceName + "/" + methodName; + } + } +} diff --git a/src/csharp/Grpc.Core.Api/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core.Api/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..5d0b5e27 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.Core.Api")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: InternalsVisibleTo("Grpc.Core,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] +[assembly: InternalsVisibleTo("Grpc.Core.Tests,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] +[assembly: InternalsVisibleTo("Grpc.Core.Testing,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] +[assembly: InternalsVisibleTo("Grpc.IntegrationTesting,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] +[assembly: InternalsVisibleTo("Grpc.Microbenchmarks,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] diff --git a/src/csharp/Grpc.Core.Api/RpcException.cs b/src/csharp/Grpc.Core.Api/RpcException.cs new file mode 100644 index 00000000..cdc55e1f --- /dev/null +++ b/src/csharp/Grpc.Core.Api/RpcException.cs @@ -0,0 +1,109 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Thrown when remote procedure call fails. Every RpcException is associated with a resulting of the call. + /// + public class RpcException : Exception + { + private readonly Status status; + private readonly Metadata trailers; + + /// + /// Creates a new RpcException associated with given status. + /// + /// Resulting status of a call. + public RpcException(Status status) : this(status, Metadata.Empty, status.ToString()) + { + } + + /// + /// Creates a new RpcException associated with given status and message. + /// NOTE: the exception message is not sent to the remote peer. Use status.Details to pass error + /// details to the peer. + /// + /// Resulting status of a call. + /// The exception message. + public RpcException(Status status, string message) : this(status, Metadata.Empty, message) + { + } + + /// + /// Creates a new RpcException associated with given status and trailing response metadata. + /// + /// Resulting status of a call. + /// Response trailing metadata. + public RpcException(Status status, Metadata trailers) : this(status, trailers, status.ToString()) + { + } + + /// + /// Creates a new RpcException associated with given status, message and trailing response metadata. + /// NOTE: the exception message is not sent to the remote peer. Use status.Details to pass error + /// details to the peer. + /// + /// Resulting status of a call. + /// Response trailing metadata. + /// The exception message. + public RpcException(Status status, Metadata trailers, string message) : base(message) + { + this.status = status; + this.trailers = GrpcPreconditions.CheckNotNull(trailers); + } + + /// + /// Resulting status of the call. + /// + public Status Status + { + get + { + return status; + } + } + + /// + /// Returns the status code of the call, as a convenient alternative to Status.StatusCode. + /// + public StatusCode StatusCode + { + get + { + return status.StatusCode; + } + } + + /// + /// Gets the call trailing metadata. + /// Trailers only have meaningful content for client-side calls (in which case they represent the trailing metadata sent by the server when closing the call). + /// Instances of RpcException thrown by the server-side part of the stack will have trailers always set to empty. + /// + public Metadata Trailers + { + get + { + return trailers; + } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/SerializationContext.cs b/src/csharp/Grpc.Core.Api/SerializationContext.cs new file mode 100644 index 00000000..021ca29c --- /dev/null +++ b/src/csharp/Grpc.Core.Api/SerializationContext.cs @@ -0,0 +1,69 @@ +#region Copyright notice and license + +// Copyright 2018 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Buffers; + +namespace Grpc.Core +{ + /// + /// Provides storage for payload when serializing a message. + /// + public abstract class SerializationContext + { + /// + /// Use the byte array as serialized form of current message and mark serialization process as complete. + /// Complete(byte[]) can only be called once. By calling this method the caller gives up the ownership of the + /// payload which must not be accessed afterwards. + /// + /// the serialized form of current message + public virtual void Complete(byte[] payload) + { + throw new NotImplementedException(); + } + + /// + /// Gets buffer writer that can be used to write the serialized data. Once serialization is finished, + /// Complete() needs to be called. + /// + public virtual IBufferWriter GetBufferWriter() + { + throw new NotImplementedException(); + } + + /// + /// Sets the payload length when writing serialized data into a buffer writer. If the serializer knows the full payload + /// length in advance, providing that information before obtaining the buffer writer using GetBufferWriter() can improve + /// serialization efficiency by avoiding copies. The provided payload length must be the same as the data written to the writer. + /// Calling this method is optional. If the payload length is not set then the length is calculated using the data written to + /// the buffer writer when Complete() is called. + /// + /// The total length of the payload in bytes. + public virtual void SetPayloadLength(int payloadLength) + { + } + + /// + /// Complete the payload written to the buffer writer. Complete() can only be called once. + /// + public virtual void Complete() + { + throw new NotImplementedException(); + } + } +} diff --git a/src/csharp/Grpc.Core.Api/ServerCallContext.cs b/src/csharp/Grpc.Core.Api/ServerCallContext.cs new file mode 100644 index 00000000..ece2e5a5 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/ServerCallContext.cs @@ -0,0 +1,163 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Grpc.Core +{ + /// + /// Context for a server-side call. + /// + public abstract class ServerCallContext + { + private Dictionary userState; + + /// + /// Creates a new instance of ServerCallContext. + /// + protected ServerCallContext() + { + } + + /// + /// Asynchronously sends response headers for the current call to the client. This method may only be invoked once for each call and needs to be invoked + /// before any response messages are written. Writing the first response message implicitly sends empty response headers if WriteResponseHeadersAsync haven't + /// been called yet. + /// + /// The response headers to send. + /// The task that finished once response headers have been written. + public Task WriteResponseHeadersAsync(Metadata responseHeaders) + { + return WriteResponseHeadersAsyncCore(responseHeaders); + } + + /// + /// Creates a propagation token to be used to propagate call context to a child call. + /// + public ContextPropagationToken CreatePropagationToken(ContextPropagationOptions options = null) + { + return CreatePropagationTokenCore(options); + } + + /// Name of method called in this RPC. + public string Method => MethodCore; + + /// Name of host called in this RPC. + public string Host => HostCore; + + /// Address of the remote endpoint in URI format. + public string Peer => PeerCore; + + /// Deadline for this RPC. The call will be automatically cancelled once the deadline is exceeded. + public DateTime Deadline => DeadlineCore; + + /// Initial metadata sent by client. + public Metadata RequestHeaders => RequestHeadersCore; + + /// Cancellation token signals when call is cancelled. It is also triggered when the deadline is exceeeded or there was some other error (e.g. network problem). + public CancellationToken CancellationToken => CancellationTokenCore; + + /// Trailers to send back to client after RPC finishes. + public Metadata ResponseTrailers => ResponseTrailersCore; + + /// Status to send back to client after RPC finishes. + public Status Status + { + get + { + return StatusCore; + } + + set + { + StatusCore = value; + } + } + + /// + /// Allows setting write options for the following write. + /// For streaming response calls, this property is also exposed as on IServerStreamWriter for convenience. + /// Both properties are backed by the same underlying value. + /// + public WriteOptions WriteOptions + { + get + { + return WriteOptionsCore; + } + + set + { + WriteOptionsCore = value; + } + } + + /// + /// Gets the AuthContext associated with this call. + /// Note: Access to AuthContext is an experimental API that can change without any prior notice. + /// + public AuthContext AuthContext => AuthContextCore; + + /// + /// Gets a dictionary that can be used by the various interceptors and handlers of this + /// call to store arbitrary state. + /// + public IDictionary UserState => UserStateCore; + + /// Provides implementation of a non-virtual public member. + protected abstract Task WriteResponseHeadersAsyncCore(Metadata responseHeaders); + /// Provides implementation of a non-virtual public member. + protected abstract ContextPropagationToken CreatePropagationTokenCore(ContextPropagationOptions options); + /// Provides implementation of a non-virtual public member. + protected abstract string MethodCore { get; } + /// Provides implementation of a non-virtual public member. + protected abstract string HostCore { get; } + /// Provides implementation of a non-virtual public member. + protected abstract string PeerCore { get; } + /// Provides implementation of a non-virtual public member. + protected abstract DateTime DeadlineCore { get; } + /// Provides implementation of a non-virtual public member. + protected abstract Metadata RequestHeadersCore { get; } + /// Provides implementation of a non-virtual public member. + protected abstract CancellationToken CancellationTokenCore { get; } + /// Provides implementation of a non-virtual public member. + protected abstract Metadata ResponseTrailersCore { get; } + /// Provides implementation of a non-virtual public member. + protected abstract Status StatusCore { get; set; } + /// Provides implementation of a non-virtual public member. + protected abstract WriteOptions WriteOptionsCore { get; set; } + /// Provides implementation of a non-virtual public member. + protected abstract AuthContext AuthContextCore { get; } + /// Provides implementation of a non-virtual public member. + protected virtual IDictionary UserStateCore + { + get + { + if (userState == null) + { + userState = new Dictionary(); + } + + return userState; + } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/ServerMethods.cs b/src/csharp/Grpc.Core.Api/ServerMethods.cs new file mode 100644 index 00000000..ad0eef9f --- /dev/null +++ b/src/csharp/Grpc.Core.Api/ServerMethods.cs @@ -0,0 +1,58 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Threading.Tasks; + +namespace Grpc.Core +{ + /// + /// Server-side handler for unary call. + /// + /// Request message type for this method. + /// Response message type for this method. + public delegate Task UnaryServerMethod(TRequest request, ServerCallContext context) + where TRequest : class + where TResponse : class; + + /// + /// Server-side handler for client streaming call. + /// + /// Request message type for this method. + /// Response message type for this method. + public delegate Task ClientStreamingServerMethod(IAsyncStreamReader requestStream, ServerCallContext context) + where TRequest : class + where TResponse : class; + + /// + /// Server-side handler for server streaming call. + /// + /// Request message type for this method. + /// Response message type for this method. + public delegate Task ServerStreamingServerMethod(TRequest request, IServerStreamWriter responseStream, ServerCallContext context) + where TRequest : class + where TResponse : class; + + /// + /// Server-side handler for bidi streaming call. + /// + /// Request message type for this method. + /// Response message type for this method. + public delegate Task DuplexStreamingServerMethod(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + where TRequest : class + where TResponse : class; +} diff --git a/src/csharp/Grpc.Core.Api/ServerServiceDefinition.cs b/src/csharp/Grpc.Core.Api/ServerServiceDefinition.cs new file mode 100644 index 00000000..8c76f0bc --- /dev/null +++ b/src/csharp/Grpc.Core.Api/ServerServiceDefinition.cs @@ -0,0 +1,161 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; + +namespace Grpc.Core +{ + /// + /// Stores mapping of methods to server call handlers. + /// Normally, the ServerServiceDefinition objects will be created by the BindService factory method + /// that is part of the autogenerated code for a protocol buffers service definition. + /// + public class ServerServiceDefinition + { + readonly IReadOnlyList> addMethodActions; + + internal ServerServiceDefinition(List> addMethodActions) + { + this.addMethodActions = addMethodActions.AsReadOnly(); + } + + /// + /// Forwards all the previously stored AddMethod calls to the service binder. + /// + internal void BindService(ServiceBinderBase serviceBinder) + { + foreach (var addMethodAction in addMethodActions) + { + addMethodAction(serviceBinder); + } + } + + /// + /// Creates a new builder object for ServerServiceDefinition. + /// + /// The builder object. + public static Builder CreateBuilder() + { + return new Builder(); + } + + /// + /// Builder class for . + /// + public class Builder + { + // to maintain legacy behavior, we need to detect duplicate keys and throw the same exception as before + readonly Dictionary duplicateDetector = new Dictionary(); + // for each AddMethod call, we store an action that will later register the method and handler with ServiceBinderBase + readonly List> addMethodActions = new List>(); + + /// + /// Creates a new instance of builder. + /// + public Builder() + { + } + + /// + /// Adds a definition for a single request - single response method. + /// + /// The request message class. + /// The response message class. + /// The method. + /// The method handler. + /// This builder instance. + public Builder AddMethod( + Method method, + UnaryServerMethod handler) + where TRequest : class + where TResponse : class + { + duplicateDetector.Add(method.FullName, null); + addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); + return this; + } + + /// + /// Adds a definition for a client streaming method. + /// + /// The request message class. + /// The response message class. + /// The method. + /// The method handler. + /// This builder instance. + public Builder AddMethod( + Method method, + ClientStreamingServerMethod handler) + where TRequest : class + where TResponse : class + { + duplicateDetector.Add(method.FullName, null); + addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); + return this; + } + + /// + /// Adds a definition for a server streaming method. + /// + /// The request message class. + /// The response message class. + /// The method. + /// The method handler. + /// This builder instance. + public Builder AddMethod( + Method method, + ServerStreamingServerMethod handler) + where TRequest : class + where TResponse : class + { + duplicateDetector.Add(method.FullName, null); + addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); + return this; + } + + /// + /// Adds a definition for a bidirectional streaming method. + /// + /// The request message class. + /// The response message class. + /// The method. + /// The method handler. + /// This builder instance. + public Builder AddMethod( + Method method, + DuplexStreamingServerMethod handler) + where TRequest : class + where TResponse : class + { + duplicateDetector.Add(method.FullName, null); + addMethodActions.Add((serviceBinder) => serviceBinder.AddMethod(method, handler)); + return this; + } + + /// + /// Creates an immutable ServerServiceDefinition from this builder. + /// + /// The ServerServiceDefinition object. + public ServerServiceDefinition Build() + { + return new ServerServiceDefinition(addMethodActions); + } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/ServiceBinderBase.cs b/src/csharp/Grpc.Core.Api/ServiceBinderBase.cs new file mode 100644 index 00000000..074bfae1 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/ServiceBinderBase.cs @@ -0,0 +1,98 @@ +#region Copyright notice and license + +// Copyright 2018 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Allows binding server-side method implementations in alternative serving stacks. + /// Instances of this class are usually populated by the BindService method + /// that is part of the autogenerated code for a protocol buffers service definition. + /// + public class ServiceBinderBase + { + /// + /// Adds a definition for a single request - single response method. + /// + /// The request message class. + /// The response message class. + /// The method. + /// The method handler. + public virtual void AddMethod( + Method method, + UnaryServerMethod handler) + where TRequest : class + where TResponse : class + { + throw new NotImplementedException(); + } + + /// + /// Adds a definition for a client streaming method. + /// + /// The request message class. + /// The response message class. + /// The method. + /// The method handler. + public virtual void AddMethod( + Method method, + ClientStreamingServerMethod handler) + where TRequest : class + where TResponse : class + { + throw new NotImplementedException(); + } + + /// + /// Adds a definition for a server streaming method. + /// + /// The request message class. + /// The response message class. + /// The method. + /// The method handler. + public virtual void AddMethod( + Method method, + ServerStreamingServerMethod handler) + where TRequest : class + where TResponse : class + { + throw new NotImplementedException(); + } + + /// + /// Adds a definition for a bidirectional streaming method. + /// + /// The request message class. + /// The response message class. + /// The method. + /// The method handler. + public virtual void AddMethod( + Method method, + DuplexStreamingServerMethod handler) + where TRequest : class + where TResponse : class + { + throw new NotImplementedException(); + } + } +} diff --git a/src/csharp/Grpc.Core.Api/SslCredentials.cs b/src/csharp/Grpc.Core.Api/SslCredentials.cs new file mode 100644 index 00000000..21db7cdf --- /dev/null +++ b/src/csharp/Grpc.Core.Api/SslCredentials.cs @@ -0,0 +1,122 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +namespace Grpc.Core +{ + /// + /// Callback invoked with the expected targetHost and the peer's certificate. + /// If false is returned by this callback then it is treated as a + /// verification failure and the attempted connection will fail. + /// Invocation of the callback is blocking, so any + /// implementation should be light-weight. + /// Note that the callback can potentially be invoked multiple times, + /// concurrently from different threads (e.g. when multiple connections + /// are being created for the same credentials). + /// + /// The associated with the callback + /// true if verification succeeded, false otherwise. + /// Note: experimental API that can change or be removed without any prior notice. + public delegate bool VerifyPeerCallback(VerifyPeerContext context); + + /// + /// Client-side SSL credentials. + /// + public sealed class SslCredentials : ChannelCredentials + { + readonly string rootCertificates; + readonly KeyCertificatePair keyCertificatePair; + readonly VerifyPeerCallback verifyPeerCallback; + + /// + /// Creates client-side SSL credentials loaded from + /// disk file pointed to by the GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment variable. + /// If that fails, gets the roots certificates from a well known place on disk. + /// + public SslCredentials() : this(null, null, null) + { + } + + /// + /// Creates client-side SSL credentials from + /// a string containing PEM encoded root certificates. + /// + public SslCredentials(string rootCertificates) : this(rootCertificates, null, null) + { + } + + /// + /// Creates client-side SSL credentials. + /// + /// string containing PEM encoded server root certificates. + /// a key certificate pair. + public SslCredentials(string rootCertificates, KeyCertificatePair keyCertificatePair) : + this(rootCertificates, keyCertificatePair, null) + { + } + + /// + /// Creates client-side SSL credentials. + /// + /// string containing PEM encoded server root certificates. + /// a key certificate pair. + /// a callback to verify peer's target name and certificate. + /// Note: experimental API that can change or be removed without any prior notice. + public SslCredentials(string rootCertificates, KeyCertificatePair keyCertificatePair, VerifyPeerCallback verifyPeerCallback) + { + this.rootCertificates = rootCertificates; + this.keyCertificatePair = keyCertificatePair; + this.verifyPeerCallback = verifyPeerCallback; + } + + /// + /// PEM encoding of the server root certificates. + /// + public string RootCertificates + { + get + { + return this.rootCertificates; + } + } + + /// + /// Client side key and certificate pair. + /// If null, client will not use key and certificate pair. + /// + public KeyCertificatePair KeyCertificatePair + { + get + { + return this.keyCertificatePair; + } + } + + /// + /// Populates channel credentials configurator with this instance's configuration. + /// End users never need to invoke this method as it is part of internal implementation. + /// + public override void InternalPopulateConfiguration(ChannelCredentialsConfiguratorBase configurator, object state) + { + configurator.SetSslCredentials(state, rootCertificates, keyCertificatePair, verifyPeerCallback); + } + + internal override bool IsComposable => true; + } + + +} diff --git a/src/csharp/Grpc.Core.Api/Status.cs b/src/csharp/Grpc.Core.Api/Status.cs new file mode 100644 index 00000000..c13f9d88 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Status.cs @@ -0,0 +1,95 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion + +using System; + +namespace Grpc.Core +{ + /// + /// Represents RPC result, which consists of and an optional detail string. + /// + public struct Status + { + /// + /// Default result of a successful RPC. StatusCode=OK, empty details message. + /// + public static readonly Status DefaultSuccess = new Status(StatusCode.OK, ""); + + /// + /// Default result of a cancelled RPC. StatusCode=Cancelled, empty details message. + /// + public static readonly Status DefaultCancelled = new Status(StatusCode.Cancelled, ""); + + /// + /// Creates a new instance of Status. + /// + /// Status code. + /// Detail. + public Status(StatusCode statusCode, string detail) : this(statusCode, detail, null) + { + } + + /// + /// Creates a new instance of Status. + /// Users should not use this constructor, except for creating instances for testing. + /// The debug error string should only be populated by gRPC internals. + /// Note: experimental API that can change or be removed without any prior notice. + /// + /// Status code. + /// Detail. + /// Optional internal error details. + public Status(StatusCode statusCode, string detail, Exception debugException) + { + StatusCode = statusCode; + Detail = detail; + DebugException = debugException; + } + + /// + /// Gets the gRPC status code. OK indicates success, all other values indicate an error. + /// + public StatusCode StatusCode { get; } + + /// + /// Gets the detail. + /// + public string Detail { get; } + + /// + /// In case of an error, this field may contain additional error details to help with debugging. + /// This field will be only populated on a client and its value is generated locally, + /// based on the internal state of the gRPC client stack (i.e. the value is never sent over the wire). + /// Note that this field is available only for debugging purposes, the application logic should + /// never rely on values of this field (it should use StatusCode and Detail instead). + /// Example: when a client fails to connect to a server, this field may provide additional details + /// why the connection to the server has failed. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public Exception DebugException { get; } + + /// + /// Returns a that represents the current . + /// + public override string ToString() + { + if (DebugException != null) + { + return $"Status(StatusCode=\"{StatusCode}\", Detail=\"{Detail}\", DebugException=\"{DebugException}\")"; + } + return $"Status(StatusCode=\"{StatusCode}\", Detail=\"{Detail}\")"; + } + } +} diff --git a/src/csharp/Grpc.Core.Api/StatusCode.cs b/src/csharp/Grpc.Core.Api/StatusCode.cs new file mode 100644 index 00000000..8493f375 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/StatusCode.cs @@ -0,0 +1,125 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +namespace Grpc.Core +{ + /// + /// Result of a remote procedure call. + /// Based on grpc_status_code from grpc/status.h + /// + public enum StatusCode + { + /// Not an error; returned on success. + OK = 0, + + /// The operation was cancelled (typically by the caller). + Cancelled = 1, + + /// + /// Unknown error. An example of where this error may be returned is + /// if a Status value received from another address space belongs to + /// an error-space that is not known in this address space. Also + /// errors raised by APIs that do not return enough error information + /// may be converted to this error. + /// + Unknown = 2, + + /// + /// Client specified an invalid argument. Note that this differs + /// from FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments + /// that are problematic regardless of the state of the system + /// (e.g., a malformed file name). + /// + InvalidArgument = 3, + + /// + /// Deadline expired before operation could complete. For operations + /// that change the state of the system, this error may be returned + /// even if the operation has completed successfully. For example, a + /// successful response from a server could have been delayed long + /// enough for the deadline to expire. + /// + DeadlineExceeded = 4, + + /// Some requested entity (e.g., file or directory) was not found. + NotFound = 5, + + /// Some entity that we attempted to create (e.g., file or directory) already exists. + AlreadyExists = 6, + + /// + /// The caller does not have permission to execute the specified + /// operation. PERMISSION_DENIED must not be used for rejections + /// caused by exhausting some resource (use RESOURCE_EXHAUSTED + /// instead for those errors). PERMISSION_DENIED must not be + /// used if the caller can not be identified (use UNAUTHENTICATED + /// instead for those errors). + /// + PermissionDenied = 7, + + /// The request does not have valid authentication credentials for the operation. + Unauthenticated = 16, + + /// + /// Some resource has been exhausted, perhaps a per-user quota, or + /// perhaps the entire file system is out of space. + /// + ResourceExhausted = 8, + + /// + /// Operation was rejected because the system is not in a state + /// required for the operation's execution. For example, directory + /// to be deleted may be non-empty, an rmdir operation is applied to + /// a non-directory, etc. + /// + FailedPrecondition = 9, + + /// + /// The operation was aborted, typically due to a concurrency issue + /// like sequencer check failures, transaction aborts, etc. + /// + Aborted = 10, + + /// + /// Operation was attempted past the valid range. E.g., seeking or + /// reading past end of file. + /// + OutOfRange = 11, + + /// Operation is not implemented or not supported/enabled in this service. + Unimplemented = 12, + + /// + /// Internal errors. Means some invariants expected by underlying + /// system has been broken. If you see one of these errors, + /// something is very broken. + /// + Internal = 13, + + /// + /// The service is currently unavailable. This is a most likely a + /// transient condition and may be corrected by retrying with + /// a backoff. Note that it is not always safe to retry + /// non-idempotent operations. + /// + Unavailable = 14, + + /// Unrecoverable data loss or corruption. + DataLoss = 15 + } +} diff --git a/src/csharp/Grpc.Core.Api/Utils/EncodingExtensions.cs b/src/csharp/Grpc.Core.Api/Utils/EncodingExtensions.cs new file mode 100644 index 00000000..080fbcd5 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Utils/EncodingExtensions.cs @@ -0,0 +1,54 @@ +#region Copyright notice and license +// Copyright 2019 The gRPC Authors +// +// 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. +#endregion + +using System; +using System.Runtime.CompilerServices; +using System.Text; + +namespace Grpc.Core.Api.Utils +{ + + internal static class EncodingExtensions + { +#if NET45 // back-fill over a method missing in NET45 + /// + /// Converts byte* pointing to an encoded byte array to a string using the provided Encoding. + /// + public static unsafe string GetString(this Encoding encoding, byte* source, int byteCount) + { + if (byteCount == 0) return ""; // most callers will have already checked, but: make sure + + // allocate a right-sized string and decode into it + int charCount = encoding.GetCharCount(source, byteCount); + string s = new string('\0', charCount); + fixed (char* cPtr = s) + { + encoding.GetChars(source, byteCount, cPtr, charCount); + } + return s; + } +#endif + /// + /// Converts IntPtr pointing to a encoded byte array to a string using the provided Encoding. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe string GetString(this Encoding encoding, IntPtr ptr, int len) + { + return len == 0 ? "" : encoding.GetString((byte*)ptr.ToPointer(), len); + } + } + +} diff --git a/src/csharp/Grpc.Core.Api/Utils/GrpcPreconditions.cs b/src/csharp/Grpc.Core.Api/Utils/GrpcPreconditions.cs new file mode 100644 index 00000000..a01684fe --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Utils/GrpcPreconditions.cs @@ -0,0 +1,105 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; + +namespace Grpc.Core.Utils +{ + /// + /// Utility methods to simplify checking preconditions in the code. + /// + public static class GrpcPreconditions + { + /// + /// Throws if condition is false. + /// + /// The condition. + public static void CheckArgument(bool condition) + { + if (!condition) + { + throw new ArgumentException(); + } + } + + /// + /// Throws with given message if condition is false. + /// + /// The condition. + /// The error message. + public static void CheckArgument(bool condition, string errorMessage) + { + if (!condition) + { + throw new ArgumentException(errorMessage); + } + } + + /// + /// Throws if reference is null. + /// + /// The reference. + public static T CheckNotNull(T reference) + { + if (reference == null) + { + throw new ArgumentNullException(); + } + return reference; + } + + /// + /// Throws if reference is null. + /// + /// The reference. + /// The parameter name. + public static T CheckNotNull(T reference, string paramName) + { + if (reference == null) + { + throw new ArgumentNullException(paramName); + } + return reference; + } + + /// + /// Throws if condition is false. + /// + /// The condition. + public static void CheckState(bool condition) + { + if (!condition) + { + throw new InvalidOperationException(); + } + } + + /// + /// Throws with given message if condition is false. + /// + /// The condition. + /// The error message. + public static void CheckState(bool condition, string errorMessage) + { + if (!condition) + { + throw new InvalidOperationException(errorMessage); + } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/VerifyPeerContext.cs b/src/csharp/Grpc.Core.Api/VerifyPeerContext.cs new file mode 100644 index 00000000..b1dc60f8 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/VerifyPeerContext.cs @@ -0,0 +1,48 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +namespace Grpc.Core +{ + /// + /// Verification context for VerifyPeerCallback. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public class VerifyPeerContext + { + /// + /// Initializes a new instance of the class. + /// + /// The target name of the peer. + /// The PEM encoded certificate of the peer. + internal VerifyPeerContext(string targetName, string peerPem) + { + this.TargetName = targetName; + this.PeerPem = peerPem; + } + + /// + /// The target name of the peer. + /// + public string TargetName { get; } + + /// + /// The PEM encoded certificate of the peer. + /// + public string PeerPem { get; } + } +} diff --git a/src/csharp/Grpc.Core.Api/Version.cs b/src/csharp/Grpc.Core.Api/Version.cs new file mode 100644 index 00000000..9164b83c --- /dev/null +++ b/src/csharp/Grpc.Core.Api/Version.cs @@ -0,0 +1,23 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; + +[assembly: AssemblyVersion(Grpc.Core.VersionInfo.CurrentAssemblyVersion)] +[assembly: AssemblyFileVersion(Grpc.Core.VersionInfo.CurrentAssemblyFileVersion)] +[assembly: AssemblyInformationalVersion(Grpc.Core.VersionInfo.CurrentVersion)] diff --git a/src/csharp/Grpc.Core.Api/VersionInfo.cs b/src/csharp/Grpc.Core.Api/VersionInfo.cs new file mode 100644 index 00000000..3a3ee64a --- /dev/null +++ b/src/csharp/Grpc.Core.Api/VersionInfo.cs @@ -0,0 +1,43 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +namespace Grpc.Core +{ + /// + /// Provides info about current version of gRPC. + /// See https://codingforsmarties.wordpress.com/2016/01/21/how-to-version-assemblies-destined-for-nuget/ + /// for rationale about assembly versioning. + /// + public static class VersionInfo + { + /// + /// Current AssemblyVersion attribute of gRPC C# assemblies + /// + public const string CurrentAssemblyVersion = "2.0.0.0"; + + /// + /// Current AssemblyFileVersion of gRPC C# assemblies + /// + public const string CurrentAssemblyFileVersion = "2.42.0.0"; + + /// + /// Current version of gRPC C# + /// + public const string CurrentVersion = "2.42.0-dev"; + } +} diff --git a/src/csharp/Grpc.Core.Api/WriteOptions.cs b/src/csharp/Grpc.Core.Api/WriteOptions.cs new file mode 100644 index 00000000..cbb866b0 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/WriteOptions.cs @@ -0,0 +1,74 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System; + +namespace Grpc.Core +{ + /// + /// Flags for write operations. + /// + [Flags] + public enum WriteFlags + { + /// + /// Hint that the write may be buffered and need not go out on the wire immediately. + /// gRPC is free to buffer the message until the next non-buffered + /// write, or until write stream completion, but it need not buffer completely or at all. + /// + BufferHint = 0x1, + + /// + /// Force compression to be disabled for a particular write. + /// + NoCompress = 0x2 + } + + /// + /// Options for write operations. + /// + public class WriteOptions + { + /// + /// Default write options. + /// + public static readonly WriteOptions Default = new WriteOptions(); + + private readonly WriteFlags flags; + + /// + /// Initializes a new instance of WriteOptions class. + /// + /// The write flags. + public WriteOptions(WriteFlags flags = default(WriteFlags)) + { + this.flags = flags; + } + + /// + /// Gets the write flags. + /// + public WriteFlags Flags + { + get + { + return this.flags; + } + } + } +} diff --git a/src/csharp/Grpc.Core.Testing/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core.Testing/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..33c67088 --- /dev/null +++ b/src/csharp/Grpc.Core.Testing/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.Core.Testing")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.Core.Testing/TestCalls.cs b/src/csharp/Grpc.Core.Testing/TestCalls.cs new file mode 100644 index 00000000..8c76781b --- /dev/null +++ b/src/csharp/Grpc.Core.Testing/TestCalls.cs @@ -0,0 +1,76 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading.Tasks; +using Grpc.Core; + +namespace Grpc.Core.Testing +{ + /// + /// Test doubles for client-side call objects. + /// + public static class TestCalls + { + /// + /// Creates a test double for AsyncUnaryCall. Only for testing. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public static AsyncUnaryCall AsyncUnaryCall ( + Task responseAsync, Task responseHeadersAsync, Func getStatusFunc, + Func getTrailersFunc, Action disposeAction) + { + return new AsyncUnaryCall(responseAsync, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction); + } + + /// + /// Creates a test double for AsyncClientStreamingCall. Only for testing. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public static AsyncClientStreamingCall AsyncClientStreamingCall( + IClientStreamWriter requestStream, Task responseAsync, + Task responseHeadersAsync, Func getStatusFunc, + Func getTrailersFunc, Action disposeAction) + { + return new AsyncClientStreamingCall(requestStream, responseAsync, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction); + } + + /// + /// Creates a test double for AsyncServerStreamingCall. Only for testing. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public static AsyncServerStreamingCall AsyncServerStreamingCall( + IAsyncStreamReader responseStream, Task responseHeadersAsync, + Func getStatusFunc, Func getTrailersFunc, Action disposeAction) + { + return new AsyncServerStreamingCall(responseStream, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction); + } + + /// + /// Creates a test double for AsyncDuplexStreamingCall. Only for testing. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public static AsyncDuplexStreamingCall AsyncDuplexStreamingCall( + IClientStreamWriter requestStream, IAsyncStreamReader responseStream, + Task responseHeadersAsync, Func getStatusFunc, + Func getTrailersFunc, Action disposeAction) + { + return new AsyncDuplexStreamingCall(requestStream, responseStream, responseHeadersAsync, getStatusFunc, getTrailersFunc, disposeAction); + } + } +} diff --git a/src/csharp/Grpc.Core.Testing/TestServerCallContext.cs b/src/csharp/Grpc.Core.Testing/TestServerCallContext.cs new file mode 100644 index 00000000..e6297e61 --- /dev/null +++ b/src/csharp/Grpc.Core.Testing/TestServerCallContext.cs @@ -0,0 +1,107 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Grpc.Core.Testing +{ + /// + /// Creates test doubles for ServerCallContext. + /// + public static class TestServerCallContext + { + /// + /// Creates a test double for ServerCallContext. Only for testing. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public static ServerCallContext Create(string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken, + string peer, AuthContext authContext, ContextPropagationToken contextPropagationToken, + Func writeHeadersFunc, Func writeOptionsGetter, Action writeOptionsSetter) + { + return new TestingServerCallContext(method, host, deadline, requestHeaders, cancellationToken, peer, + authContext, contextPropagationToken, writeHeadersFunc, writeOptionsGetter, writeOptionsSetter); + } + + private class TestingServerCallContext : ServerCallContext + { + private readonly string method; + private readonly string host; + private readonly DateTime deadline; + private readonly Metadata requestHeaders; + private readonly CancellationToken cancellationToken; + private readonly Metadata responseTrailers = new Metadata(); + private Status status; + private readonly string peer; + private readonly AuthContext authContext; + private readonly ContextPropagationToken contextPropagationToken; + private readonly Func writeHeadersFunc; + private readonly Func writeOptionsGetter; + private readonly Action writeOptionsSetter; + + public TestingServerCallContext(string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken, + string peer, AuthContext authContext, ContextPropagationToken contextPropagationToken, + Func writeHeadersFunc, Func writeOptionsGetter, Action writeOptionsSetter) + { + this.method = method; + this.host = host; + this.deadline = deadline; + this.requestHeaders = requestHeaders; + this.cancellationToken = cancellationToken; + this.responseTrailers = new Metadata(); + this.status = Status.DefaultSuccess; + this.peer = peer; + this.authContext = authContext; + this.contextPropagationToken = contextPropagationToken; + this.writeHeadersFunc = writeHeadersFunc; + this.writeOptionsGetter = writeOptionsGetter; + this.writeOptionsSetter = writeOptionsSetter; + } + + protected override string MethodCore => method; + + protected override string HostCore => host; + + protected override string PeerCore => peer; + + protected override DateTime DeadlineCore => deadline; + + protected override Metadata RequestHeadersCore => requestHeaders; + + protected override CancellationToken CancellationTokenCore => cancellationToken; + + protected override Metadata ResponseTrailersCore => responseTrailers; + + protected override Status StatusCore { get => status; set => status = value; } + protected override WriteOptions WriteOptionsCore { get => writeOptionsGetter(); set => writeOptionsSetter(value); } + + protected override AuthContext AuthContextCore => authContext; + + protected override ContextPropagationToken CreatePropagationTokenCore(ContextPropagationOptions options) + { + return contextPropagationToken; + } + + protected override Task WriteResponseHeadersAsyncCore(Metadata responseHeaders) + { + return writeHeadersFunc(responseHeaders); + } + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs b/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs new file mode 100644 index 00000000..b10d7a10 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/AppDomainUnloadTest.cs @@ -0,0 +1,77 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading.Tasks; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class AppDomainUnloadTest + { +#if NETCOREAPP1_1 || NETCOREAPP2_1 + [Test] + [Ignore("Not supported for CoreCLR")] + public void AppDomainUnloadHookCanCleanupAbandonedCall() + { + } +#else + [Test] + public void AppDomainUnloadHookCanCleanupAbandonedCall() + { + var setup = new AppDomainSetup + { + ApplicationBase = AppDomain.CurrentDomain.BaseDirectory + }; + var childDomain = AppDomain.CreateDomain("test", null, setup); + var remoteObj = childDomain.CreateInstance(typeof(AppDomainTestClass).Assembly.GetName().Name, typeof(AppDomainTestClass).FullName); + + // Try to unload the appdomain once we've created a server and a channel inside the appdomain. + AppDomain.Unload(childDomain); + } + + public class AppDomainTestClass + { + const string Host = "127.0.0.1"; + + /// + /// Creates a server and a channel and initiates a call. The code is invoked from inside of an AppDomain + /// to test if AppDomain.Unload() work if Grpc is being used. + /// + public AppDomainTestClass() + { + var helper = new MockServiceHelper(Host); + var readyToShutdown = new TaskCompletionSource(); + helper.DuplexStreamingHandler = new DuplexStreamingServerMethod(async (requestStream, responseStream, context) => + { + readyToShutdown.SetResult(null); + await requestStream.ToListAsync(); + }); + + var server = helper.GetServer(); + server.Start(); + var channel = helper.GetChannel(); + + var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall()); + readyToShutdown.Task.Wait(); // make sure handler is running + } + } +#endif + } +} diff --git a/src/csharp/Grpc.Core.Tests/AuthContextTest.cs b/src/csharp/Grpc.Core.Tests/AuthContextTest.cs new file mode 100644 index 00000000..6e19610c --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/AuthContextTest.cs @@ -0,0 +1,71 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using Grpc.Core; +using System.Linq; + +namespace Grpc.Core.Tests +{ + public class AuthContextTest + { + [Test] + public void EmptyContext() + { + var context = new AuthContext(null, new Dictionary>()); + Assert.IsFalse(context.IsPeerAuthenticated); + Assert.IsNull(context.PeerIdentityPropertyName); + Assert.AreEqual(0, context.PeerIdentity.Count()); + Assert.AreEqual(0, context.Properties.Count()); + Assert.AreEqual(0, context.FindPropertiesByName("nonexistent").Count()); + } + + [Test] + public void AuthenticatedContext() + { + var property1 = AuthProperty.Create("abc", new byte[] { 68, 69, 70 }); + var context = new AuthContext("some_identity", new Dictionary> + { + {"some_identity", new List {property1}} + }); + Assert.IsTrue(context.IsPeerAuthenticated); + Assert.AreEqual("some_identity", context.PeerIdentityPropertyName); + Assert.AreEqual(1, context.PeerIdentity.Count()); + } + + [Test] + public void FindPropertiesByName() + { + var property1 = AuthProperty.Create("abc", new byte[] {68, 69, 70}); + var property2 = AuthProperty.Create("abc", new byte[] {71, 72, 73 }); + var property3 = AuthProperty.Create("abc", new byte[] {}); + var context = new AuthContext(null, new Dictionary> + { + {"existent", new List {property1, property2}}, + {"foobar", new List {property3}}, + }); + Assert.AreEqual(3, context.Properties.Count()); + Assert.AreEqual(0, context.FindPropertiesByName("nonexistent").Count()); + + var existentProperties = new List(context.FindPropertiesByName("existent")); + Assert.AreEqual(2, existentProperties.Count); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/AuthPropertyTest.cs b/src/csharp/Grpc.Core.Tests/AuthPropertyTest.cs new file mode 100644 index 00000000..04f08f01 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/AuthPropertyTest.cs @@ -0,0 +1,67 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class AuthPropertyTest + { + [Test] + public void Create_NameIsNotNull() + { + Assert.Throws(typeof(ArgumentNullException), () => AuthProperty.Create(null, new byte[0])); + Assert.Throws(typeof(ArgumentNullException), () => AuthProperty.CreateUnsafe(null, new byte[0])); + } + + [Test] + public void Create_ValueIsNotNull() + { + Assert.Throws(typeof(ArgumentNullException), () => AuthProperty.Create("abc", null)); + Assert.Throws(typeof(ArgumentNullException), () => AuthProperty.CreateUnsafe("abc", null)); + } + + [Test] + public void Create() + { + var valueBytes = new byte[] { 68, 69, 70 }; + var authProperty = AuthProperty.Create("abc", valueBytes); + + Assert.AreEqual("abc", authProperty.Name); + Assert.AreNotSame(valueBytes, authProperty.ValueBytesUnsafe); + CollectionAssert.AreEqual(valueBytes, authProperty.ValueBytes); + CollectionAssert.AreEqual(valueBytes, authProperty.ValueBytesUnsafe); + Assert.AreEqual("DEF", authProperty.Value); + } + + [Test] + public void CreateUnsafe() + { + var valueBytes = new byte[] { 68, 69, 70 }; + var authProperty = AuthProperty.CreateUnsafe("abc", valueBytes); + + Assert.AreEqual("abc", authProperty.Name); + Assert.AreSame(valueBytes, authProperty.ValueBytesUnsafe); + Assert.AreNotSame(valueBytes, authProperty.ValueBytes); + CollectionAssert.AreEqual(valueBytes, authProperty.ValueBytes); + CollectionAssert.AreEqual(valueBytes, authProperty.ValueBytesUnsafe); + Assert.AreEqual("DEF", authProperty.Value); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/CallCancellationTest.cs b/src/csharp/Grpc.Core.Tests/CallCancellationTest.cs new file mode 100644 index 00000000..753b8b22 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/CallCancellationTest.cs @@ -0,0 +1,193 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Profiling; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class CallCancellationTest + { + const string Host = "127.0.0.1"; + + MockServiceHelper helper; + Server server; + Channel channel; + + [SetUp] + public void Init() + { + helper = new MockServiceHelper(Host); + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public async Task ClientStreamingCall_CancelAfterBegin() + { + var barrier = new TaskCompletionSource(); + + helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => + { + barrier.SetResult(null); + await requestStream.ToListAsync(); + return ""; + }); + + var cts = new CancellationTokenSource(); + var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(cancellationToken: cts.Token))); + + await barrier.Task; // make sure the handler has started. + cts.Cancel(); + + try + { + // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock. + await call.ResponseAsync; + Assert.Fail(); + } + catch (RpcException ex) + { + Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode); + } + } + + [Test] + public async Task ClientStreamingCall_ServerSideReadAfterCancelNotificationReturnsNull() + { + var handlerStartedBarrier = new TaskCompletionSource(); + var cancelNotificationReceivedBarrier = new TaskCompletionSource(); + var successTcs = new TaskCompletionSource(); + + helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => + { + handlerStartedBarrier.SetResult(null); + + // wait for cancellation to be delivered. + context.CancellationToken.Register(() => cancelNotificationReceivedBarrier.SetResult(null)); + await cancelNotificationReceivedBarrier.Task; + + var moveNextResult = await requestStream.MoveNext(); + successTcs.SetResult(!moveNextResult ? "SUCCESS" : "FAIL"); + return ""; + }); + + var cts = new CancellationTokenSource(); + var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(cancellationToken: cts.Token))); + + await handlerStartedBarrier.Task; + cts.Cancel(); + + try + { + await call.ResponseAsync; + Assert.Fail(); + } + catch (RpcException ex) + { + Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode); + } + Assert.AreEqual("SUCCESS", await successTcs.Task); + } + + [Test] + public async Task ClientStreamingCall_CancelServerSideRead() + { + helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => + { + var cts = new CancellationTokenSource(); + var moveNextTask = requestStream.MoveNext(cts.Token); + cts.Cancel(); + await moveNextTask; + return ""; + }); + + var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()); + try + { + // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock. + await call.ResponseAsync; + Assert.Fail(); + } + catch (RpcException ex) + { + Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode); + } + } + + [Test] + public async Task ServerStreamingCall_CancelClientSideRead() + { + helper.ServerStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => + { + await responseStream.WriteAsync("abc"); + while (!context.CancellationToken.IsCancellationRequested) + { + await Task.Delay(10); + } + }); + + var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), ""); + await call.ResponseStream.MoveNext(); + Assert.AreEqual("abc", call.ResponseStream.Current); + + var cts = new CancellationTokenSource(); + var moveNextTask = call.ResponseStream.MoveNext(cts.Token); + cts.Cancel(); + + try + { + // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock. + await moveNextTask; + Assert.Fail(); + } + catch (RpcException ex) + { + Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode); + } + } + + [Test] + public void CanDisposeDefaultCancellationRegistration() + { + // prove that we're fine to dispose default CancellationTokenRegistration + // values without boxing them to IDisposable for a null-check + var obj = default(CancellationTokenRegistration); + obj.Dispose(); + + using (obj) {} + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/CallCredentialsTest.cs b/src/csharp/Grpc.Core.Tests/CallCredentialsTest.cs new file mode 100644 index 00000000..92b9a10d --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/CallCredentialsTest.cs @@ -0,0 +1,50 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class CallCredentialsTest + { + [Test] + public void CallCredentials_ComposeAtLeastTwo() + { + Assert.Throws(typeof(ArgumentException), () => CallCredentials.Compose(new FakeCallCredentials())); + } + + [Test] + public void CallCredentials_ToNativeCredentials() + { + var composite = CallCredentials.Compose( + CallCredentials.FromInterceptor(async (uri, m) => { await Task.Delay(1); }), + CallCredentials.FromInterceptor(async (uri, m) => { await Task.Delay(2); })); + using (var nativeComposite = composite.ToNativeCredentials()) + { + } + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs b/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs new file mode 100644 index 00000000..1fd48812 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/CallOptionsTest.cs @@ -0,0 +1,98 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Threading; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class CallOptionsTest + { + [Test] + public void WithMethods() + { + var options = new CallOptions(); + + var metadata = new Metadata(); + Assert.AreSame(metadata, options.WithHeaders(metadata).Headers); + + var deadline = DateTime.UtcNow; + Assert.AreEqual(deadline, options.WithDeadline(deadline).Deadline.Value); + + var cancellationToken = new CancellationTokenSource().Token; + Assert.AreEqual(cancellationToken, options.WithCancellationToken(cancellationToken).CancellationToken); + + var writeOptions = new WriteOptions(); + Assert.AreSame(writeOptions, options.WithWriteOptions(writeOptions).WriteOptions); + + var propagationToken = new ContextPropagationTokenImpl(CallSafeHandle.NullInstance, DateTime.UtcNow, + CancellationToken.None, ContextPropagationOptions.Default); + Assert.AreSame(propagationToken, options.WithPropagationToken(propagationToken).PropagationToken); + + var credentials = new FakeCallCredentials(); + Assert.AreSame(credentials, options.WithCredentials(credentials).Credentials); + + var flags = CallFlags.WaitForReady | CallFlags.CacheableRequest; + Assert.AreEqual(flags, options.WithFlags(flags).Flags); + + // Check that the original instance is unchanged. + Assert.IsNull(options.Headers); + Assert.IsNull(options.Deadline); + Assert.AreEqual(CancellationToken.None, options.CancellationToken); + Assert.IsNull(options.WriteOptions); + Assert.IsNull(options.PropagationToken); + Assert.IsNull(options.Credentials); + Assert.AreEqual(default(CallFlags), options.Flags); + } + + [Test] + public void Normalize() + { + Assert.AreSame(Metadata.Empty, new CallOptions().Normalize().Headers); + Assert.AreEqual(DateTime.MaxValue, new CallOptions().Normalize().Deadline.Value); + + var deadline = DateTime.UtcNow; + var propagationToken1 = new ContextPropagationTokenImpl(CallSafeHandle.NullInstance, deadline, CancellationToken.None, + new ContextPropagationOptions(propagateDeadline: true, propagateCancellation: false)); + Assert.AreEqual(deadline, new CallOptions(propagationToken: propagationToken1).Normalize().Deadline.Value); + Assert.Throws(typeof(ArgumentException), () => new CallOptions(deadline: deadline, propagationToken: propagationToken1).Normalize()); + + var token = new CancellationTokenSource().Token; + var propagationToken2 = new ContextPropagationTokenImpl(CallSafeHandle.NullInstance, deadline, token, + new ContextPropagationOptions(propagateDeadline: false, propagateCancellation: true)); + Assert.AreEqual(token, new CallOptions(propagationToken: propagationToken2).Normalize().CancellationToken); + Assert.Throws(typeof(ArgumentException), () => new CallOptions(cancellationToken: token, propagationToken: propagationToken2).Normalize()); + } + + [Test] + public void WaitForReady() + { + var callOptions = new CallOptions(); + Assert.IsFalse(callOptions.IsWaitForReady); + + Assert.AreEqual(CallFlags.WaitForReady, callOptions.WithWaitForReady().Flags); + Assert.IsTrue(callOptions.WithWaitForReady().IsWaitForReady); + Assert.IsFalse(callOptions.WithWaitForReady(true).WithWaitForReady(false).IsWaitForReady); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/ChannelConnectivityTest.cs b/src/csharp/Grpc.Core.Tests/ChannelConnectivityTest.cs new file mode 100644 index 00000000..0834ddad --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ChannelConnectivityTest.cs @@ -0,0 +1,90 @@ +#region Copyright notice and license + +// Copyright 2017 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Profiling; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class ChannelConnectivityTest + { + const string Host = "127.0.0.1"; + + MockServiceHelper helper; + Server server; + Channel channel; + + [SetUp] + public void Init() + { + helper = new MockServiceHelper(Host); + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public async Task Channel_WaitForStateChangedAsync() + { + Assert.ThrowsAsync(typeof(TaskCanceledException), + async () => await channel.WaitForStateChangedAsync(channel.State, DateTime.UtcNow.AddMilliseconds(0))); + + var stateChangedTask = channel.WaitForStateChangedAsync(channel.State); + await channel.ConnectAsync(DateTime.UtcNow.AddMilliseconds(5000)); + await stateChangedTask; + Assert.AreEqual(ChannelState.Ready, channel.State); + } + + [Test] + public async Task Channel_TryWaitForStateChangedAsync() + { + Assert.IsFalse(await channel.TryWaitForStateChangedAsync(channel.State, DateTime.UtcNow.AddMilliseconds(0))); + + var stateChangedTask = channel.TryWaitForStateChangedAsync(channel.State); + await channel.ConnectAsync(DateTime.UtcNow.AddMilliseconds(5000)); + Assert.IsTrue(await stateChangedTask); + Assert.AreEqual(ChannelState.Ready, channel.State); + } + + [Test] + public async Task Channel_ConnectAsync() + { + await channel.ConnectAsync(); + Assert.AreEqual(ChannelState.Ready, channel.State); + + await channel.ConnectAsync(DateTime.UtcNow.AddMilliseconds(1000)); + Assert.AreEqual(ChannelState.Ready, channel.State); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/ChannelCredentialsTest.cs b/src/csharp/Grpc.Core.Tests/ChannelCredentialsTest.cs new file mode 100644 index 00000000..f5d06ad1 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ChannelCredentialsTest.cs @@ -0,0 +1,67 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.Core.Internal; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class ChannelCredentialsTest + { + [Test] + public void InsecureCredentials_IsNonComposable() + { + Assert.IsFalse(ChannelCredentials.Insecure.IsComposable); + } + + [Test] + public void SecureCredentials_IsComposable() + { + Assert.IsTrue(ChannelCredentials.SecureSsl.IsComposable); + } + + [Test] + public void ChannelCredentials_CreateComposite() + { + var composite = ChannelCredentials.Create(new FakeChannelCredentials(true), new FakeCallCredentials()); + Assert.IsFalse(composite.IsComposable); + + Assert.Throws(typeof(ArgumentNullException), () => ChannelCredentials.Create(null, new FakeCallCredentials())); + Assert.Throws(typeof(ArgumentNullException), () => ChannelCredentials.Create(new FakeChannelCredentials(true), null)); + + // forbid composing non-composable + var ex = Assert.Throws(typeof(ArgumentException), () => ChannelCredentials.Create(new FakeChannelCredentials(false), new FakeCallCredentials())); + Assert.AreEqual("CallCredentials can't be composed with FakeChannelCredentials. CallCredentials must be used with secure channel credentials like SslCredentials.", ex.Message); + } + + [Test] + public void ChannelCredentials_NativeCredentialsAreReused() + { + // always returning the same native object is critical for subchannel sharing to work with secure channels + var creds = new SslCredentials(); + var nativeCreds1 = creds.ToNativeCredentials(); + var nativeCreds2 = creds.ToNativeCredentials(); + Assert.AreSame(nativeCreds1, nativeCreds2); + + var nativeCreds3 = ChannelCredentials.SecureSsl.ToNativeCredentials(); + var nativeCreds4 = ChannelCredentials.SecureSsl.ToNativeCredentials(); + Assert.AreSame(nativeCreds3, nativeCreds4); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/ChannelOptionsTest.cs b/src/csharp/Grpc.Core.Tests/ChannelOptionsTest.cs new file mode 100644 index 00000000..ae78b80c --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ChannelOptionsTest.cs @@ -0,0 +1,90 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class ChannelOptionsTest + { + [Test] + public void IntOption() + { + var option = new ChannelOption("somename", 1); + + Assert.AreEqual(ChannelOption.OptionType.Integer, option.Type); + Assert.AreEqual("somename", option.Name); + Assert.AreEqual(1, option.IntValue); + Assert.Throws(typeof(InvalidOperationException), () => { var s = option.StringValue; }); + } + + [Test] + public void StringOption() + { + var option = new ChannelOption("somename", "ABCDEF"); + + Assert.AreEqual(ChannelOption.OptionType.String, option.Type); + Assert.AreEqual("somename", option.Name); + Assert.AreEqual("ABCDEF", option.StringValue); + Assert.Throws(typeof(InvalidOperationException), () => { var s = option.IntValue; }); + } + + [Test] + public void ConstructorPreconditions() + { + Assert.Throws(typeof(ArgumentNullException), () => { new ChannelOption(null, "abc"); }); + Assert.Throws(typeof(ArgumentNullException), () => { new ChannelOption(null, 1); }); + Assert.Throws(typeof(ArgumentNullException), () => { new ChannelOption("abc", null); }); + } + + [Test] + public void CreateChannelArgsNull() + { + var channelArgs = ChannelOptions.CreateChannelArgs(null); + Assert.IsTrue(channelArgs.IsInvalid); + } + + [Test] + public void CreateChannelArgsEmpty() + { + var options = new List(); + var channelArgs = ChannelOptions.CreateChannelArgs(options); + channelArgs.Dispose(); + } + + [Test] + public void CreateChannelArgs() + { + var options = new List + { + new ChannelOption("ABC", "XYZ"), + new ChannelOption("somename", "IJKLM"), + new ChannelOption("intoption", 12345), + new ChannelOption("GHIJK", 12345), + }; + + var channelArgs = ChannelOptions.CreateChannelArgs(options); + channelArgs.Dispose(); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/ChannelTest.cs b/src/csharp/Grpc.Core.Tests/ChannelTest.cs new file mode 100644 index 00000000..9f9dedaa --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ChannelTest.cs @@ -0,0 +1,127 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class ChannelTest + { + [Test] + public void Constructor_RejectsInvalidParams() + { + Assert.Throws(typeof(ArgumentNullException), () => new Channel(null, ChannelCredentials.Insecure)); + } + + [Test] + public void Constructor_RejectsDuplicateOptions() + { + var options = new ChannelOption[] + { + new ChannelOption(ChannelOptions.PrimaryUserAgentString, "ABC"), + new ChannelOption(ChannelOptions.PrimaryUserAgentString, "XYZ") + }; + Assert.Throws(typeof(ArgumentException), () => new Channel("127.0.0.1", ChannelCredentials.Insecure, options)); + } + + [Test] + public void State_IdleAfterCreation() + { + var channel = new Channel("localhost", ChannelCredentials.Insecure); + Assert.AreEqual(ChannelState.Idle, channel.State); + channel.ShutdownAsync().Wait(); + } + + [Test] + public void WaitForStateChangedAsync_InvalidArgument() + { + var channel = new Channel("localhost", ChannelCredentials.Insecure); + Assert.ThrowsAsync(typeof(ArgumentException), async () => await channel.WaitForStateChangedAsync(ChannelState.Shutdown)); + channel.ShutdownAsync().Wait(); + } + + [Test] + public void ResolvedTarget() + { + var channel = new Channel("127.0.0.1", ChannelCredentials.Insecure); + Assert.IsTrue(channel.ResolvedTarget.Contains("127.0.0.1")); + channel.ShutdownAsync().Wait(); + } + + [Test] + public void Shutdown_AllowedOnlyOnce() + { + var channel = new Channel("localhost", ChannelCredentials.Insecure); + channel.ShutdownAsync().Wait(); + Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await channel.ShutdownAsync()); + } + + [Test] + public async Task ShutdownTokenCancelledAfterShutdown() + { + var channel = new Channel("localhost", ChannelCredentials.Insecure); + Assert.IsFalse(channel.ShutdownToken.IsCancellationRequested); + var shutdownTask = channel.ShutdownAsync(); + Assert.IsTrue(channel.ShutdownToken.IsCancellationRequested); + await shutdownTask; + } + + [Test] + public async Task StateIsShutdownAfterShutdown() + { + var channel = new Channel("localhost", ChannelCredentials.Insecure); + await channel.ShutdownAsync(); + Assert.AreEqual(ChannelState.Shutdown, channel.State); + } + + [Test] + public async Task ShutdownFinishesWaitForStateChangedAsync() + { + var channel = new Channel("localhost", ChannelCredentials.Insecure); + var stateChangedTask = channel.WaitForStateChangedAsync(ChannelState.Idle); + var shutdownTask = channel.ShutdownAsync(); + await stateChangedTask; + await shutdownTask; + } + + [Test] + public async Task OperationsThrowAfterShutdown() + { + var channel = new Channel("localhost", ChannelCredentials.Insecure); + await channel.ShutdownAsync(); + Assert.ThrowsAsync(typeof(ObjectDisposedException), async () => await channel.WaitForStateChangedAsync(ChannelState.Idle)); + Assert.Throws(typeof(ObjectDisposedException), () => { var x = channel.ResolvedTarget; }); + Assert.ThrowsAsync(typeof(TaskCanceledException), async () => await channel.ConnectAsync()); + } + + [Test] + public async Task ChannelBaseShutdownAsyncInvokesShutdownAsync() + { + var channel = new Channel("localhost", ChannelCredentials.Insecure); + ChannelBase channelBase = channel; + await channelBase.ShutdownAsync(); + // check that Channel.ShutdownAsync has run + Assert.AreEqual(ChannelState.Shutdown, channel.State); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs new file mode 100644 index 00000000..7ff639c7 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs @@ -0,0 +1,397 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Profiling; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class ClientServerTest + { + const string Host = "127.0.0.1"; + + MockServiceHelper helper; + Server server; + Channel channel; + + [SetUp] + public void Init() + { + helper = new MockServiceHelper(Host); + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public async Task UnaryCall() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult(request); + }); + + Assert.AreEqual("ABC", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "ABC")); + + Assert.AreEqual("ABC", await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "ABC")); + } + + [Test] + public void UnaryCall_ServerHandlerThrows() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + throw new Exception("This was thrown on purpose by a test"); + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); + Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode); + + var ex2 = Assert.ThrowsAsync(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc")); + Assert.AreEqual(StatusCode.Unknown, ex2.Status.StatusCode); + } + + [Test] + public void UnaryCall_ServerHandlerThrowsRpcException() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + throw new RpcException(new Status(StatusCode.Unauthenticated, "")); + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); + Assert.AreEqual(StatusCode.Unauthenticated, ex.Status.StatusCode); + Assert.AreEqual(0, ex.Trailers.Count); + + var ex2 = Assert.ThrowsAsync(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc")); + Assert.AreEqual(StatusCode.Unauthenticated, ex2.Status.StatusCode); + Assert.AreEqual(0, ex.Trailers.Count); + } + + [Test] + public void UnaryCall_ServerHandlerThrowsRpcExceptionWithTrailers() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + var trailers = new Metadata { {"xyz", "xyz-value"} }; + throw new RpcException(new Status(StatusCode.Unauthenticated, ""), trailers); + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); + Assert.AreEqual(StatusCode.Unauthenticated, ex.Status.StatusCode); + Assert.AreEqual(1, ex.Trailers.Count); + Assert.AreEqual("xyz", ex.Trailers[0].Key); + Assert.AreEqual("xyz-value", ex.Trailers[0].Value); + + var ex2 = Assert.ThrowsAsync(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc")); + Assert.AreEqual(StatusCode.Unauthenticated, ex2.Status.StatusCode); + Assert.AreEqual(1, ex2.Trailers.Count); + Assert.AreEqual("xyz", ex2.Trailers[0].Key); + Assert.AreEqual("xyz-value", ex2.Trailers[0].Value); + } + + [Test] + public void UnaryCall_ServerHandlerSetsStatus() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + context.Status = new Status(StatusCode.Unauthenticated, ""); + return Task.FromResult(""); + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); + Assert.AreEqual(StatusCode.Unauthenticated, ex.Status.StatusCode); + Assert.AreEqual(0, ex.Trailers.Count); + + var ex2 = Assert.ThrowsAsync(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc")); + Assert.AreEqual(StatusCode.Unauthenticated, ex2.Status.StatusCode); + Assert.AreEqual(0, ex2.Trailers.Count); + } + + [Test] + public void UnaryCall_StatusDebugErrorStringNotTransmittedFromServer() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + context.Status = new Status(StatusCode.Unauthenticated, "", new CoreErrorDetailException("this DebugErrorString value should not be transmitted to the client")); + return Task.FromResult(""); + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); + Assert.AreEqual(StatusCode.Unauthenticated, ex.Status.StatusCode); + StringAssert.Contains("Error received from peer", ex.Status.DebugException.Message, "Is \"Error received from peer\" still a valid substring to search for in the client-generated error message from C-core?"); + Assert.AreEqual(0, ex.Trailers.Count); + + var ex2 = Assert.ThrowsAsync(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc")); + Assert.AreEqual(StatusCode.Unauthenticated, ex2.Status.StatusCode); + StringAssert.Contains("Error received from peer", ex2.Status.DebugException.Message, "Is \"Error received from peer\" still a valid substring to search for in the client-generated error message from C-core?"); + Assert.AreEqual(0, ex2.Trailers.Count); + } + + [Test] + public void UnaryCall_ServerHandlerSetsStatusAndTrailers() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + context.Status = new Status(StatusCode.Unauthenticated, ""); + context.ResponseTrailers.Add("xyz", "xyz-value"); + return Task.FromResult(""); + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); + Assert.AreEqual(StatusCode.Unauthenticated, ex.Status.StatusCode); + Assert.AreEqual(1, ex.Trailers.Count); + Assert.AreEqual("xyz", ex.Trailers[0].Key); + Assert.AreEqual("xyz-value", ex.Trailers[0].Value); + + var ex2 = Assert.ThrowsAsync(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "abc")); + Assert.AreEqual(StatusCode.Unauthenticated, ex2.Status.StatusCode); + Assert.AreEqual(1, ex2.Trailers.Count); + Assert.AreEqual("xyz", ex2.Trailers[0].Key); + Assert.AreEqual("xyz-value", ex2.Trailers[0].Value); + } + + [Test] + public async Task ClientStreamingCall() + { + helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => + { + string result = ""; + await requestStream.ForEachAsync((request) => + { + result += request; + return TaskUtils.CompletedTask; + }); + await Task.Delay(100); + return result; + }); + + var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()); + await call.RequestStream.WriteAllAsync(new string[] { "A", "B", "C" }); + Assert.AreEqual("ABC", await call.ResponseAsync); + + Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode); + Assert.IsNotNull(call.GetTrailers()); + } + + [Test] + public async Task ServerStreamingCall() + { + helper.ServerStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => + { + await responseStream.WriteAllAsync(request.Split(new []{' '})); + context.ResponseTrailers.Add("xyz", ""); + }); + + var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), "A B C"); + CollectionAssert.AreEqual(new string[] { "A", "B", "C" }, await call.ResponseStream.ToListAsync()); + + Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode); + Assert.AreEqual("xyz", call.GetTrailers()[0].Key); + } + + [Test] + public async Task ServerStreamingCall_EndOfStreamIsIdempotent() + { + helper.ServerStreamingHandler = new ServerStreamingServerMethod((request, responseStream, context) => TaskUtils.CompletedTask); + + var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), ""); + + Assert.IsFalse(await call.ResponseStream.MoveNext()); + Assert.IsFalse(await call.ResponseStream.MoveNext()); + } + + [Test] + public void ServerStreamingCall_ErrorCanBeAwaitedTwice() + { + helper.ServerStreamingHandler = new ServerStreamingServerMethod((request, responseStream, context) => + { + context.Status = new Status(StatusCode.InvalidArgument, ""); + return TaskUtils.CompletedTask; + }); + + var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), ""); + + var ex = Assert.ThrowsAsync(async () => await call.ResponseStream.MoveNext()); + Assert.AreEqual(StatusCode.InvalidArgument, ex.Status.StatusCode); + + // attempting MoveNext again should result in throwing the same exception. + var ex2 = Assert.ThrowsAsync(async () => await call.ResponseStream.MoveNext()); + Assert.AreEqual(StatusCode.InvalidArgument, ex2.Status.StatusCode); + } + + [Test] + public void ServerStreamingCall_TrailersFromMultipleSourcesGetConcatenated() + { + helper.ServerStreamingHandler = new ServerStreamingServerMethod((request, responseStream, context) => + { + context.ResponseTrailers.Add("xyz", "xyz-value"); + throw new RpcException(new Status(StatusCode.InvalidArgument, ""), new Metadata { {"abc", "abc-value"} }); + }); + + var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), ""); + + var ex = Assert.ThrowsAsync(async () => await call.ResponseStream.MoveNext()); + Assert.AreEqual(StatusCode.InvalidArgument, ex.Status.StatusCode); + Assert.AreEqual(2, call.GetTrailers().Count); + Assert.AreEqual(2, ex.Trailers.Count); + Assert.AreEqual("xyz", ex.Trailers[0].Key); + Assert.AreEqual("xyz-value", ex.Trailers[0].Value); + Assert.AreEqual("abc", ex.Trailers[1].Key); + Assert.AreEqual("abc-value", ex.Trailers[1].Value); + } + + [Test] + public async Task DuplexStreamingCall() + { + helper.DuplexStreamingHandler = new DuplexStreamingServerMethod(async (requestStream, responseStream, context) => + { + while (await requestStream.MoveNext()) + { + await responseStream.WriteAsync(requestStream.Current); + } + context.ResponseTrailers.Add("xyz", "xyz-value"); + }); + + var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall()); + await call.RequestStream.WriteAllAsync(new string[] { "A", "B", "C" }); + CollectionAssert.AreEqual(new string[] { "A", "B", "C" }, await call.ResponseStream.ToListAsync()); + + Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode); + Assert.AreEqual("xyz-value", call.GetTrailers()[0].Value); + } + + [Test] + public async Task AsyncUnaryCall_EchoMetadata() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + foreach (Metadata.Entry metadataEntry in context.RequestHeaders) + { + if (metadataEntry.Key != "user-agent") + { + context.ResponseTrailers.Add(metadataEntry); + } + } + return Task.FromResult(""); + }); + + var headers = new Metadata + { + { "ascii-header", "abcdefg" }, + { "binary-header-bin", new byte[] { 1, 2, 3, 0, 0xff } } + }; + var call = Calls.AsyncUnaryCall(helper.CreateUnaryCall(new CallOptions(headers: headers)), "ABC"); + await call; + + Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode); + + var trailers = call.GetTrailers(); + Assert.AreEqual(2, trailers.Count); + Assert.AreEqual(headers[0].Key, trailers[0].Key); + Assert.AreEqual(headers[0].Value, trailers[0].Value); + + Assert.AreEqual(headers[1].Key, trailers[1].Key); + CollectionAssert.AreEqual(headers[1].ValueBytes, trailers[1].ValueBytes); + } + + [Test] + public void UnknownMethodHandler() + { + var nonexistentMethod = new Method( + MethodType.Unary, + MockServiceHelper.ServiceName, + "NonExistentMethod", + Marshallers.StringMarshaller, + Marshallers.StringMarshaller); + + var callDetails = new CallInvocationDetails(channel, nonexistentMethod, new CallOptions()); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(callDetails, "abc")); + Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode); + } + + [Test] + public void StatusDetailIsUtf8() + { + // some japanese and chinese characters + var nonAsciiString = "\u30a1\u30a2\u30a3 \u62b5\u6297\u662f\u5f92\u52b3\u7684"; + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + context.Status = new Status(StatusCode.Unknown, nonAsciiString); + return Task.FromResult(""); + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); + Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode); + Assert.AreEqual(nonAsciiString, ex.Status.Detail); + } + + [Test] + public void ServerCallContext_PeerInfoPresent() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult(context.Peer); + }); + + string peer = Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"); + Assert.IsTrue(peer.Contains(Host)); + } + + [Test] + public void ServerCallContext_HostAndMethodPresent() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + Assert.IsTrue(context.Host.Contains(Host)); + Assert.AreEqual("/tests.Test/Unary", context.Method); + return Task.FromResult("PASS"); + }); + Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); + } + + [Test] + public void ServerCallContext_AuthContextNotPopulated() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + Assert.IsFalse(context.AuthContext.IsPeerAuthenticated); + Assert.AreEqual(0, context.AuthContext.Properties.Count()); + return Task.FromResult("PASS"); + }); + Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/CompressionTest.cs b/src/csharp/Grpc.Core.Tests/CompressionTest.cs new file mode 100644 index 00000000..7dd22e9b --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/CompressionTest.cs @@ -0,0 +1,153 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class CompressionTest + { + MockServiceHelper helper; + Server server; + Channel channel; + + [SetUp] + public void Init() + { + helper = new MockServiceHelper(); + + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void WriteOptions_Unary() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + context.WriteOptions = new WriteOptions(WriteFlags.NoCompress); + return Task.FromResult(request); + }); + + var callOptions = new CallOptions(writeOptions: new WriteOptions(WriteFlags.NoCompress)); + Calls.BlockingUnaryCall(helper.CreateUnaryCall(callOptions), "abc"); + } + + [Test] + public async Task WriteOptions_DuplexStreaming() + { + helper.DuplexStreamingHandler = new DuplexStreamingServerMethod(async (requestStream, responseStream, context) => + { + await requestStream.ToListAsync(); + + context.WriteOptions = new WriteOptions(WriteFlags.NoCompress); + + await context.WriteResponseHeadersAsync(new Metadata { { "ascii-header", "abcdefg" } }); + + await responseStream.WriteAsync("X"); + + responseStream.WriteOptions = null; + await responseStream.WriteAsync("Y"); + + responseStream.WriteOptions = new WriteOptions(WriteFlags.NoCompress); + await responseStream.WriteAsync("Z"); + }); + + var callOptions = new CallOptions(writeOptions: new WriteOptions(WriteFlags.NoCompress)); + var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall(callOptions)); + + // check that write options from call options are propagated to request stream. + Assert.IsTrue((call.RequestStream.WriteOptions.Flags & WriteFlags.NoCompress) != 0); + + call.RequestStream.WriteOptions = new WriteOptions(); + await call.RequestStream.WriteAsync("A"); + + call.RequestStream.WriteOptions = null; + await call.RequestStream.WriteAsync("B"); + + call.RequestStream.WriteOptions = new WriteOptions(WriteFlags.NoCompress); + await call.RequestStream.WriteAsync("C"); + + await call.RequestStream.CompleteAsync(); + + await call.ResponseStream.ToListAsync(); + } + + [Test] + public void CanReadCompressedMessages() + { + var compressionMetadata = new Metadata + { + { new Metadata.Entry(Metadata.CompressionRequestAlgorithmMetadataKey, "gzip") } + }; + + helper.UnaryHandler = new UnaryServerMethod(async (req, context) => + { + await context.WriteResponseHeadersAsync(compressionMetadata); + return req; + }); + + var stringBuilder = new StringBuilder(); + for (int i = 0; i < 200000; i++) + { + stringBuilder.Append('a'); + } + var request = stringBuilder.ToString(); + var response = Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(compressionMetadata)), request); + + Assert.AreEqual(request, response); + } + + [Test] + public void CanReadCompressedMessages_EmptyPayload() + { + var compressionMetadata = new Metadata + { + { new Metadata.Entry(Metadata.CompressionRequestAlgorithmMetadataKey, "gzip") } + }; + + helper.UnaryHandler = new UnaryServerMethod(async (req, context) => + { + await context.WriteResponseHeadersAsync(compressionMetadata); + return req; + }); + + var request = ""; + var response = Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(compressionMetadata)), request); + + Assert.AreEqual(request, response); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs b/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs new file mode 100644 index 00000000..097db777 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ContextPropagationTest.cs @@ -0,0 +1,181 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class ContextPropagationTest + { + MockServiceHelper helper; + Server server; + Channel channel; + + [SetUp] + public void Init() + { + helper = new MockServiceHelper(); + + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public async Task PropagateCancellation() + { + var readyToCancelTcs = new TaskCompletionSource(); + var successTcs = new TaskCompletionSource(); + + helper.UnaryHandler = new UnaryServerMethod(async (request, context) => + { + readyToCancelTcs.SetResult(null); // child call running, ready to parent call + + while (!context.CancellationToken.IsCancellationRequested) + { + await Task.Delay(10); + } + successTcs.SetResult("CHILD_CALL_CANCELLED"); + return ""; + }); + + helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => + { + var propagationToken = context.CreatePropagationToken(); + Assert.IsNotNull(propagationToken.AsImplOrNull().ParentCall); + + var callOptions = new CallOptions(propagationToken: propagationToken); + try + { + await Calls.AsyncUnaryCall(helper.CreateUnaryCall(callOptions), "xyz"); + } + catch(RpcException) + { + // Child call will get cancelled, eat the exception. + } + return ""; + }); + + var cts = new CancellationTokenSource(); + var parentCall = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(cancellationToken: cts.Token))); + await readyToCancelTcs.Task; + cts.Cancel(); + try + { + // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock. + await parentCall; + Assert.Fail(); + } + catch (RpcException) + { + } + Assert.AreEqual("CHILD_CALL_CANCELLED", await successTcs.Task); + } + + [Test] + public async Task PropagateDeadline() + { + var deadline = DateTime.UtcNow.AddDays(7); + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + Assert.IsTrue(context.Deadline < deadline.AddHours(1)); + Assert.IsTrue(context.Deadline > deadline.AddHours(-1)); + return Task.FromResult("PASS"); + }); + + helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => + { + Assert.Throws(typeof(ArgumentException), () => + { + // Trying to override deadline while propagating deadline from parent call will throw. + Calls.BlockingUnaryCall(helper.CreateUnaryCall( + new CallOptions(deadline: DateTime.UtcNow.AddDays(8), + propagationToken: context.CreatePropagationToken())), ""); + }); + + var callOptions = new CallOptions(propagationToken: context.CreatePropagationToken()); + return await Calls.AsyncUnaryCall(helper.CreateUnaryCall(callOptions), "xyz"); + }); + + var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(deadline: deadline))); + await call.RequestStream.CompleteAsync(); + Assert.AreEqual("PASS", await call); + } + + [Test] + public async Task SuppressDeadlinePropagation() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + Assert.AreEqual(DateTime.MaxValue, context.Deadline); + return Task.FromResult("PASS"); + }); + + helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => + { + Assert.IsTrue(context.CancellationToken.CanBeCanceled); + + var callOptions = new CallOptions(propagationToken: context.CreatePropagationToken(new ContextPropagationOptions(propagateDeadline: false))); + return await Calls.AsyncUnaryCall(helper.CreateUnaryCall(callOptions), "xyz"); + }); + + var cts = new CancellationTokenSource(); + var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall(new CallOptions(deadline: DateTime.UtcNow.AddDays(7)))); + await call.RequestStream.CompleteAsync(); + Assert.AreEqual("PASS", await call); + } + + [Test] + public void ForeignPropagationTokenInterpretedAsNull() + { + Assert.IsNull(new ForeignContextPropagationToken().AsImplOrNull()); + } + + [Test] + public async Task ForeignPropagationTokenIsIgnored() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult("PASS"); + }); + + var callOptions = new CallOptions(propagationToken: new ForeignContextPropagationToken()); + await Calls.AsyncUnaryCall(helper.CreateUnaryCall(callOptions), "xyz"); + } + + // For testing, represents context propagation token that's not generated by Grpc.Core + private class ForeignContextPropagationToken : ContextPropagationToken + { + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/ContextualMarshallerTest.cs b/src/csharp/Grpc.Core.Tests/ContextualMarshallerTest.cs new file mode 100644 index 00000000..dbceb27b --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ContextualMarshallerTest.cs @@ -0,0 +1,121 @@ +#region Copyright notice and license + +// Copyright 2018 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class ContextualMarshallerTest + { + const string Host = "127.0.0.1"; + + MockServiceHelper helper; + Server server; + Channel channel; + + [SetUp] + public void Init() + { + var contextualMarshaller = new Marshaller( + (str, serializationContext) => + { + if (str == "UNSERIALIZABLE_VALUE") + { + // Google.Protobuf throws exception inherited from IOException + throw new IOException("Error serializing the message."); + } + if (str == "SERIALIZE_TO_NULL") + { + // for contextual marshaller, serializing to null payload corresponds + // to not calling the Complete() method in the serializer. + return; + } + var bytes = System.Text.Encoding.UTF8.GetBytes(str); + serializationContext.Complete(bytes); + }, + (deserializationContext) => + { + var buffer = deserializationContext.PayloadAsNewBuffer(); + Assert.AreEqual(buffer.Length, deserializationContext.PayloadLength); + var s = System.Text.Encoding.UTF8.GetString(buffer); + if (s == "UNPARSEABLE_VALUE") + { + // Google.Protobuf throws exception inherited from IOException + throw new IOException("Error parsing the message."); + } + return s; + }); + helper = new MockServiceHelper(Host, contextualMarshaller); + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void UnaryCall() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult(request); + }); + Assert.AreEqual("ABC", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "ABC")); + } + + [Test] + public void ResponseParsingError_UnaryResponse() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult("UNPARSEABLE_VALUE"); + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "REQUEST")); + Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); + } + + [Test] + public void RequestSerializationError_BlockingUnary() + { + Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "UNSERIALIZABLE_VALUE")); + } + + [Test] + public void SerializationResultIsNull_BlockingUnary() + { + Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "SERIALIZE_TO_NULL")); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/FakeCredentials.cs b/src/csharp/Grpc.Core.Tests/FakeCredentials.cs new file mode 100644 index 00000000..e38e0e13 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/FakeCredentials.cs @@ -0,0 +1,50 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using Grpc.Core.Internal; + +namespace Grpc.Core.Tests +{ + internal class FakeChannelCredentials : ChannelCredentials + { + readonly bool composable; + + public FakeChannelCredentials(bool composable) + { + this.composable = composable; + } + + internal override bool IsComposable + { + get { return composable; } + } + + public override void InternalPopulateConfiguration(ChannelCredentialsConfiguratorBase configurator, object state) + { + // not invoking configuration on purpose + } + } + + internal class FakeCallCredentials : CallCredentials + { + public override void InternalPopulateConfiguration(CallCredentialsConfiguratorBase configurator, object state) + { + // not invoking the configurator on purpose + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs new file mode 100644 index 00000000..fc9d5599 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs @@ -0,0 +1,94 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Linq; +using System.Threading; +using Grpc.Core; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class GrpcEnvironmentTest + { + [Test] + public void InitializeAndShutdownGrpcEnvironment() + { + var env = GrpcEnvironment.AddRef(); + Assert.IsTrue(env.CompletionQueues.Count > 0); + for (int i = 0; i < env.CompletionQueues.Count; i++) + { + Assert.IsNotNull(env.CompletionQueues.ElementAt(i)); + } + GrpcEnvironment.ReleaseAsync().Wait(); + } + + [Test] + public void SubsequentInvocations() + { + var env1 = GrpcEnvironment.AddRef(); + var env2 = GrpcEnvironment.AddRef(); + Assert.AreSame(env1, env2); + GrpcEnvironment.ReleaseAsync().Wait(); + GrpcEnvironment.ReleaseAsync().Wait(); + } + + [Test] + public void InitializeAfterShutdown() + { + Assert.AreEqual(0, GrpcEnvironment.GetRefCount()); + + var env1 = GrpcEnvironment.AddRef(); + GrpcEnvironment.ReleaseAsync().Wait(); + + var env2 = GrpcEnvironment.AddRef(); + GrpcEnvironment.ReleaseAsync().Wait(); + + Assert.AreNotSame(env1, env2); + } + + [Test] + public void ReleaseWithoutAddRef() + { + Assert.AreEqual(0, GrpcEnvironment.GetRefCount()); + Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await GrpcEnvironment.ReleaseAsync()); + } + + [Test] + public void GetCoreVersionString() + { + var coreVersion = GrpcEnvironment.GetCoreVersionString(); + var parts = coreVersion.Split('.'); + Assert.AreEqual(3, parts.Length); + } + + [Test] + public void ShuttingDownEventIsFired() + { + var cts = new CancellationTokenSource(); + var handler = new EventHandler((sender, args) => { cts.Cancel(); }); + + GrpcEnvironment.ShuttingDown += handler; + var env = GrpcEnvironment.AddRef(); + GrpcEnvironment.ReleaseAsync().Wait(); + GrpcEnvironment.ShuttingDown -= handler; + + Assert.IsTrue(cts.Token.IsCancellationRequested); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/HalfcloseTest.cs b/src/csharp/Grpc.Core.Tests/HalfcloseTest.cs new file mode 100644 index 00000000..5fc8fb69 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/HalfcloseTest.cs @@ -0,0 +1,82 @@ +#region Copyright notice and license + +// Copyright 2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class HalfcloseTest + { + MockServiceHelper helper; + Server server; + Channel channel; + + [SetUp] + public void Init() + { + helper = new MockServiceHelper(); + + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + /// + /// For client streaming and duplex streaming calls, if server does a full close + /// before we halfclose the request stream, an attempt to halfclose + /// (complete the request stream) shouldn't be treated as an error. + /// + [Test] + public async Task HalfcloseAfterFullclose_ClientStreamingCall() + { + helper.ClientStreamingHandler = new ClientStreamingServerMethod((requestStream, context) => + { + return Task.FromResult("PASS"); + }); + + var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()); + // make sure server has fullclosed on us + Assert.AreEqual("PASS", await call.ResponseAsync); + + // sending close from client should be still fine because server can finish + // the call anytime and we cannot do anything about it on the client side. + await call.RequestStream.CompleteAsync(); + + // Second attempt to close from client is not allowed. + Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await call.RequestStream.CompleteAsync()); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Interceptors/ClientInterceptorTest.cs b/src/csharp/Grpc.Core.Tests/Interceptors/ClientInterceptorTest.cs new file mode 100644 index 00000000..02f6f6ff --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Interceptors/ClientInterceptorTest.cs @@ -0,0 +1,228 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Interceptors; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using Grpc.Core.Tests; +using NUnit.Framework; + +namespace Grpc.Core.Interceptors.Tests +{ + public class ClientInterceptorTest + { + const string Host = "127.0.0.1"; + + [Test] + public void AddRequestHeaderInClientInterceptor() + { + const string HeaderKey = "x-client-interceptor"; + const string HeaderValue = "hello-world"; + var helper = new MockServiceHelper(Host); + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + var interceptorHeader = context.RequestHeaders.Last(m => (m.Key == HeaderKey)).Value; + Assert.AreEqual(interceptorHeader, HeaderValue); + return Task.FromResult("PASS"); + }); + var server = helper.GetServer(); + server.Start(); + var callInvoker = helper.GetChannel().Intercept(metadata => + { + metadata = metadata ?? new Metadata(); + metadata.Add(new Metadata.Entry(HeaderKey, HeaderValue)); + return metadata; + }); + Assert.AreEqual("PASS", callInvoker.BlockingUnaryCall(new Method(MethodType.Unary, MockServiceHelper.ServiceName, "Unary", Marshallers.StringMarshaller, Marshallers.StringMarshaller), Host, new CallOptions(), "")); + } + + [Test] + public void CheckInterceptorOrderInClientInterceptors() + { + var helper = new MockServiceHelper(Host); + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult("PASS"); + }); + var server = helper.GetServer(); + server.Start(); + var stringBuilder = new StringBuilder(); + var callInvoker = helper.GetChannel().Intercept(metadata => { + stringBuilder.Append("interceptor1"); + return metadata; + }).Intercept(new CallbackInterceptor(() => stringBuilder.Append("array1")), + new CallbackInterceptor(() => stringBuilder.Append("array2")), + new CallbackInterceptor(() => stringBuilder.Append("array3"))) + .Intercept(metadata => + { + stringBuilder.Append("interceptor2"); + return metadata; + }).Intercept(metadata => + { + stringBuilder.Append("interceptor3"); + return metadata; + }); + Assert.AreEqual("PASS", callInvoker.BlockingUnaryCall(new Method(MethodType.Unary, MockServiceHelper.ServiceName, "Unary", Marshallers.StringMarshaller, Marshallers.StringMarshaller), Host, new CallOptions(), "")); + Assert.AreEqual("interceptor3interceptor2array1array2array3interceptor1", stringBuilder.ToString()); + } + + [Test] + public void CheckNullInterceptorRegistrationFails() + { + var helper = new MockServiceHelper(Host); + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult("PASS"); + }); + Assert.Throws(() => helper.GetChannel().Intercept(default(Interceptor))); + Assert.Throws(() => helper.GetChannel().Intercept(new[]{default(Interceptor)})); + Assert.Throws(() => helper.GetChannel().Intercept(new[]{new CallbackInterceptor(()=>{}), null})); + Assert.Throws(() => helper.GetChannel().Intercept(default(Interceptor[]))); + } + + [Test] + public async Task CountNumberOfRequestsInClientInterceptors() + { + var helper = new MockServiceHelper(Host); + helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => + { + var stringBuilder = new StringBuilder(); + await requestStream.ForEachAsync(request => + { + stringBuilder.Append(request); + return TaskUtils.CompletedTask; + }); + await Task.Delay(100); + return stringBuilder.ToString(); + }); + + var callInvoker = helper.GetChannel().Intercept(new ClientStreamingCountingInterceptor()); + + var server = helper.GetServer(); + server.Start(); + var call = callInvoker.AsyncClientStreamingCall(new Method(MethodType.ClientStreaming, MockServiceHelper.ServiceName, "ClientStreaming", Marshallers.StringMarshaller, Marshallers.StringMarshaller), Host, new CallOptions()); + await call.RequestStream.WriteAllAsync(new string[] { "A", "B", "C" }); + Assert.AreEqual("3", await call.ResponseAsync); + + Assert.AreEqual(StatusCode.OK, call.GetStatus().StatusCode); + Assert.IsNotNull(call.GetTrailers()); + } + + private class CallbackInterceptor : Interceptor + { + readonly Action callback; + + public CallbackInterceptor(Action callback) + { + this.callback = GrpcPreconditions.CheckNotNull(callback, nameof(callback)); + } + + public override TResponse BlockingUnaryCall(TRequest request, ClientInterceptorContext context, BlockingUnaryCallContinuation continuation) + { + callback(); + return continuation(request, context); + } + + public override AsyncUnaryCall AsyncUnaryCall(TRequest request, ClientInterceptorContext context, AsyncUnaryCallContinuation continuation) + { + callback(); + return continuation(request, context); + } + + public override AsyncServerStreamingCall AsyncServerStreamingCall(TRequest request, ClientInterceptorContext context, AsyncServerStreamingCallContinuation continuation) + { + callback(); + return continuation(request, context); + } + + public override AsyncClientStreamingCall AsyncClientStreamingCall(ClientInterceptorContext context, AsyncClientStreamingCallContinuation continuation) + { + callback(); + return continuation(context); + } + + public override AsyncDuplexStreamingCall AsyncDuplexStreamingCall(ClientInterceptorContext context, AsyncDuplexStreamingCallContinuation continuation) + { + callback(); + return continuation(context); + } + } + + private class ClientStreamingCountingInterceptor : Interceptor + { + public override AsyncClientStreamingCall AsyncClientStreamingCall(ClientInterceptorContext context, AsyncClientStreamingCallContinuation continuation) + { + var response = continuation(context); + int counter = 0; + var requestStream = new WrappedClientStreamWriter(response.RequestStream, + message => { counter++; return message; }, null); + var responseAsync = response.ResponseAsync.ContinueWith( + unaryResponse => (TResponse)(object)counter.ToString() // Cast to object first is needed to satisfy the type-checker + ); + return new AsyncClientStreamingCall(requestStream, responseAsync, response.ResponseHeadersAsync, response.GetStatus, response.GetTrailers, response.Dispose); + } + } + + private class WrappedClientStreamWriter : IClientStreamWriter + { + readonly IClientStreamWriter writer; + readonly Func onMessage; + readonly Action onResponseStreamEnd; + public WrappedClientStreamWriter(IClientStreamWriter writer, Func onMessage, Action onResponseStreamEnd) + { + this.writer = writer; + this.onMessage = onMessage; + this.onResponseStreamEnd = onResponseStreamEnd; + } + public Task CompleteAsync() + { + if (onResponseStreamEnd != null) + { + return writer.CompleteAsync().ContinueWith(x => onResponseStreamEnd()); + } + return writer.CompleteAsync(); + } + public Task WriteAsync(T message) + { + if (onMessage != null) + { + message = onMessage(message); + } + return writer.WriteAsync(message); + } + public WriteOptions WriteOptions + { + get + { + return writer.WriteOptions; + } + set + { + writer.WriteOptions = value; + } + } + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Interceptors/ServerInterceptorTest.cs b/src/csharp/Grpc.Core.Tests/Interceptors/ServerInterceptorTest.cs new file mode 100644 index 00000000..66990832 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Interceptors/ServerInterceptorTest.cs @@ -0,0 +1,173 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Interceptors; +using Grpc.Core.Internal; +using Grpc.Core.Tests; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Interceptors.Tests +{ + public class ServerInterceptorTest + { + const string Host = "127.0.0.1"; + + [Test] + public void AddRequestHeaderInServerInterceptor() + { + var helper = new MockServiceHelper(Host); + const string MetadataKey = "x-interceptor"; + const string MetadataValue = "hello world"; + var interceptor = new ServerCallContextInterceptor(ctx => ctx.RequestHeaders.Add(new Metadata.Entry(MetadataKey, MetadataValue))); + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + var interceptorHeader = context.RequestHeaders.Last(m => (m.Key == MetadataKey)).Value; + Assert.AreEqual(interceptorHeader, MetadataValue); + return Task.FromResult("PASS"); + }); + helper.ServiceDefinition = helper.ServiceDefinition.Intercept(interceptor); + var server = helper.GetServer(); + server.Start(); + var channel = helper.GetChannel(); + Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "")); + } + + [Test] + public void VerifyInterceptorOrdering() + { + var helper = new MockServiceHelper(Host); + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult("PASS"); + }); + var stringBuilder = new StringBuilder(); + helper.ServiceDefinition = helper.ServiceDefinition + .Intercept(new ServerCallContextInterceptor(ctx => stringBuilder.Append("A"))) + .Intercept(new ServerCallContextInterceptor(ctx => stringBuilder.Append("B1")), + new ServerCallContextInterceptor(ctx => stringBuilder.Append("B2")), + new ServerCallContextInterceptor(ctx => stringBuilder.Append("B3"))) + .Intercept(new ServerCallContextInterceptor(ctx => stringBuilder.Append("C"))); + var server = helper.GetServer(); + server.Start(); + var channel = helper.GetChannel(); + Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "")); + Assert.AreEqual("CB1B2B3A", stringBuilder.ToString()); + } + + [Test] + public void UserStateVisibleToAllInterceptors() + { + object key1 = new object(); + object value1 = new object(); + const string key2 = "Interceptor #2"; + const string value2 = "Important state"; + + var interceptor1 = new ServerCallContextInterceptor(ctx => { + // state starts off empty + Assert.AreEqual(0, ctx.UserState.Count); + + ctx.UserState.Add(key1, value1); + }); + + var interceptor2 = new ServerCallContextInterceptor(ctx => { + // second interceptor can see state set by the first + bool found = ctx.UserState.TryGetValue(key1, out object storedValue1); + Assert.IsTrue(found); + Assert.AreEqual(value1, storedValue1); + + ctx.UserState.Add(key2, value2); + }); + + var helper = new MockServiceHelper(Host); + helper.UnaryHandler = new UnaryServerMethod((request, context) => { + // call handler can see all the state + bool found = context.UserState.TryGetValue(key1, out object storedValue1); + Assert.IsTrue(found); + Assert.AreEqual(value1, storedValue1); + + found = context.UserState.TryGetValue(key2, out object storedValue2); + Assert.IsTrue(found); + Assert.AreEqual(value2, storedValue2); + + return Task.FromResult("PASS"); + }); + helper.ServiceDefinition = helper.ServiceDefinition + .Intercept(interceptor2) + .Intercept(interceptor1); + + var server = helper.GetServer(); + server.Start(); + var channel = helper.GetChannel(); + Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "")); + } + + [Test] + public void CheckNullInterceptorRegistrationFails() + { + var helper = new MockServiceHelper(Host); + var sd = helper.ServiceDefinition; + Assert.Throws(() => sd.Intercept(default(Interceptor))); + Assert.Throws(() => sd.Intercept(new[]{default(Interceptor)})); + Assert.Throws(() => sd.Intercept(new[]{new ServerCallContextInterceptor(ctx=>{}), null})); + Assert.Throws(() => sd.Intercept(default(Interceptor[]))); + } + + private class ServerCallContextInterceptor : Interceptor + { + readonly Action interceptor; + + public ServerCallContextInterceptor(Action interceptor) + { + GrpcPreconditions.CheckNotNull(interceptor, nameof(interceptor)); + this.interceptor = interceptor; + } + + public override Task UnaryServerHandler(TRequest request, ServerCallContext context, UnaryServerMethod continuation) + { + interceptor(context); + return continuation(request, context); + } + + public override Task ClientStreamingServerHandler(IAsyncStreamReader requestStream, ServerCallContext context, ClientStreamingServerMethod continuation) + { + interceptor(context); + return continuation(requestStream, context); + } + + public override Task ServerStreamingServerHandler(TRequest request, IServerStreamWriter responseStream, ServerCallContext context, ServerStreamingServerMethod continuation) + { + interceptor(context); + return continuation(request, responseStream, context); + } + + public override Task DuplexStreamingServerHandler(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context, DuplexStreamingServerMethod continuation) + { + interceptor(context); + return continuation(requestStream, responseStream, context); + } + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs new file mode 100644 index 00000000..fd221613 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs @@ -0,0 +1,194 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +using Grpc.Core.Internal; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + /// + /// Uses fake native call to test interaction of AsyncCallServer wrapping code with C core in different situations. + /// + public class AsyncCallServerTest + { + Server server; + FakeNativeCall fakeCall; + AsyncCallServer asyncCallServer; + FakeBufferReaderManager fakeBufferReaderManager; + + [SetUp] + public void Init() + { + // Create a fake server just so we have an instance to refer to. + // The server won't actually be used at all. + server = new Server() + { + Ports = { { "localhost", 0, ServerCredentials.Insecure } } + }; + server.Start(); + + fakeCall = new FakeNativeCall(); + asyncCallServer = new AsyncCallServer( + Marshallers.StringMarshaller.ContextualSerializer, Marshallers.StringMarshaller.ContextualDeserializer, + server); + asyncCallServer.InitializeForTesting(fakeCall); + fakeBufferReaderManager = new FakeBufferReaderManager(); + } + + [TearDown] + public void Cleanup() + { + fakeBufferReaderManager.Dispose(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void CancelNotificationAfterStartDisposes() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + fakeCall.ReceivedCloseOnServerCallback.OnReceivedCloseOnServer(true, cancelled: true); + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + [Test] + public void CancelNotificationAfterStartDisposesAfterPendingReadFinishes() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + var requestStream = new ServerRequestStream(asyncCallServer); + + var moveNextTask = requestStream.MoveNext(); + + fakeCall.ReceivedCloseOnServerCallback.OnReceivedCloseOnServer(true, cancelled: true); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateNullResponse()); + Assert.IsFalse(moveNextTask.Result); + + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + [Test] + public void ReadAfterCancelNotificationCanSucceed() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + var requestStream = new ServerRequestStream(asyncCallServer); + + fakeCall.ReceivedCloseOnServerCallback.OnReceivedCloseOnServer(true, cancelled: true); + + // Check that starting a read after cancel notification has been processed is legal. + var moveNextTask = requestStream.MoveNext(); + Assert.IsFalse(moveNextTask.Result); + + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + [Test] + public void ReadCompletionFailureClosesRequestStream() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + var requestStream = new ServerRequestStream(asyncCallServer); + + // if a read completion's success==false, the request stream will silently finish + // and we rely on C core cancelling the call. + var moveNextTask = requestStream.MoveNext(); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(false, CreateNullResponse()); + Assert.IsFalse(moveNextTask.Result); + + fakeCall.ReceivedCloseOnServerCallback.OnReceivedCloseOnServer(true, cancelled: true); + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + [Test] + public void WriteAfterCancelNotificationFails() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + var responseStream = new ServerResponseStream(asyncCallServer); + + fakeCall.ReceivedCloseOnServerCallback.OnReceivedCloseOnServer(true, cancelled: true); + + // TODO(jtattermusch): should we throw a different exception type instead? + Assert.Throws(typeof(InvalidOperationException), () => responseStream.WriteAsync("request1")); + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + [Test] + public void WriteCompletionFailureThrows() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + var responseStream = new ServerResponseStream(asyncCallServer); + + var writeTask = responseStream.WriteAsync("request1"); + fakeCall.SendCompletionCallback.OnSendCompletion(false); + Assert.ThrowsAsync(typeof(IOException), async () => await writeTask); + + fakeCall.ReceivedCloseOnServerCallback.OnReceivedCloseOnServer(true, cancelled: true); + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + [Test] + public void WriteAndWriteStatusCanRunConcurrently() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + var responseStream = new ServerResponseStream(asyncCallServer); + + var writeTask = responseStream.WriteAsync("request1"); + var writeStatusTask = asyncCallServer.SendStatusFromServerAsync(Status.DefaultSuccess, new Metadata(), null); + + fakeCall.SendCompletionCallback.OnSendCompletion(true); + fakeCall.SendStatusFromServerCallback.OnSendStatusFromServerCompletion(true); + + Assert.DoesNotThrowAsync(async () => await writeTask); + Assert.DoesNotThrowAsync(async () => await writeStatusTask); + + fakeCall.ReceivedCloseOnServerCallback.OnReceivedCloseOnServer(true, cancelled: true); + + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + [Test] + public void WriteAfterWriteStatusThrowsInvalidOperationException() + { + var finishedTask = asyncCallServer.ServerSideCallAsync(); + var responseStream = new ServerResponseStream(asyncCallServer); + + asyncCallServer.SendStatusFromServerAsync(Status.DefaultSuccess, new Metadata(), null); + Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await responseStream.WriteAsync("request1")); + + fakeCall.SendStatusFromServerCallback.OnSendStatusFromServerCompletion(true); + fakeCall.ReceivedCloseOnServerCallback.OnReceivedCloseOnServer(true, cancelled: true); + + AssertFinished(asyncCallServer, fakeCall, finishedTask); + } + + static void AssertFinished(AsyncCallServer asyncCallServer, FakeNativeCall fakeCall, Task finishedTask) + { + Assert.IsTrue(fakeCall.IsDisposed); + Assert.IsTrue(finishedTask.IsCompleted); + Assert.DoesNotThrow(() => finishedTask.Wait()); + } + + IBufferReader CreateNullResponse() + { + return fakeBufferReaderManager.CreateNullPayloadBufferReader(); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallStateTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallStateTest.cs new file mode 100644 index 00000000..f85b0f59 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallStateTest.cs @@ -0,0 +1,82 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System.Threading.Tasks; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class AsyncCallStateTest + { + [Test] + public void Stateless() + { + bool disposed = false; + Task responseHeaders = Task.FromResult(new Metadata()); + Metadata trailers = new Metadata(); + var state = new AsyncCallState(responseHeaders, () => new Status(StatusCode.DataLoss, "oops"), + () => trailers, () => disposed = true); + + Assert.AreSame(responseHeaders, state.ResponseHeadersAsync()); + + var status = state.GetStatus(); + Assert.AreEqual(StatusCode.DataLoss, status.StatusCode); + Assert.AreEqual("oops", status.Detail); + + Assert.AreSame(trailers, state.GetTrailers()); + + Assert.False(disposed); + state.Dispose(); + Assert.True(disposed); + } + + class State + { + public bool disposed = false; + public Task responseHeaders = Task.FromResult(new Metadata()); + public Metadata trailers = new Metadata(); + public Status status = new Status(StatusCode.DataLoss, "oops"); + public void Dispose() { disposed = true; } + } + + [Test] + public void WithState() + { + var callbackState = new State(); + + var state = new AsyncCallState( + obj => ((State)obj).responseHeaders, + obj => ((State)obj).status, + obj => ((State)obj).trailers, + obj => ((State)obj).Dispose(), + callbackState); + + Assert.AreSame(callbackState.responseHeaders, state.ResponseHeadersAsync()); + + var status = state.GetStatus(); + Assert.AreEqual(StatusCode.DataLoss, status.StatusCode); + Assert.AreEqual("oops", status.Detail); + + Assert.AreSame(callbackState.trailers, state.GetTrailers()); + + Assert.False(callbackState.disposed); + state.Dispose(); + Assert.True(callbackState.disposed); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs new file mode 100644 index 00000000..e337f907 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs @@ -0,0 +1,766 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + /// + /// Uses fake native call to test interaction of AsyncCall wrapping code with C core in different situations. + /// + public class AsyncCallTest + { + Channel channel; + FakeNativeCall fakeCall; + AsyncCall asyncCall; + FakeBufferReaderManager fakeBufferReaderManager; + + [SetUp] + public void Init() + { + channel = new Channel("localhost", ChannelCredentials.Insecure); + + fakeCall = new FakeNativeCall(); + + var callDetails = new CallInvocationDetails(channel, "someMethod", null, Marshallers.StringMarshaller, Marshallers.StringMarshaller, new CallOptions()); + asyncCall = new AsyncCall(callDetails, fakeCall); + fakeBufferReaderManager = new FakeBufferReaderManager(); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + fakeBufferReaderManager.Dispose(); + } + + [Test] + public void AsyncUnary_CanBeStartedOnlyOnce() + { + asyncCall.UnaryCallAsync("request1"); + Assert.Throws(typeof(InvalidOperationException), + () => asyncCall.UnaryCallAsync("abc")); + } + + [Test] + public void AsyncUnary_StreamingOperationsNotAllowed() + { + asyncCall.UnaryCallAsync("request1"); + Assert.ThrowsAsync(typeof(InvalidOperationException), + async () => await asyncCall.ReadMessageAsync()); + Assert.Throws(typeof(InvalidOperationException), + () => asyncCall.SendMessageAsync("abc", new WriteFlags())); + } + + [Test] + public void AsyncUnary_Success() + { + var resultTask = asyncCall.UnaryCallAsync("request1"); + fakeCall.UnaryResponseClientCallback.OnUnaryResponseClient(true, + new ClientSideStatus(Status.DefaultSuccess, new Metadata()), + CreateResponsePayload(), + new Metadata()); + + AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); + } + + [Test] + public void AsyncUnary_NonSuccessStatusCode() + { + var resultTask = asyncCall.UnaryCallAsync("request1"); + fakeCall.UnaryResponseClientCallback.OnUnaryResponseClient(true, + CreateClientSideStatus(StatusCode.InvalidArgument), + CreateNullResponse(), + new Metadata()); + + AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.InvalidArgument); + } + + [Test] + public void AsyncUnary_NullResponsePayload() + { + var resultTask = asyncCall.UnaryCallAsync("request1"); + fakeCall.UnaryResponseClientCallback.OnUnaryResponseClient(true, + new ClientSideStatus(Status.DefaultSuccess, new Metadata()), + null, + new Metadata()); + + // failure to deserialize will result in InvalidArgument status. + AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal); + } + + [Test] + public void AsyncUnary_RequestSerializationExceptionDoesntLeakResources() + { + string nullRequest = null; // will throw when serializing + Assert.Throws(typeof(ArgumentNullException), () => asyncCall.UnaryCallAsync(nullRequest)); + Assert.AreEqual(0, channel.GetCallReferenceCount()); + Assert.IsTrue(fakeCall.IsDisposed); + } + + [Test] + public void AsyncUnary_StartCallFailureDoesntLeakResources() + { + fakeCall.MakeStartCallFail(); + Assert.Throws(typeof(InvalidOperationException), () => asyncCall.UnaryCallAsync("request1")); + Assert.AreEqual(0, channel.GetCallReferenceCount()); + Assert.IsTrue(fakeCall.IsDisposed); + } + + [Test] + public void SyncUnary_RequestSerializationExceptionDoesntLeakResources() + { + string nullRequest = null; // will throw when serializing + Assert.Throws(typeof(ArgumentNullException), () => asyncCall.UnaryCall(nullRequest)); + Assert.AreEqual(0, channel.GetCallReferenceCount()); + Assert.IsTrue(fakeCall.IsDisposed); + } + + [Test] + public void SyncUnary_StartCallFailureDoesntLeakResources() + { + fakeCall.MakeStartCallFail(); + Assert.Throws(typeof(InvalidOperationException), () => asyncCall.UnaryCall("request1")); + Assert.AreEqual(0, channel.GetCallReferenceCount()); + Assert.IsTrue(fakeCall.IsDisposed); + } + + [Test] + public void ClientStreaming_StreamingReadNotAllowed() + { + asyncCall.ClientStreamingCallAsync(); + Assert.ThrowsAsync(typeof(InvalidOperationException), + async () => await asyncCall.ReadMessageAsync()); + } + + [Test] + public void ClientStreaming_NoRequest_Success() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + fakeCall.UnaryResponseClientCallback.OnUnaryResponseClient(true, + new ClientSideStatus(Status.DefaultSuccess, new Metadata()), + CreateResponsePayload(), + new Metadata()); + + AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); + } + + [Test] + public void ClientStreaming_NoRequest_NonSuccessStatusCode() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + fakeCall.UnaryResponseClientCallback.OnUnaryResponseClient(true, + CreateClientSideStatus(StatusCode.InvalidArgument), + CreateNullResponse(), + new Metadata()); + + AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.InvalidArgument); + } + + [Test] + public void ClientStreaming_MoreRequests_Success() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + + var writeTask = requestStream.WriteAsync("request1"); + fakeCall.SendCompletionCallback.OnSendCompletion(true); + writeTask.Wait(); + + var writeTask2 = requestStream.WriteAsync("request2"); + fakeCall.SendCompletionCallback.OnSendCompletion(true); + writeTask2.Wait(); + + var completeTask = requestStream.CompleteAsync(); + fakeCall.SendCompletionCallback.OnSendCompletion(true); + completeTask.Wait(); + + fakeCall.UnaryResponseClientCallback.OnUnaryResponseClient(true, + new ClientSideStatus(Status.DefaultSuccess, new Metadata()), + CreateResponsePayload(), + new Metadata()); + + AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); + } + + [Test] + public void ClientStreaming_WriteFailureThrowsRpcException() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + + var writeTask = requestStream.WriteAsync("request1"); + fakeCall.SendCompletionCallback.OnSendCompletion(false); + + // The write will wait for call to finish to receive the status code. + Assert.IsFalse(writeTask.IsCompleted); + + fakeCall.UnaryResponseClientCallback.OnUnaryResponseClient(true, + CreateClientSideStatus(StatusCode.Internal), + CreateNullResponse(), + new Metadata()); + + var ex = Assert.ThrowsAsync(async () => await writeTask); + Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); + + AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal); + } + + [Test] + public void ClientStreaming_WriteFailureThrowsRpcException2() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + + var writeTask = requestStream.WriteAsync("request1"); + + fakeCall.UnaryResponseClientCallback.OnUnaryResponseClient(true, + CreateClientSideStatus(StatusCode.Internal), + CreateNullResponse(), + new Metadata()); + + fakeCall.SendCompletionCallback.OnSendCompletion(false); + + var ex = Assert.ThrowsAsync(async () => await writeTask); + Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); + + AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal); + } + + [Test] + public void ClientStreaming_WriteFailureThrowsRpcException3() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + + var writeTask = requestStream.WriteAsync("request1"); + fakeCall.SendCompletionCallback.OnSendCompletion(false); + + // Until the delayed write completion has been triggered, + // we still act as if there was an active write. + Assert.Throws(typeof(InvalidOperationException), () => requestStream.WriteAsync("request2")); + + fakeCall.UnaryResponseClientCallback.OnUnaryResponseClient(true, + CreateClientSideStatus(StatusCode.Internal), + CreateNullResponse(), + new Metadata()); + + var ex = Assert.ThrowsAsync(async () => await writeTask); + Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); + + // Following attempts to write keep delivering the same status + var ex2 = Assert.ThrowsAsync(async () => await requestStream.WriteAsync("after call has finished")); + Assert.AreEqual(StatusCode.Internal, ex2.Status.StatusCode); + + AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal); + } + + [Test] + public void ClientStreaming_WriteAfterReceivingStatusThrowsRpcException() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + + fakeCall.UnaryResponseClientCallback.OnUnaryResponseClient(true, + new ClientSideStatus(Status.DefaultSuccess, new Metadata()), + CreateResponsePayload(), + new Metadata()); + + AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); + + var writeTask = requestStream.WriteAsync("request1"); + var ex = Assert.ThrowsAsync(async () => await writeTask); + Assert.AreEqual(Status.DefaultSuccess, ex.Status); + } + + [Test] + public void ClientStreaming_WriteAfterReceivingStatusThrowsRpcException2() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + + fakeCall.UnaryResponseClientCallback.OnUnaryResponseClient(true, + new ClientSideStatus(new Status(StatusCode.OutOfRange, ""), new Metadata()), + CreateResponsePayload(), + new Metadata()); + + AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.OutOfRange); + + var writeTask = requestStream.WriteAsync("request1"); + var ex = Assert.ThrowsAsync(async () => await writeTask); + Assert.AreEqual(StatusCode.OutOfRange, ex.Status.StatusCode); + } + + [Test] + public void ClientStreaming_WriteAfterCompleteThrowsInvalidOperationException() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + + requestStream.CompleteAsync(); + + Assert.Throws(typeof(InvalidOperationException), () => requestStream.WriteAsync("request1")); + + fakeCall.SendCompletionCallback.OnSendCompletion(true); + + fakeCall.UnaryResponseClientCallback.OnUnaryResponseClient(true, + new ClientSideStatus(Status.DefaultSuccess, new Metadata()), + CreateResponsePayload(), + new Metadata()); + + AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); + } + + [Test] + public void ClientStreaming_CompleteAfterReceivingStatusSucceeds() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + + fakeCall.UnaryResponseClientCallback.OnUnaryResponseClient(true, + new ClientSideStatus(Status.DefaultSuccess, new Metadata()), + CreateResponsePayload(), + new Metadata()); + + AssertUnaryResponseSuccess(asyncCall, fakeCall, resultTask); + Assert.DoesNotThrowAsync(async () => await requestStream.CompleteAsync()); + } + + [Test] + public void ClientStreaming_WriteAfterCancellationRequestThrowsTaskCanceledException() + { + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + + asyncCall.Cancel(); + Assert.IsTrue(fakeCall.IsCancelled); + + var writeTask = requestStream.WriteAsync("request1"); + Assert.ThrowsAsync(typeof(TaskCanceledException), async () => await writeTask); + + fakeCall.UnaryResponseClientCallback.OnUnaryResponseClient(true, + CreateClientSideStatus(StatusCode.Cancelled), + CreateNullResponse(), + new Metadata()); + + AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Cancelled); + } + + [Test] + public void ClientStreaming_StartCallFailureDoesntLeakResources() + { + fakeCall.MakeStartCallFail(); + Assert.Throws(typeof(InvalidOperationException), () => asyncCall.ClientStreamingCallAsync()); + Assert.AreEqual(0, channel.GetCallReferenceCount()); + Assert.IsTrue(fakeCall.IsDisposed); + } + + [Test] + public void ServerStreaming_StreamingSendNotAllowed() + { + asyncCall.StartServerStreamingCall("request1"); + Assert.Throws(typeof(InvalidOperationException), + () => asyncCall.SendMessageAsync("abc", new WriteFlags())); + } + + [Test] + public void ServerStreaming_NoResponse_Success1() + { + asyncCall.StartServerStreamingCall("request1"); + var responseStream = new ClientResponseStream(asyncCall); + var readTask = responseStream.MoveNext(); + + fakeCall.ReceivedResponseHeadersCallback.OnReceivedResponseHeaders(true, new Metadata()); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateNullResponse()); + fakeCall.ReceivedStatusOnClientCallback.OnReceivedStatusOnClient(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); + + AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); + } + + [Test] + public void ServerStreaming_NoResponse_Success2() + { + asyncCall.StartServerStreamingCall("request1"); + var responseStream = new ClientResponseStream(asyncCall); + var readTask = responseStream.MoveNext(); + + // try alternative order of completions + fakeCall.ReceivedStatusOnClientCallback.OnReceivedStatusOnClient(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateNullResponse()); + fakeCall.ReceivedResponseHeadersCallback.OnReceivedResponseHeaders(true, new Metadata()); + + AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); + } + + [Test] + public void ServerStreaming_NoResponse_Success3() + { + asyncCall.StartServerStreamingCall("request1"); + var responseStream = new ClientResponseStream(asyncCall); + var readTask = responseStream.MoveNext(); + + // try alternative order of completions + fakeCall.ReceivedStatusOnClientCallback.OnReceivedStatusOnClient(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); + fakeCall.ReceivedResponseHeadersCallback.OnReceivedResponseHeaders(true, new Metadata()); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateNullResponse()); + + AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); + } + + [Test] + public void ServerStreaming_NoResponse_ReadFailure() + { + asyncCall.StartServerStreamingCall("request1"); + var responseStream = new ClientResponseStream(asyncCall); + var readTask = responseStream.MoveNext(); + + fakeCall.ReceivedResponseHeadersCallback.OnReceivedResponseHeaders(true, new Metadata()); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + + fakeCall.ReceivedMessageCallback.OnReceivedMessage(false, CreateNullResponse()); // after a failed read, we rely on C core to deliver appropriate status code. + fakeCall.ReceivedStatusOnClientCallback.OnReceivedStatusOnClient(true, CreateClientSideStatus(StatusCode.Internal)); + + AssertStreamingResponseError(asyncCall, fakeCall, readTask, StatusCode.Internal); + } + + [Test] + public void ServerStreaming_MoreResponses_Success() + { + asyncCall.StartServerStreamingCall("request1"); + var responseStream = new ClientResponseStream(asyncCall); + + fakeCall.ReceivedResponseHeadersCallback.OnReceivedResponseHeaders(true, new Metadata()); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + + var readTask1 = responseStream.MoveNext(); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateResponsePayload()); + Assert.IsTrue(readTask1.Result); + Assert.AreEqual("response1", responseStream.Current); + + var readTask2 = responseStream.MoveNext(); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateResponsePayload()); + Assert.IsTrue(readTask2.Result); + Assert.AreEqual("response1", responseStream.Current); + + var readTask3 = responseStream.MoveNext(); + fakeCall.ReceivedStatusOnClientCallback.OnReceivedStatusOnClient(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateNullResponse()); + + AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask3); + } + + [Test] + public void ServerStreaming_RequestSerializationExceptionDoesntLeakResources() + { + string nullRequest = null; // will throw when serializing + Assert.Throws(typeof(ArgumentNullException), () => asyncCall.StartServerStreamingCall(nullRequest)); + Assert.AreEqual(0, channel.GetCallReferenceCount()); + Assert.IsTrue(fakeCall.IsDisposed); + + var responseStream = new ClientResponseStream(asyncCall); + var readTask = responseStream.MoveNext(); + } + + [Test] + public void ServerStreaming_StartCallFailureDoesntLeakResources() + { + fakeCall.MakeStartCallFail(); + Assert.Throws(typeof(InvalidOperationException), () => asyncCall.StartServerStreamingCall("request1")); + Assert.AreEqual(0, channel.GetCallReferenceCount()); + Assert.IsTrue(fakeCall.IsDisposed); + } + + [Test] + public void DuplexStreaming_NoRequestNoResponse_Success1() + { + asyncCall.StartDuplexStreamingCall(); + var requestStream = new ClientRequestStream(asyncCall); + var responseStream = new ClientResponseStream(asyncCall); + + fakeCall.ReceivedResponseHeadersCallback.OnReceivedResponseHeaders(true, new Metadata()); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + + var writeTask1 = requestStream.CompleteAsync(); + fakeCall.SendCompletionCallback.OnSendCompletion(true); + Assert.DoesNotThrowAsync(async () => await writeTask1); + + var readTask = responseStream.MoveNext(); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateNullResponse()); + fakeCall.ReceivedStatusOnClientCallback.OnReceivedStatusOnClient(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); + + AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); + } + + [Test] + public void DuplexStreaming_NoRequestNoResponse_Success2() + { + asyncCall.StartDuplexStreamingCall(); + var requestStream = new ClientRequestStream(asyncCall); + var responseStream = new ClientResponseStream(asyncCall); + + var writeTask1 = requestStream.CompleteAsync(); + fakeCall.SendCompletionCallback.OnSendCompletion(true); + Assert.DoesNotThrowAsync(async () => await writeTask1); + + var readTask = responseStream.MoveNext(); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateNullResponse()); + fakeCall.ReceivedStatusOnClientCallback.OnReceivedStatusOnClient(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); + + fakeCall.ReceivedResponseHeadersCallback.OnReceivedResponseHeaders(true, new Metadata()); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + + AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); + } + + [Test] + public void DuplexStreaming_WriteAfterReceivingStatusThrowsRpcException() + { + asyncCall.StartDuplexStreamingCall(); + var requestStream = new ClientRequestStream(asyncCall); + var responseStream = new ClientResponseStream(asyncCall); + + fakeCall.ReceivedResponseHeadersCallback.OnReceivedResponseHeaders(true, new Metadata()); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + + var readTask = responseStream.MoveNext(); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateNullResponse()); + fakeCall.ReceivedStatusOnClientCallback.OnReceivedStatusOnClient(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); + + AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); + + var writeTask = requestStream.WriteAsync("request1"); + var ex = Assert.ThrowsAsync(async () => await writeTask); + Assert.AreEqual(Status.DefaultSuccess, ex.Status); + } + + [Test] + public void DuplexStreaming_CompleteAfterReceivingStatusSuceeds() + { + asyncCall.StartDuplexStreamingCall(); + var requestStream = new ClientRequestStream(asyncCall); + var responseStream = new ClientResponseStream(asyncCall); + + fakeCall.ReceivedResponseHeadersCallback.OnReceivedResponseHeaders(true, new Metadata()); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + + var readTask = responseStream.MoveNext(); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateNullResponse()); + fakeCall.ReceivedStatusOnClientCallback.OnReceivedStatusOnClient(true, new ClientSideStatus(Status.DefaultSuccess, new Metadata())); + + AssertStreamingResponseSuccess(asyncCall, fakeCall, readTask); + + Assert.DoesNotThrowAsync(async () => await requestStream.CompleteAsync()); + } + + [Test] + public void DuplexStreaming_WriteFailureThrowsRpcException() + { + asyncCall.StartDuplexStreamingCall(); + var requestStream = new ClientRequestStream(asyncCall); + var responseStream = new ClientResponseStream(asyncCall); + + fakeCall.ReceivedResponseHeadersCallback.OnReceivedResponseHeaders(true, new Metadata()); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + + var writeTask = requestStream.WriteAsync("request1"); + fakeCall.SendCompletionCallback.OnSendCompletion(false); + + // The write will wait for call to finish to receive the status code. + Assert.IsFalse(writeTask.IsCompleted); + + var readTask = responseStream.MoveNext(); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateNullResponse()); + fakeCall.ReceivedStatusOnClientCallback.OnReceivedStatusOnClient(true, CreateClientSideStatus(StatusCode.PermissionDenied)); + + var ex = Assert.ThrowsAsync(async () => await writeTask); + Assert.AreEqual(StatusCode.PermissionDenied, ex.Status.StatusCode); + + AssertStreamingResponseError(asyncCall, fakeCall, readTask, StatusCode.PermissionDenied); + } + + [Test] + public void DuplexStreaming_WriteFailureThrowsRpcException2() + { + asyncCall.StartDuplexStreamingCall(); + var requestStream = new ClientRequestStream(asyncCall); + var responseStream = new ClientResponseStream(asyncCall); + + fakeCall.ReceivedResponseHeadersCallback.OnReceivedResponseHeaders(true, new Metadata()); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + + var writeTask = requestStream.WriteAsync("request1"); + + var readTask = responseStream.MoveNext(); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateNullResponse()); + fakeCall.ReceivedStatusOnClientCallback.OnReceivedStatusOnClient(true, CreateClientSideStatus(StatusCode.PermissionDenied)); + fakeCall.SendCompletionCallback.OnSendCompletion(false); + + var ex = Assert.ThrowsAsync(async () => await writeTask); + Assert.AreEqual(StatusCode.PermissionDenied, ex.Status.StatusCode); + + AssertStreamingResponseError(asyncCall, fakeCall, readTask, StatusCode.PermissionDenied); + } + + [Test] + public void DuplexStreaming_WriteAfterCancellationRequestThrowsTaskCanceledException() + { + asyncCall.StartDuplexStreamingCall(); + var requestStream = new ClientRequestStream(asyncCall); + var responseStream = new ClientResponseStream(asyncCall); + + fakeCall.ReceivedResponseHeadersCallback.OnReceivedResponseHeaders(true, new Metadata()); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + + asyncCall.Cancel(); + Assert.IsTrue(fakeCall.IsCancelled); + + var writeTask = requestStream.WriteAsync("request1"); + Assert.ThrowsAsync(typeof(TaskCanceledException), async () => await writeTask); + + var readTask = responseStream.MoveNext(); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateNullResponse()); + fakeCall.ReceivedStatusOnClientCallback.OnReceivedStatusOnClient(true, CreateClientSideStatus(StatusCode.Cancelled)); + + AssertStreamingResponseError(asyncCall, fakeCall, readTask, StatusCode.Cancelled); + } + + [Test] + public void DuplexStreaming_ReadAfterCancellationRequestCanSucceed() + { + asyncCall.StartDuplexStreamingCall(); + var responseStream = new ClientResponseStream(asyncCall); + + fakeCall.ReceivedResponseHeadersCallback.OnReceivedResponseHeaders(true, new Metadata()); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + + asyncCall.Cancel(); + Assert.IsTrue(fakeCall.IsCancelled); + + var readTask1 = responseStream.MoveNext(); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateResponsePayload()); + Assert.IsTrue(readTask1.Result); + Assert.AreEqual("response1", responseStream.Current); + + var readTask2 = responseStream.MoveNext(); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateNullResponse()); + fakeCall.ReceivedStatusOnClientCallback.OnReceivedStatusOnClient(true, CreateClientSideStatus(StatusCode.Cancelled)); + + AssertStreamingResponseError(asyncCall, fakeCall, readTask2, StatusCode.Cancelled); + } + + [Test] + public void DuplexStreaming_ReadStartedBeforeCancellationRequestCanSucceed() + { + asyncCall.StartDuplexStreamingCall(); + var responseStream = new ClientResponseStream(asyncCall); + + fakeCall.ReceivedResponseHeadersCallback.OnReceivedResponseHeaders(true, new Metadata()); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + + var readTask1 = responseStream.MoveNext(); // initiate the read before cancel request + asyncCall.Cancel(); + Assert.IsTrue(fakeCall.IsCancelled); + + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateResponsePayload()); + Assert.IsTrue(readTask1.Result); + Assert.AreEqual("response1", responseStream.Current); + + var readTask2 = responseStream.MoveNext(); + fakeCall.ReceivedMessageCallback.OnReceivedMessage(true, CreateNullResponse()); + fakeCall.ReceivedStatusOnClientCallback.OnReceivedStatusOnClient(true, CreateClientSideStatus(StatusCode.Cancelled)); + + AssertStreamingResponseError(asyncCall, fakeCall, readTask2, StatusCode.Cancelled); + } + + [Test] + public void DuplexStreaming_StartCallFailureDoesntLeakResources() + { + fakeCall.MakeStartCallFail(); + Assert.Throws(typeof(InvalidOperationException), () => asyncCall.StartDuplexStreamingCall()); + Assert.AreEqual(0, channel.GetCallReferenceCount()); + Assert.IsTrue(fakeCall.IsDisposed); + } + + ClientSideStatus CreateClientSideStatus(StatusCode statusCode) + { + return new ClientSideStatus(new Status(statusCode, ""), new Metadata()); + } + + IBufferReader CreateResponsePayload() + { + return fakeBufferReaderManager.CreateSingleSegmentBufferReader(Marshallers.StringMarshaller.Serializer("response1")); + } + + IBufferReader CreateNullResponse() + { + return fakeBufferReaderManager.CreateNullPayloadBufferReader(); + } + + static void AssertUnaryResponseSuccess(AsyncCall asyncCall, FakeNativeCall fakeCall, Task resultTask) + { + Assert.IsTrue(resultTask.IsCompleted); + Assert.IsTrue(fakeCall.IsDisposed); + + Assert.AreEqual(Status.DefaultSuccess, asyncCall.GetStatus()); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + Assert.AreEqual(0, asyncCall.GetTrailers().Count); + Assert.AreEqual("response1", resultTask.Result); + } + + static void AssertStreamingResponseSuccess(AsyncCall asyncCall, FakeNativeCall fakeCall, Task moveNextTask) + { + Assert.IsTrue(moveNextTask.IsCompleted); + Assert.IsTrue(fakeCall.IsDisposed); + + Assert.IsFalse(moveNextTask.Result); + Assert.AreEqual(Status.DefaultSuccess, asyncCall.GetStatus()); + Assert.AreEqual(0, asyncCall.GetTrailers().Count); + } + + static void AssertUnaryResponseError(AsyncCall asyncCall, FakeNativeCall fakeCall, Task resultTask, StatusCode expectedStatusCode) + { + Assert.IsTrue(resultTask.IsCompleted); + Assert.IsTrue(fakeCall.IsDisposed); + + Assert.AreEqual(expectedStatusCode, asyncCall.GetStatus().StatusCode); + var ex = Assert.ThrowsAsync(async () => await resultTask); + Assert.AreEqual(expectedStatusCode, ex.Status.StatusCode); + Assert.AreEqual(0, asyncCall.ResponseHeadersAsync.Result.Count); + Assert.AreEqual(0, asyncCall.GetTrailers().Count); + } + + static void AssertStreamingResponseError(AsyncCall asyncCall, FakeNativeCall fakeCall, Task moveNextTask, StatusCode expectedStatusCode) + { + Assert.IsTrue(moveNextTask.IsCompleted); + Assert.IsTrue(fakeCall.IsDisposed); + + var ex = Assert.ThrowsAsync(async () => await moveNextTask); + Assert.AreEqual(expectedStatusCode, ex.Status.StatusCode); + Assert.AreEqual(expectedStatusCode, asyncCall.GetStatus().StatusCode); + Assert.AreEqual(0, asyncCall.GetTrailers().Count); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/ChannelArgsSafeHandleTest.cs b/src/csharp/Grpc.Core.Tests/Internal/ChannelArgsSafeHandleTest.cs new file mode 100644 index 00000000..d3722e3e --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/ChannelArgsSafeHandleTest.cs @@ -0,0 +1,60 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class ChannelArgsSafeHandleTest + { + [Test] + public void CreateEmptyAndDestroy() + { + var channelArgs = ChannelArgsSafeHandle.Create(0); + channelArgs.Dispose(); + } + + [Test] + public void CreateNonEmptyAndDestroy() + { + var channelArgs = ChannelArgsSafeHandle.Create(5); + channelArgs.Dispose(); + } + + [Test] + public void CreateNullAndDestroy() + { + var channelArgs = ChannelArgsSafeHandle.CreateNull(); + channelArgs.Dispose(); + } + + [Test] + public void CreateFillAndDestroy() + { + var channelArgs = ChannelArgsSafeHandle.Create(3); + channelArgs.SetInteger(0, "somekey", 12345); + channelArgs.SetString(1, "somekey", "abcdefghijkl"); + channelArgs.SetString(2, "somekey", "XYZ"); + channelArgs.Dispose(); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/CompletionQueueEventTest.cs b/src/csharp/Grpc.Core.Tests/Internal/CompletionQueueEventTest.cs new file mode 100644 index 00000000..25952084 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/CompletionQueueEventTest.cs @@ -0,0 +1,40 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class CompletionQueueEventTest + { + [Test] + public void CompletionQueueEventSizeIsNativeSize() + { + #pragma warning disable 0618 + // We need to use the obsolete non-generic version of Marshal.SizeOf because the generic version is not available in net45 + Assert.AreEqual(CompletionQueueEvent.NativeSize, Marshal.SizeOf(typeof(CompletionQueueEvent))); + #pragma warning restore 0618 + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/CompletionQueueSafeHandleTest.cs b/src/csharp/Grpc.Core.Tests/Internal/CompletionQueueSafeHandleTest.cs new file mode 100644 index 00000000..a0ea1cc4 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/CompletionQueueSafeHandleTest.cs @@ -0,0 +1,52 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class CompletionQueueSafeHandleTest + { + [Test] + public void CreateSyncAndDestroy() + { + GrpcEnvironment.AddRef(); + var cq = CompletionQueueSafeHandle.CreateSync(); + cq.Dispose(); + GrpcEnvironment.ReleaseAsync().Wait(); + } + + [Test] + public void CreateAsyncAndShutdown() + { + var env = GrpcEnvironment.AddRef(); + var cq = CompletionQueueSafeHandle.CreateAsync(new CompletionRegistry(env, () => BatchContextSafeHandle.Create(), () => RequestCallContextSafeHandle.Create())); + cq.Shutdown(); + var ev = cq.Next(); + cq.Dispose(); + GrpcEnvironment.ReleaseAsync().Wait(); + Assert.AreEqual(CompletionQueueEvent.CompletionType.Shutdown, ev.type); + Assert.AreNotEqual(IntPtr.Zero, ev.success); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/DefaultDeserializationContextTest.cs b/src/csharp/Grpc.Core.Tests/Internal/DefaultDeserializationContextTest.cs new file mode 100644 index 00000000..8b635f92 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/DefaultDeserializationContextTest.cs @@ -0,0 +1,230 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class DefaultDeserializationContextTest + { + FakeBufferReaderManager fakeBufferReaderManager; + + [SetUp] + public void Init() + { + fakeBufferReaderManager = new FakeBufferReaderManager(); + } + + [TearDown] + public void Cleanup() + { + fakeBufferReaderManager.Dispose(); + } + + [TestCase] + public void PayloadAsReadOnlySequence_ZeroSegmentPayload() + { + var context = new DefaultDeserializationContext(); + context.Initialize(fakeBufferReaderManager.CreateMultiSegmentBufferReader(new List {})); + + Assert.AreEqual(0, context.PayloadLength); + + var sequence = context.PayloadAsReadOnlySequence(); + + Assert.AreEqual(ReadOnlySequence.Empty, sequence); + Assert.IsTrue(sequence.IsEmpty); + Assert.IsTrue(sequence.IsSingleSegment); + } + + [TestCase(0)] + [TestCase(1)] + [TestCase(10)] + [TestCase(100)] + [TestCase(1000)] + public void PayloadAsReadOnlySequence_SingleSegmentPayload(int segmentLength) + { + var origBuffer = GetTestBuffer(segmentLength); + var context = new DefaultDeserializationContext(); + context.Initialize(fakeBufferReaderManager.CreateSingleSegmentBufferReader(origBuffer)); + + Assert.AreEqual(origBuffer.Length, context.PayloadLength); + + var sequence = context.PayloadAsReadOnlySequence(); + + Assert.AreEqual(origBuffer.Length, sequence.Length); + Assert.AreEqual(origBuffer.Length, sequence.First.Length); + Assert.IsTrue(sequence.IsSingleSegment); + CollectionAssert.AreEqual(origBuffer, sequence.First.ToArray()); + } + + [TestCase(0, 5, 10)] + [TestCase(1, 1, 1)] + [TestCase(10, 100, 1000)] + [TestCase(100, 100, 10)] + [TestCase(1000, 1000, 1000)] + public void PayloadAsReadOnlySequence_MultiSegmentPayload(int segmentLen1, int segmentLen2, int segmentLen3) + { + var origBuffer1 = GetTestBuffer(segmentLen1); + var origBuffer2 = GetTestBuffer(segmentLen2); + var origBuffer3 = GetTestBuffer(segmentLen3); + int totalLen = origBuffer1.Length + origBuffer2.Length + origBuffer3.Length; + + var context = new DefaultDeserializationContext(); + context.Initialize(fakeBufferReaderManager.CreateMultiSegmentBufferReader(new List { origBuffer1, origBuffer2, origBuffer3 })); + + Assert.AreEqual(totalLen, context.PayloadLength); + + var sequence = context.PayloadAsReadOnlySequence(); + + Assert.AreEqual(totalLen, sequence.Length); + + var segmentEnumerator = sequence.GetEnumerator(); + + Assert.IsTrue(segmentEnumerator.MoveNext()); + CollectionAssert.AreEqual(origBuffer1, segmentEnumerator.Current.ToArray()); + + Assert.IsTrue(segmentEnumerator.MoveNext()); + CollectionAssert.AreEqual(origBuffer2, segmentEnumerator.Current.ToArray()); + + Assert.IsTrue(segmentEnumerator.MoveNext()); + CollectionAssert.AreEqual(origBuffer3, segmentEnumerator.Current.ToArray()); + + Assert.IsFalse(segmentEnumerator.MoveNext()); + } + + [TestCase] + public void NullPayloadNotAllowed() + { + var context = new DefaultDeserializationContext(); + Assert.Throws(typeof(InvalidOperationException), () => context.Initialize(fakeBufferReaderManager.CreateNullPayloadBufferReader())); + } + + [TestCase] + public void PayloadAsNewByteBuffer_ZeroSegmentPayload() + { + var context = new DefaultDeserializationContext(); + context.Initialize(fakeBufferReaderManager.CreateMultiSegmentBufferReader(new List {})); + + Assert.AreEqual(0, context.PayloadLength); + + var payload = context.PayloadAsNewBuffer(); + Assert.AreEqual(0, payload.Length); + } + + [TestCase(0)] + [TestCase(1)] + [TestCase(10)] + [TestCase(100)] + [TestCase(1000)] + public void PayloadAsNewByteBuffer_SingleSegmentPayload(int segmentLength) + { + var origBuffer = GetTestBuffer(segmentLength); + var context = new DefaultDeserializationContext(); + context.Initialize(fakeBufferReaderManager.CreateSingleSegmentBufferReader(origBuffer)); + + Assert.AreEqual(origBuffer.Length, context.PayloadLength); + + var payload = context.PayloadAsNewBuffer(); + CollectionAssert.AreEqual(origBuffer, payload); + } + + [TestCase(0, 5, 10)] + [TestCase(1, 1, 1)] + [TestCase(10, 100, 1000)] + [TestCase(100, 100, 10)] + [TestCase(1000, 1000, 1000)] + public void PayloadAsNewByteBuffer_MultiSegmentPayload(int segmentLen1, int segmentLen2, int segmentLen3) + { + var origBuffer1 = GetTestBuffer(segmentLen1); + var origBuffer2 = GetTestBuffer(segmentLen2); + var origBuffer3 = GetTestBuffer(segmentLen3); + + var context = new DefaultDeserializationContext(); + context.Initialize(fakeBufferReaderManager.CreateMultiSegmentBufferReader(new List { origBuffer1, origBuffer2, origBuffer3 })); + + var payload = context.PayloadAsNewBuffer(); + + var concatenatedOrigBuffers = new List(); + concatenatedOrigBuffers.AddRange(origBuffer1); + concatenatedOrigBuffers.AddRange(origBuffer2); + concatenatedOrigBuffers.AddRange(origBuffer3); + + Assert.AreEqual(concatenatedOrigBuffers.Count, context.PayloadLength); + Assert.AreEqual(concatenatedOrigBuffers.Count, payload.Length); + CollectionAssert.AreEqual(concatenatedOrigBuffers, payload); + } + + [TestCase] + public void GetPayloadMultipleTimesIsIllegal() + { + var origBuffer = GetTestBuffer(100); + var context = new DefaultDeserializationContext(); + context.Initialize(fakeBufferReaderManager.CreateSingleSegmentBufferReader(origBuffer)); + + Assert.AreEqual(origBuffer.Length, context.PayloadLength); + + var payload = context.PayloadAsNewBuffer(); + CollectionAssert.AreEqual(origBuffer, payload); + + // Getting payload multiple times is illegal + Assert.Throws(typeof(InvalidOperationException), () => context.PayloadAsNewBuffer()); + Assert.Throws(typeof(InvalidOperationException), () => context.PayloadAsReadOnlySequence()); + } + + [TestCase] + public void ResetContextAndReinitialize() + { + var origBuffer = GetTestBuffer(100); + var context = new DefaultDeserializationContext(); + context.Initialize(fakeBufferReaderManager.CreateSingleSegmentBufferReader(origBuffer)); + + Assert.AreEqual(origBuffer.Length, context.PayloadLength); + + // Reset invalidates context + context.Reset(); + + Assert.AreEqual(0, context.PayloadLength); + Assert.Throws(typeof(NullReferenceException), () => context.PayloadAsNewBuffer()); + Assert.Throws(typeof(NullReferenceException), () => context.PayloadAsReadOnlySequence()); + + // Previously reset context can be initialized again + var origBuffer2 = GetTestBuffer(50); + context.Initialize(fakeBufferReaderManager.CreateSingleSegmentBufferReader(origBuffer2)); + + Assert.AreEqual(origBuffer2.Length, context.PayloadLength); + CollectionAssert.AreEqual(origBuffer2, context.PayloadAsNewBuffer()); + } + + private byte[] GetTestBuffer(int length) + { + var testBuffer = new byte[length]; + for (int i = 0; i < testBuffer.Length; i++) + { + testBuffer[i] = (byte) i; + } + return testBuffer; + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/DefaultObjectPoolTest.cs b/src/csharp/Grpc.Core.Tests/Internal/DefaultObjectPoolTest.cs new file mode 100644 index 00000000..9c6f8a21 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/DefaultObjectPoolTest.cs @@ -0,0 +1,95 @@ +#region Copyright notice and license + +// Copyright 2017 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class DefaultObjectPoolTest + { + [Test] + [TestCase(10, 2)] + [TestCase(10, 1)] + [TestCase(0, 2)] + [TestCase(2, 0)] + public void ObjectIsReused(int sharedCapacity, int threadLocalCapacity) + { + var pool = new DefaultObjectPool(() => new TestPooledObject(), sharedCapacity, threadLocalCapacity); + var origLeased = pool.Lease(); + pool.Return(origLeased); + Assert.AreSame(origLeased, pool.Lease()); + Assert.AreNotSame(origLeased, pool.Lease()); + } + + [Test] + public void ZeroCapacities() + { + var pool = new DefaultObjectPool(() => new TestPooledObject(), 0, 0); + var origLeased = pool.Lease(); + pool.Return(origLeased); + Assert.AreNotSame(origLeased, pool.Lease()); + } + + [Test] + public void DisposeCleansSharedPool() + { + var pool = new DefaultObjectPool(() => new TestPooledObject(), 10, 0); + var origLeased = pool.Lease(); + pool.Return(origLeased); + pool.Dispose(); + Assert.AreNotSame(origLeased, pool.Lease()); + } + + [Test] + public void LeaseSetsReturnAction() + { + var pool = new DefaultObjectPool(() => new TestPooledObject(), 10, 0); + var origLeased = pool.Lease(); + origLeased.ReturnAction(origLeased); + pool.Dispose(); + Assert.AreNotSame(origLeased, pool.Lease()); + } + + [Test] + public void Constructor() + { + Assert.Throws(() => new DefaultObjectPool(null, 10, 2)); + Assert.Throws(() => new DefaultObjectPool(() => new TestPooledObject(), -1, 10)); + Assert.Throws(() => new DefaultObjectPool(() => new TestPooledObject(), 10, -1)); + } + + class TestPooledObject : IPooledObject + { + public Action ReturnAction; + + public void SetReturnToPoolAction(Action returnAction) + { + this.ReturnAction = returnAction; + } + + public void Dispose() + { + + } + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/DefaultSerializationContextTest.cs b/src/csharp/Grpc.Core.Tests/Internal/DefaultSerializationContextTest.cs new file mode 100644 index 00000000..061230d8 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/DefaultSerializationContextTest.cs @@ -0,0 +1,207 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class DefaultSerializationContextTest + { + [TestCase] + public void CompleteAllowedOnlyOnce() + { + using (var scope = NewDefaultSerializationContextScope()) + { + var context = scope.Context; + var buffer = GetTestBuffer(10); + + context.Complete(buffer); + Assert.Throws(typeof(InvalidOperationException), () => context.Complete(buffer)); + Assert.Throws(typeof(InvalidOperationException), () => context.Complete()); + } + } + + [TestCase] + public void CompleteAllowedOnlyOnce2() + { + using (var scope = NewDefaultSerializationContextScope()) + { + var context = scope.Context; + + context.Complete(); + Assert.Throws(typeof(InvalidOperationException), () => context.Complete(GetTestBuffer(10))); + Assert.Throws(typeof(InvalidOperationException), () => context.Complete()); + } + } + + [TestCase(0)] + [TestCase(1)] + [TestCase(10)] + [TestCase(100)] + [TestCase(1000)] + public void ByteArrayPayload(int payloadSize) + { + using (var scope = NewDefaultSerializationContextScope()) + { + var context = scope.Context; + var origPayload = GetTestBuffer(payloadSize); + + context.Complete(origPayload); + + var nativePayload = context.GetPayload().ToByteArray(); + CollectionAssert.AreEqual(origPayload, nativePayload); + } + } + + [TestCase(0)] + [TestCase(1)] + [TestCase(10)] + [TestCase(100)] + [TestCase(1000)] + public void BufferWriter_OneSegment(int payloadSize) + { + using (var scope = NewDefaultSerializationContextScope()) + { + var context = scope.Context; + var origPayload = GetTestBuffer(payloadSize); + + var bufferWriter = context.GetBufferWriter(); + origPayload.AsSpan().CopyTo(bufferWriter.GetSpan(payloadSize)); + bufferWriter.Advance(payloadSize); + context.Complete(); + + var nativePayload = context.GetPayload().ToByteArray(); + CollectionAssert.AreEqual(origPayload, nativePayload); + } + } + + [TestCase(0)] + [TestCase(1)] + [TestCase(10)] + [TestCase(100)] + [TestCase(1000)] + public void BufferWriter_OneSegment_GetMemory(int payloadSize) + { + using (var scope = NewDefaultSerializationContextScope()) + { + var context = scope.Context; + var origPayload = GetTestBuffer(payloadSize); + + var bufferWriter = context.GetBufferWriter(); + origPayload.AsSpan().CopyTo(bufferWriter.GetMemory(payloadSize).Span); + bufferWriter.Advance(payloadSize); + context.Complete(); + + var nativePayload = context.GetPayload().ToByteArray(); + CollectionAssert.AreEqual(origPayload, nativePayload); + } + } + + [TestCase(1, 4)] // small slice size tests grpc_slice with inline data + [TestCase(10, 4)] + [TestCase(100, 4)] + [TestCase(1000, 4)] + [TestCase(1, 64)] // larger slice size tests allocated grpc_slices + [TestCase(10, 64)] + [TestCase(1000, 50)] + [TestCase(1000, 64)] + public void BufferWriter_MultipleSegments(int payloadSize, int maxSliceSize) + { + using (var scope = NewDefaultSerializationContextScope()) + { + var context = scope.Context; + var origPayload = GetTestBuffer(payloadSize); + + var bufferWriter = context.GetBufferWriter(); + for (int offset = 0; offset < payloadSize; offset += maxSliceSize) + { + var sliceSize = Math.Min(maxSliceSize, payloadSize - offset); + // we allocate last slice as too big intentionally to test that shrinking works + var dest = bufferWriter.GetSpan(maxSliceSize); + + origPayload.AsSpan(offset, sliceSize).CopyTo(dest); + bufferWriter.Advance(sliceSize); + } + context.Complete(); + + var nativePayload = context.GetPayload().ToByteArray(); + CollectionAssert.AreEqual(origPayload, nativePayload); + } + } + + [TestCase] + public void ContextIsReusable() + { + using (var scope = NewDefaultSerializationContextScope()) + { + var context = scope.Context; + + Assert.Throws(typeof(NullReferenceException), () => context.GetPayload()); + + var origPayload1 = GetTestBuffer(10); + context.Complete(origPayload1); + CollectionAssert.AreEqual(origPayload1, context.GetPayload().ToByteArray()); + + context.Reset(); + + var origPayload2 = GetTestBuffer(20); + + var bufferWriter = context.GetBufferWriter(); + origPayload2.AsSpan().CopyTo(bufferWriter.GetMemory(origPayload2.Length).Span); + bufferWriter.Advance(origPayload2.Length); + context.Complete(); + CollectionAssert.AreEqual(origPayload2, context.GetPayload().ToByteArray()); + + context.Reset(); + + Assert.Throws(typeof(NullReferenceException), () => context.GetPayload()); + } + } + + [TestCase] + public void GetBufferWriterThrowsForCompletedContext() + { + using (var scope = NewDefaultSerializationContextScope()) + { + var context = scope.Context; + context.Complete(GetTestBuffer(10)); + + Assert.Throws(typeof(InvalidOperationException), () => context.GetBufferWriter()); + } + } + + private DefaultSerializationContext.UsageScope NewDefaultSerializationContextScope() + { + return new DefaultSerializationContext.UsageScope(new DefaultSerializationContext()); + } + + private byte[] GetTestBuffer(int length) + { + var testBuffer = new byte[length]; + for (int i = 0; i < testBuffer.Length; i++) + { + testBuffer[i] = (byte) i; + } + return testBuffer; + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/FakeBufferReaderManager.cs b/src/csharp/Grpc.Core.Tests/Internal/FakeBufferReaderManager.cs new file mode 100644 index 00000000..d8d0c0a6 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/FakeBufferReaderManager.cs @@ -0,0 +1,118 @@ +#region Copyright notice and license + +// Copyright 2018 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal.Tests +{ + // Creates instances of fake IBufferReader. All created instances will become invalid once Dispose is called. + internal class FakeBufferReaderManager : IDisposable + { + List pinnedHandles = new List(); + bool disposed = false; + public IBufferReader CreateSingleSegmentBufferReader(byte[] data) + { + return CreateMultiSegmentBufferReader(new List { data }); + } + + public IBufferReader CreateMultiSegmentBufferReader(IEnumerable dataSegments) + { + GrpcPreconditions.CheckState(!disposed); + GrpcPreconditions.CheckNotNull(dataSegments); + var segments = new List(); + foreach (var data in dataSegments) + { + GrpcPreconditions.CheckNotNull(data); + segments.Add(GCHandle.Alloc(data, GCHandleType.Pinned)); + } + pinnedHandles.AddRange(segments); // all the allocated GCHandles will be freed on Dispose() + return new FakeBufferReader(segments); + } + + public IBufferReader CreateNullPayloadBufferReader() + { + GrpcPreconditions.CheckState(!disposed); + return new FakeBufferReader(null); + } + + public void Dispose() + { + if (!disposed) + { + disposed = true; + for (int i = 0; i < pinnedHandles.Count; i++) + { + pinnedHandles[i].Free(); + } + } + } + + private class FakeBufferReader : IBufferReader + { + readonly List bufferSegments; + readonly int? totalLength; + readonly IEnumerator segmentEnumerator; + + public FakeBufferReader(List bufferSegments) + { + this.bufferSegments = bufferSegments; + this.totalLength = ComputeTotalLength(bufferSegments); + this.segmentEnumerator = bufferSegments?.GetEnumerator(); + } + + public int? TotalLength => totalLength; + + public bool TryGetNextSlice(out Slice slice) + { + GrpcPreconditions.CheckNotNull(bufferSegments); + if (!segmentEnumerator.MoveNext()) + { + slice = default(Slice); + return false; + } + + var segment = segmentEnumerator.Current; + int sliceLen = ((byte[]) segment.Target).Length; + slice = new Slice(segment.AddrOfPinnedObject(), sliceLen); + return true; + } + + static int? ComputeTotalLength(List bufferSegments) + { + if (bufferSegments == null) + { + return null; + } + + int sum = 0; + foreach (var segment in bufferSegments) + { + var data = (byte[]) segment.Target; + sum += data.Length; + } + return sum; + } + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/FakeBufferReaderManagerTest.cs b/src/csharp/Grpc.Core.Tests/Internal/FakeBufferReaderManagerTest.cs new file mode 100644 index 00000000..8211b7fe --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/FakeBufferReaderManagerTest.cs @@ -0,0 +1,121 @@ +#region Copyright notice and license + +// Copyright 2018 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class FakeBufferReaderManagerTest + { + FakeBufferReaderManager fakeBufferReaderManager; + + [SetUp] + public void Init() + { + fakeBufferReaderManager = new FakeBufferReaderManager(); + } + + [TearDown] + public void Cleanup() + { + fakeBufferReaderManager.Dispose(); + } + + [TestCase] + public void NullPayload() + { + var fakeBufferReader = fakeBufferReaderManager.CreateNullPayloadBufferReader(); + Assert.IsFalse(fakeBufferReader.TotalLength.HasValue); + Assert.Throws(typeof(ArgumentNullException), () => fakeBufferReader.TryGetNextSlice(out Slice slice)); + } + [TestCase] + public void ZeroSegmentPayload() + { + var fakeBufferReader = fakeBufferReaderManager.CreateMultiSegmentBufferReader(new List {}); + Assert.AreEqual(0, fakeBufferReader.TotalLength.Value); + Assert.IsFalse(fakeBufferReader.TryGetNextSlice(out Slice slice)); + } + + [TestCase(0)] + [TestCase(1)] + [TestCase(10)] + [TestCase(30)] + [TestCase(100)] + [TestCase(1000)] + public void SingleSegmentPayload(int bufferLen) + { + var origBuffer = GetTestBuffer(bufferLen); + var fakeBufferReader = fakeBufferReaderManager.CreateSingleSegmentBufferReader(origBuffer); + Assert.AreEqual(origBuffer.Length, fakeBufferReader.TotalLength.Value); + + Assert.IsTrue(fakeBufferReader.TryGetNextSlice(out Slice slice)); + AssertSliceDataEqual(origBuffer, slice); + + Assert.IsFalse(fakeBufferReader.TryGetNextSlice(out Slice slice2)); + } + + [TestCase(0, 5, 10)] + [TestCase(1, 1, 1)] + [TestCase(10, 100, 1000)] + [TestCase(100, 100, 10)] + [TestCase(1000, 1000, 1000)] + public void MultiSegmentPayload(int segmentLen1, int segmentLen2, int segmentLen3) + { + var origBuffer1 = GetTestBuffer(segmentLen1); + var origBuffer2 = GetTestBuffer(segmentLen2); + var origBuffer3 = GetTestBuffer(segmentLen3); + var fakeBufferReader = fakeBufferReaderManager.CreateMultiSegmentBufferReader(new List { origBuffer1, origBuffer2, origBuffer3 }); + + Assert.AreEqual(origBuffer1.Length + origBuffer2.Length + origBuffer3.Length, fakeBufferReader.TotalLength.Value); + + Assert.IsTrue(fakeBufferReader.TryGetNextSlice(out Slice slice1)); + AssertSliceDataEqual(origBuffer1, slice1); + + Assert.IsTrue(fakeBufferReader.TryGetNextSlice(out Slice slice2)); + AssertSliceDataEqual(origBuffer2, slice2); + + Assert.IsTrue(fakeBufferReader.TryGetNextSlice(out Slice slice3)); + AssertSliceDataEqual(origBuffer3, slice3); + + Assert.IsFalse(fakeBufferReader.TryGetNextSlice(out Slice slice4)); + } + + private void AssertSliceDataEqual(byte[] expected, Slice actual) + { + var actualSliceData = new byte[actual.Length]; + actual.ToSpanUnsafe().CopyTo(actualSliceData); + CollectionAssert.AreEqual(expected, actualSliceData); + } + + // create a buffer of given size and fill it with some data + private byte[] GetTestBuffer(int length) + { + var testBuffer = new byte[length]; + for (int i = 0; i < testBuffer.Length; i++) + { + testBuffer[i] = (byte) i; + } + return testBuffer; + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs b/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs new file mode 100644 index 00000000..c16b55ca --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/FakeNativeCall.cs @@ -0,0 +1,192 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +using Grpc.Core.Internal; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + /// + /// For testing purposes. + /// + internal class FakeNativeCall : INativeCall + { + private bool shouldStartCallFail; + public IUnaryResponseClientCallback UnaryResponseClientCallback + { + get; + set; + } + + public IReceivedStatusOnClientCallback ReceivedStatusOnClientCallback + { + get; + set; + } + + public IReceivedMessageCallback ReceivedMessageCallback + { + get; + set; + } + + public IReceivedResponseHeadersCallback ReceivedResponseHeadersCallback + { + get; + set; + } + + public ISendCompletionCallback SendCompletionCallback + { + get; + set; + } + + public ISendStatusFromServerCompletionCallback SendStatusFromServerCallback + { + get; + set; + } + + public IReceivedCloseOnServerCallback ReceivedCloseOnServerCallback + { + get; + set; + } + + public bool IsCancelled + { + get; + set; + } + + public bool IsDisposed + { + get; + set; + } + + public void Cancel() + { + IsCancelled = true; + } + + public void CancelWithStatus(Status status) + { + IsCancelled = true; + } + + public string GetPeer() + { + return "PEER"; + } + + public void StartUnary(IUnaryResponseClientCallback callback, SliceBufferSafeHandle payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) + { + StartCallMaybeFail(); + UnaryResponseClientCallback = callback; + } + + public void StartUnary(BatchContextSafeHandle ctx, SliceBufferSafeHandle payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) + { + StartCallMaybeFail(); + throw new NotImplementedException(); + } + + public void StartClientStreaming(IUnaryResponseClientCallback callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags) + { + StartCallMaybeFail(); + UnaryResponseClientCallback = callback; + } + + public void StartServerStreaming(IReceivedStatusOnClientCallback callback, SliceBufferSafeHandle payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) + { + StartCallMaybeFail(); + ReceivedStatusOnClientCallback = callback; + } + + public void StartDuplexStreaming(IReceivedStatusOnClientCallback callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags) + { + StartCallMaybeFail(); + ReceivedStatusOnClientCallback = callback; + } + + public void StartReceiveMessage(IReceivedMessageCallback callback) + { + ReceivedMessageCallback = callback; + } + + public void StartReceiveInitialMetadata(IReceivedResponseHeadersCallback callback) + { + ReceivedResponseHeadersCallback = callback; + } + + public void StartSendInitialMetadata(ISendCompletionCallback callback, MetadataArraySafeHandle metadataArray) + { + SendCompletionCallback = callback; + } + + public void StartSendMessage(ISendCompletionCallback callback, SliceBufferSafeHandle payload, WriteFlags writeFlags, bool sendEmptyInitialMetadata) + { + SendCompletionCallback = callback; + } + + public void StartSendCloseFromClient(ISendCompletionCallback callback) + { + SendCompletionCallback = callback; + } + + public void StartSendStatusFromServer(ISendStatusFromServerCompletionCallback callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, + SliceBufferSafeHandle payload, WriteFlags writeFlags) + { + SendStatusFromServerCallback = callback; + } + + public void StartServerSide(IReceivedCloseOnServerCallback callback) + { + ReceivedCloseOnServerCallback = callback; + } + + public void Dispose() + { + IsDisposed = true; + } + + /// + /// Emulate CallSafeHandle.CheckOk() failure for all future attempts + /// to start a call. + /// + public void MakeStartCallFail() + { + shouldStartCallFail = true; + } + + private void StartCallMaybeFail() + { + if (shouldStartCallFail) + { + throw new InvalidOperationException("Start call has failed."); + } + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs b/src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs new file mode 100644 index 00000000..11e8ae94 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs @@ -0,0 +1,69 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class MetadataArraySafeHandleTest + { + [Test] + public void CreateEmptyAndDestroy() + { + var nativeMetadata = MetadataArraySafeHandle.Create(new Metadata()); + nativeMetadata.Dispose(); + } + + [Test] + public void CreateAndDestroy() + { + var metadata = new Metadata + { + { "host", "somehost" }, + { "header2", "header value" }, + }; + var nativeMetadata = MetadataArraySafeHandle.Create(metadata); + nativeMetadata.Dispose(); + } + + [Test] + public void ReadMetadataFromPtrUnsafe() + { + var metadata = new Metadata + { + { "host", "somehost" }, + { "header2", "header value" } + }; + var nativeMetadata = MetadataArraySafeHandle.Create(metadata); + + var copy = MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(nativeMetadata.Handle); + Assert.AreEqual(2, copy.Count); + + Assert.AreEqual("host", copy[0].Key); + Assert.AreEqual("somehost", copy[0].Value); + Assert.AreEqual("header2", copy[1].Key); + Assert.AreEqual("header value", copy[1].Value); + + nativeMetadata.Dispose(); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/ReusableSliceBufferTest.cs b/src/csharp/Grpc.Core.Tests/Internal/ReusableSliceBufferTest.cs new file mode 100644 index 00000000..bfe4f645 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/ReusableSliceBufferTest.cs @@ -0,0 +1,140 @@ +#region Copyright notice and license + +// Copyright 2018 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + // Converts IBufferReader into instances of ReadOnlySequence + // Objects representing the sequence segments are cached to decrease GC load. + public class ReusableSliceBufferTest + { + FakeBufferReaderManager fakeBufferReaderManager; + + [SetUp] + public void Init() + { + fakeBufferReaderManager = new FakeBufferReaderManager(); + } + + [TearDown] + public void Cleanup() + { + fakeBufferReaderManager.Dispose(); + } + + [TestCase] + public void NullPayload() + { + var sliceBuffer = new ReusableSliceBuffer(); + Assert.Throws(typeof(ArgumentNullException), () => sliceBuffer.PopulateFrom(fakeBufferReaderManager.CreateNullPayloadBufferReader())); + } + + [TestCase] + public void ZeroSegmentPayload() + { + var sliceBuffer = new ReusableSliceBuffer(); + var sequence = sliceBuffer.PopulateFrom(fakeBufferReaderManager.CreateMultiSegmentBufferReader(new List {})); + + Assert.AreEqual(ReadOnlySequence.Empty, sequence); + Assert.IsTrue(sequence.IsEmpty); + Assert.IsTrue(sequence.IsSingleSegment); + } + + [TestCase] + public void SegmentsAreCached() + { + var bufferSegments1 = Enumerable.Range(0, 100).Select((_) => GetTestBuffer(50)).ToList(); + var bufferSegments2 = Enumerable.Range(0, 100).Select((_) => GetTestBuffer(50)).ToList(); + + var sliceBuffer = new ReusableSliceBuffer(); + + var sequence1 = sliceBuffer.PopulateFrom(fakeBufferReaderManager.CreateMultiSegmentBufferReader(bufferSegments1)); + var memoryManagers1 = GetMemoryManagersForSequenceSegments(sequence1); + + sliceBuffer.Invalidate(); + + var sequence2 = sliceBuffer.PopulateFrom(fakeBufferReaderManager.CreateMultiSegmentBufferReader(bufferSegments2)); + var memoryManagers2 = GetMemoryManagersForSequenceSegments(sequence2); + + // check memory managers are identical objects (i.e. they've been reused) + CollectionAssert.AreEquivalent(memoryManagers1, memoryManagers2); + } + + [TestCase] + public void MultiSegmentPayload_LotsOfSegments() + { + var bufferSegments = Enumerable.Range(0, ReusableSliceBuffer.MaxCachedSegments + 100).Select((_) => GetTestBuffer(10)).ToList(); + + var sliceBuffer = new ReusableSliceBuffer(); + var sequence = sliceBuffer.PopulateFrom(fakeBufferReaderManager.CreateMultiSegmentBufferReader(bufferSegments)); + + int index = 0; + foreach (var memory in sequence) + { + CollectionAssert.AreEqual(bufferSegments[index], memory.ToArray()); + index ++; + } + } + + [TestCase] + public void InvalidateMakesSequenceUnusable() + { + var origBuffer = GetTestBuffer(100); + + var sliceBuffer = new ReusableSliceBuffer(); + var sequence = sliceBuffer.PopulateFrom(fakeBufferReaderManager.CreateMultiSegmentBufferReader(new List { origBuffer })); + + Assert.AreEqual(origBuffer.Length, sequence.Length); + + sliceBuffer.Invalidate(); + + // Invalidate with make the returned sequence completely unusable and broken, users must not use it beyond the deserializer functions. + Assert.Throws(typeof(ArgumentOutOfRangeException), () => { var first = sequence.First; }); + } + + private List> GetMemoryManagersForSequenceSegments(ReadOnlySequence sequence) + { + var result = new List>(); + foreach (var memory in sequence) + { + Assert.IsTrue(MemoryMarshal.TryGetMemoryManager(memory, out MemoryManager memoryManager)); + result.Add(memoryManager); + } + return result; + } + + private byte[] GetTestBuffer(int length) + { + var testBuffer = new byte[length]; + for (int i = 0; i < testBuffer.Length; i++) + { + testBuffer[i] = (byte) i; + } + return testBuffer; + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/SliceBufferSafeHandleTest.cs b/src/csharp/Grpc.Core.Tests/Internal/SliceBufferSafeHandleTest.cs new file mode 100644 index 00000000..76387478 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/SliceBufferSafeHandleTest.cs @@ -0,0 +1,163 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class SliceBufferSafeHandleTest + { + [TestCase] + public void Complete_EmptyBuffer() + { + using (var sliceBuffer = SliceBufferSafeHandle.Create()) + { + sliceBuffer.Complete(); + CollectionAssert.AreEqual(new byte[0], sliceBuffer.ToByteArray()); + } + } + + [TestCase] + public void Complete_TailSizeZero() + { + using (var sliceBuffer = SliceBufferSafeHandle.Create()) + { + var origPayload = GetTestBuffer(10); + origPayload.AsSpan().CopyTo(sliceBuffer.GetSpan(origPayload.Length)); + sliceBuffer.Advance(origPayload.Length); + // call complete where tail space size == 0 + sliceBuffer.Complete(); + CollectionAssert.AreEqual(origPayload, sliceBuffer.ToByteArray()); + } + } + + [TestCase] + public void Complete_TruncateTailSpace() + { + using (var sliceBuffer = SliceBufferSafeHandle.Create()) + { + var origPayload = GetTestBuffer(10); + var dest = sliceBuffer.GetSpan(origPayload.Length + 10); + origPayload.AsSpan().CopyTo(dest); + sliceBuffer.Advance(origPayload.Length); + // call complete where tail space needs to be truncated + sliceBuffer.Complete(); + CollectionAssert.AreEqual(origPayload, sliceBuffer.ToByteArray()); + } + } + + [TestCase] + public void SliceBufferIsReusable() + { + using (var sliceBuffer = SliceBufferSafeHandle.Create()) + { + var origPayload = GetTestBuffer(10); + origPayload.AsSpan().CopyTo(sliceBuffer.GetSpan(origPayload.Length)); + sliceBuffer.Advance(origPayload.Length); + sliceBuffer.Complete(); + CollectionAssert.AreEqual(origPayload, sliceBuffer.ToByteArray()); + + sliceBuffer.Reset(); + + var origPayload2 = GetTestBuffer(20); + origPayload2.AsSpan().CopyTo(sliceBuffer.GetSpan(origPayload2.Length)); + sliceBuffer.Advance(origPayload2.Length); + sliceBuffer.Complete(); + CollectionAssert.AreEqual(origPayload2, sliceBuffer.ToByteArray()); + + sliceBuffer.Reset(); + + CollectionAssert.AreEqual(new byte[0], sliceBuffer.ToByteArray()); + } + } + + [TestCase] + public void SliceBuffer_SizeHintZero() + { + using (var sliceBuffer = SliceBufferSafeHandle.Create()) + { + var destSpan = sliceBuffer.GetSpan(0); + Assert.IsTrue(destSpan.Length > 0); // some non-zero size memory is made available + + sliceBuffer.Reset(); + + var destMemory = sliceBuffer.GetMemory(0); + Assert.IsTrue(destMemory.Length > 0); + } + } + + [TestCase(0)] + [TestCase(1000)] + public void SliceBuffer_BigPayload(int sizeHint) + { + using (var sliceBuffer = SliceBufferSafeHandle.Create()) + { + var bigPayload = GetTestBuffer(4 * 1024 * 1024); + + int offset = 0; + while (offset < bigPayload.Length) + { + var destSpan = sliceBuffer.GetSpan(sizeHint); + int copySize = Math.Min(destSpan.Length, bigPayload.Length - offset); + bigPayload.AsSpan(offset, copySize).CopyTo(destSpan); + sliceBuffer.Advance(copySize); + offset += copySize; + } + + sliceBuffer.Complete(); + CollectionAssert.AreEqual(bigPayload, sliceBuffer.ToByteArray()); + } + } + + [TestCase] + public void SliceBuffer_NegativeSizeHint() + { + using (var sliceBuffer = SliceBufferSafeHandle.Create()) + { + Assert.Throws(typeof(ArgumentException), () => sliceBuffer.GetSpan(-1)); + Assert.Throws(typeof(ArgumentException), () => sliceBuffer.GetMemory(-1)); + } + } + + [TestCase] + public void SliceBuffer_AdvanceBadArg() + { + using (var sliceBuffer = SliceBufferSafeHandle.Create()) + { + int size = 10; + var destSpan = sliceBuffer.GetSpan(size); + Assert.Throws(typeof(ArgumentException), () => sliceBuffer.Advance(size + 1)); + Assert.Throws(typeof(ArgumentException), () => sliceBuffer.Advance(-1)); + } + } + + private byte[] GetTestBuffer(int length) + { + var testBuffer = new byte[length]; + for (int i = 0; i < testBuffer.Length; i++) + { + testBuffer[i] = (byte) i; + } + return testBuffer; + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/SliceTest.cs b/src/csharp/Grpc.Core.Tests/Internal/SliceTest.cs new file mode 100644 index 00000000..ff4d7472 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/SliceTest.cs @@ -0,0 +1,66 @@ +#region Copyright notice and license + +// Copyright 2018 The gRPC Authors +// +// 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. + +#endregion + +using System; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +using System.Runtime.InteropServices; + +namespace Grpc.Core.Internal.Tests +{ + public class SliceTest + { + [TestCase(0)] + [TestCase(1)] + [TestCase(10)] + [TestCase(100)] + [TestCase(1000)] + public void SliceFromNativePtr_Copy(int bufferLength) + { + var origBuffer = GetTestBuffer(bufferLength); + var gcHandle = GCHandle.Alloc(origBuffer, GCHandleType.Pinned); + try + { + var slice = new Slice(gcHandle.AddrOfPinnedObject(), origBuffer.Length); + Assert.AreEqual(bufferLength, slice.Length); + + var newBuffer = new byte[bufferLength]; + slice.ToSpanUnsafe().CopyTo(newBuffer); + CollectionAssert.AreEqual(origBuffer, newBuffer); + } + finally + { + gcHandle.Free(); + } + } + + // create a buffer of given size and fill it with some data + private byte[] GetTestBuffer(int length) + { + var testBuffer = new byte[length]; + for (int i = 0; i < testBuffer.Length; i++) + { + testBuffer[i] = (byte) i; + } + return testBuffer; + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs b/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs new file mode 100644 index 00000000..be35f31c --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/TimespecTest.cs @@ -0,0 +1,176 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Runtime.InteropServices; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class TimespecTest + { + [Test] + public void Now_IsInUtc() + { + Assert.AreEqual(DateTimeKind.Utc, Timespec.Now.ToDateTime().Kind); + } + + [Test] + public void Now_AgreesWithUtcNow() + { + var timespec = Timespec.Now; + var utcNow = DateTime.UtcNow; + + TimeSpan difference = utcNow - timespec.ToDateTime(); + + // This test is inherently a race - but the two timestamps + // should really be way less that a minute apart. + Assert.IsTrue(difference.TotalSeconds < 60); + } + + [Test] + public void InfFutureMatchesNativeValue() + { + Assert.AreEqual(Timespec.NativeInfFuture, Timespec.InfFuture); + } + + [Test] + public void InfPastMatchesNativeValue() + { + Assert.AreEqual(Timespec.NativeInfPast, Timespec.InfPast); + } + + [Test] + public void TimespecSizeIsNativeSize() + { + #pragma warning disable 0618 + // We need to use the obsolete non-generic version of Marshal.SizeOf because the generic version is not available in net45 + Assert.AreEqual(Timespec.NativeSize, Marshal.SizeOf(typeof(Timespec))); + #pragma warning restore 0618 + } + + [Test] + public void ToDateTime() + { + Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc), + new Timespec(0, 0).ToDateTime()); + + Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 10, DateTimeKind.Utc).AddTicks(50), + new Timespec(10, 5000).ToDateTime()); + + Assert.AreEqual(new DateTime(2015, 7, 21, 4, 21, 48, DateTimeKind.Utc), + new Timespec(1437452508, 0).ToDateTime()); + + // before epoch + Assert.AreEqual(new DateTime(1969, 12, 31, 23, 59, 55, DateTimeKind.Utc).AddTicks(10), + new Timespec(-5, 1000).ToDateTime()); + + // infinity + Assert.AreEqual(DateTime.MaxValue, Timespec.InfFuture.ToDateTime()); + Assert.AreEqual(DateTime.MinValue, Timespec.InfPast.ToDateTime()); + + // nanos are rounded to ticks are rounded up + Assert.AreEqual(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks(1), + new Timespec(0, 99).ToDateTime()); + + // Illegal inputs + Assert.Throws(typeof(InvalidOperationException), + () => new Timespec(0, -2).ToDateTime()); + Assert.Throws(typeof(InvalidOperationException), + () => new Timespec(0, 1000 * 1000 * 1000).ToDateTime()); + Assert.Throws(typeof(InvalidOperationException), + () => new Timespec(0, 0, ClockType.Monotonic).ToDateTime()); + } + + [Test] + public void ToDateTime_ReturnsUtc() + { + Assert.AreEqual(DateTimeKind.Utc, new Timespec(1437452508, 0).ToDateTime().Kind); + Assert.AreNotEqual(DateTimeKind.Unspecified, new Timespec(1437452508, 0).ToDateTime().Kind); + } + + [Test] + public void ToDateTime_Overflow() + { + var timespec = new Timespec(long.MaxValue - 100, 0); + Assert.AreNotEqual(Timespec.InfFuture, timespec); + Assert.AreEqual(DateTime.MaxValue, timespec.ToDateTime()); + + Assert.AreEqual(DateTime.MinValue, new Timespec(long.MinValue + 100, 0).ToDateTime()); + } + + [Test] + public void ToDateTime_OutOfDateTimeRange() + { + // DateTime range goes up to year 9999, 20000 years from now should + // be out of range. + long seconds = 20000L * 365L * 24L * 3600L; + + var timespec = new Timespec(seconds, 0); + Assert.AreNotEqual(Timespec.InfFuture, timespec); + Assert.AreEqual(DateTime.MaxValue, timespec.ToDateTime()); + + Assert.AreEqual(DateTime.MinValue, new Timespec(-seconds, 0).ToDateTime()); + } + + [Test] + public void FromDateTime() + { + Assert.AreEqual(new Timespec(0, 0), + Timespec.FromDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc))); + + Assert.AreEqual(new Timespec(10, 5000), + Timespec.FromDateTime(new DateTime(1970, 1, 1, 0, 0, 10, DateTimeKind.Utc).AddTicks(50))); + + Assert.AreEqual(new Timespec(1437452508, 0), + Timespec.FromDateTime(new DateTime(2015, 7, 21, 4, 21, 48, DateTimeKind.Utc))); + + // before epoch + Assert.AreEqual(new Timespec(-5, 1000), + Timespec.FromDateTime(new DateTime(1969, 12, 31, 23, 59, 55, DateTimeKind.Utc).AddTicks(10))); + + // infinity + Assert.AreEqual(Timespec.InfFuture, Timespec.FromDateTime(DateTime.MaxValue)); + Assert.AreEqual(Timespec.InfPast, Timespec.FromDateTime(DateTime.MinValue)); + + // illegal inputs + Assert.Throws(typeof(ArgumentException), + () => Timespec.FromDateTime(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Unspecified))); + } + + [Test] + [Category("Performance")] + [Ignore("Prevent running on Jenkins")] + public void NowBenchmark() + { + // approx Timespec.Now latency <33ns + BenchmarkUtil.RunBenchmark(10000000, 1000000000, () => { var now = Timespec.Now; }); + } + + [Test] + [Category("Performance")] + [Ignore("Prevent running on Jenkins")] + public void PreciseNowBenchmark() + { + // approx Timespec.PreciseNow latency <18ns (when compiled with GRPC_TIMERS_RDTSC) + BenchmarkUtil.RunBenchmark(10000000, 1000000000, () => { var now = Timespec.PreciseNow; }); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/UserAgentStringProviderTest.cs b/src/csharp/Grpc.Core.Tests/Internal/UserAgentStringProviderTest.cs new file mode 100644 index 00000000..24e788f6 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/UserAgentStringProviderTest.cs @@ -0,0 +1,63 @@ +#region Copyright notice and license + +// Copyright 2021 The gRPC Authors +// +// 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. + +#endregion + +using System; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class UserAgentStringProviderTest + { + [Test] + public void BasicTest() + { + Assert.AreEqual("grpc-csharp/1.0 (.NET Framework 4.6.1; CLR 1.2.3.4; net45; x64)", + new UserAgentStringProvider("1.0", ".NET Framework 4.6.1", "1.2.3.4", "net45", CommonPlatformDetection.CpuArchitecture.X64).GrpcCsharpUserAgentString); + Assert.AreEqual("grpc-csharp/1.0 (CLR 1.2.3.4; net45; x64)", + new UserAgentStringProvider("1.0", null, "1.2.3.4", "net45", CommonPlatformDetection.CpuArchitecture.X64).GrpcCsharpUserAgentString); + Assert.AreEqual("grpc-csharp/1.0 (.NET Framework 4.6.1; net45; x64)", + new UserAgentStringProvider("1.0", ".NET Framework 4.6.1", null, "net45", CommonPlatformDetection.CpuArchitecture.X64).GrpcCsharpUserAgentString); + Assert.AreEqual("grpc-csharp/1.0 (.NET Framework 4.6.1; CLR 1.2.3.4; x64)", + new UserAgentStringProvider("1.0", ".NET Framework 4.6.1", "1.2.3.4", null, CommonPlatformDetection.CpuArchitecture.X64).GrpcCsharpUserAgentString); + } + + [Test] + public void ArchitectureTest() + { + Assert.AreEqual("grpc-csharp/1.0 (.NET Framework 4.6.1; CLR 1.2.3.4; net45; arm64)", + new UserAgentStringProvider("1.0", ".NET Framework 4.6.1", "1.2.3.4", "net45", CommonPlatformDetection.CpuArchitecture.Arm64).GrpcCsharpUserAgentString); + + // unknown architecture + Assert.AreEqual("grpc-csharp/1.0 (.NET Framework 4.6.1; CLR 1.2.3.4; net45)", + new UserAgentStringProvider("1.0", ".NET Framework 4.6.1", "1.2.3.4", "net45", CommonPlatformDetection.CpuArchitecture.Unknown).GrpcCsharpUserAgentString); + } + + [Test] + public void FrameworkDescriptionTest() + { + Assert.AreEqual("grpc-csharp/1.0 (Mono 6.12.0.93; x64)", + new UserAgentStringProvider("1.0", "Mono 6.12.0.93 (2020-02/620cf538206 Tue Aug 25 14:04:52 EDT 2020)", null, null, CommonPlatformDetection.CpuArchitecture.X64).GrpcCsharpUserAgentString); + + Assert.AreEqual("grpc-csharp/1.0 (x64)", + new UserAgentStringProvider("1.0", "(some invalid framework description)", null, null, CommonPlatformDetection.CpuArchitecture.X64).GrpcCsharpUserAgentString); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Internal/WellKnownStringsTest.cs b/src/csharp/Grpc.Core.Tests/Internal/WellKnownStringsTest.cs new file mode 100644 index 00000000..4c89b993 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/WellKnownStringsTest.cs @@ -0,0 +1,62 @@ +#region Copyright notice and license +// Copyright 2019 The gRPC Authors +// +// 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. +#endregion + +using System.Text; +using Grpc.Core.Internal; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class WellKnownStringsTest + { + [Test] + [TestCase("", true)] + [TestCase("u", false)] + [TestCase("us", false)] + [TestCase("use", false)] + [TestCase("user", false)] + [TestCase("user-", false)] + [TestCase("user-a", false)] + [TestCase("user-ag", false)] + [TestCase("user-age", false)] + [TestCase("user-agent", true)] + [TestCase("user-agent ", false)] + [TestCase("useragent ", false)] + [TestCase("User-Agent", false)] + [TestCase("sdlkfjlskjfdlkjs;lfdksflsdfkh skjdfh sdkfhskdhf skjfhk sdhjkjh", false)] + + // test for endianness snafus (reversed in segments) + [TestCase("ega-resutn", false)] + public unsafe void TestWellKnownStrings(string input, bool expected) + { + // create a copy of the data; no cheating! + byte[] bytes = Encoding.ASCII.GetBytes(input); + fixed(byte* ptr = bytes) + { + string result = WellKnownStrings.TryIdentify(ptr, bytes.Length); + if (expected) Assert.AreEqual(input, result); + else Assert.IsNull(result); + + if (expected) + { + // try again, and check we get the same instance + string again = WellKnownStrings.TryIdentify(ptr, bytes.Length); + Assert.AreSame(result, again); + } + } + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/MarshallerTest.cs b/src/csharp/Grpc.Core.Tests/MarshallerTest.cs new file mode 100644 index 00000000..ad3e81d6 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/MarshallerTest.cs @@ -0,0 +1,102 @@ +#region Copyright notice and license + +// Copyright 2018 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class MarshallerTest + { + [Test] + public void ContextualSerializerEmulation() + { + Func simpleSerializer = System.Text.Encoding.UTF8.GetBytes; + Func simpleDeserializer = System.Text.Encoding.UTF8.GetString; + var marshaller = new Marshaller(simpleSerializer, + simpleDeserializer); + + Assert.AreSame(simpleSerializer, marshaller.Serializer); + Assert.AreSame(simpleDeserializer, marshaller.Deserializer); + + // test that emulated contextual serializer and deserializer work + string origMsg = "abc"; + var serializationContext = new FakeSerializationContext(); + marshaller.ContextualSerializer(origMsg, serializationContext); + + var deserializationContext = new FakeDeserializationContext(serializationContext.Payload); + Assert.AreEqual(origMsg, marshaller.ContextualDeserializer(deserializationContext)); + } + + [Test] + public void SimpleSerializerEmulation() + { + Action contextualSerializer = (str, context) => + { + var bytes = System.Text.Encoding.UTF8.GetBytes(str); + context.Complete(bytes); + }; + Func contextualDeserializer = (context) => + { + return System.Text.Encoding.UTF8.GetString(context.PayloadAsNewBuffer()); + }; + var marshaller = new Marshaller(contextualSerializer, contextualDeserializer); + + Assert.AreSame(contextualSerializer, marshaller.ContextualSerializer); + Assert.AreSame(contextualDeserializer, marshaller.ContextualDeserializer); + Assert.Throws(typeof(NotImplementedException), () => marshaller.Serializer("abc")); + Assert.Throws(typeof(NotImplementedException), () => marshaller.Deserializer(new byte[] {1, 2, 3})); + } + + class FakeSerializationContext : SerializationContext + { + public byte[] Payload; + public override void Complete(byte[] payload) + { + this.Payload = payload; + } + } + + class FakeDeserializationContext : DeserializationContext + { + public byte[] payload; + + public FakeDeserializationContext(byte[] payload) + { + this.payload = payload; + } + + public override int PayloadLength => payload.Length; + + public override byte[] PayloadAsNewBuffer() + { + return payload; + } + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs b/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs new file mode 100644 index 00000000..1916cbc5 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs @@ -0,0 +1,169 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class MarshallingErrorsTest + { + const string Host = "127.0.0.1"; + + MockServiceHelper helper; + Server server; + Channel channel; + + [SetUp] + public void Init() + { + var marshaller = new Marshaller( + (str) => + { + if (str == "UNSERIALIZABLE_VALUE") + { + // Google.Protobuf throws exception inherited from IOException + throw new IOException("Error serializing the message."); + } + return System.Text.Encoding.UTF8.GetBytes(str); + }, + (payload) => + { + var s = System.Text.Encoding.UTF8.GetString(payload); + if (s == "UNPARSEABLE_VALUE") + { + // Google.Protobuf throws exception inherited from IOException + throw new IOException("Error parsing the message."); + } + return s; + }); + helper = new MockServiceHelper(Host, marshaller); + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void ResponseParsingError_UnaryResponse() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult("UNPARSEABLE_VALUE"); + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "REQUEST")); + Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); + } + + [Test] + public void ResponseParsingError_StreamingResponse() + { + helper.ServerStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => + { + await responseStream.WriteAsync("UNPARSEABLE_VALUE"); + await Task.Delay(10000); + }); + + var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), "REQUEST"); + var ex = Assert.ThrowsAsync(async () => await call.ResponseStream.MoveNext()); + Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); + } + + [Test] + public void RequestParsingError_UnaryRequest() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult("RESPONSE"); + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "UNPARSEABLE_VALUE")); + // Spec doesn't define the behavior. With the current implementation server handler throws exception which results in StatusCode.Unknown. + Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode); + } + + [Test] + public async Task RequestParsingError_StreamingRequest() + { + helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => + { + try + { + // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock. + await requestStream.MoveNext(); + Assert.Fail(); + } + catch (IOException) + { + } + return "RESPONSE"; + }); + + var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()); + await call.RequestStream.WriteAsync("UNPARSEABLE_VALUE"); + + Assert.AreEqual("RESPONSE", await call); + } + + [Test] + public void RequestSerializationError_BlockingUnary() + { + Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "UNSERIALIZABLE_VALUE")); + } + + [Test] + public void RequestSerializationError_AsyncUnary() + { + Assert.ThrowsAsync(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "UNSERIALIZABLE_VALUE")); + } + + [Test] + public async Task RequestSerializationError_ClientStreaming() + { + helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => + { + CollectionAssert.AreEqual(new[] { "A", "B" }, await requestStream.ToListAsync()); + return "RESPONSE"; + }); + var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()); + await call.RequestStream.WriteAsync("A"); + Assert.ThrowsAsync(async () => await call.RequestStream.WriteAsync("UNSERIALIZABLE_VALUE")); + await call.RequestStream.WriteAsync("B"); + await call.RequestStream.CompleteAsync(); + + Assert.AreEqual("RESPONSE", await call); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/MetadataTest.cs b/src/csharp/Grpc.Core.Tests/MetadataTest.cs new file mode 100644 index 00000000..dbbd2c4f --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/MetadataTest.cs @@ -0,0 +1,374 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class MetadataTest + { + [Test] + public void AsciiEntry() + { + var entry = new Metadata.Entry("ABC", "XYZ"); + Assert.IsFalse(entry.IsBinary); + Assert.AreEqual("abc", entry.Key); // key is in lowercase. + Assert.AreEqual("XYZ", entry.Value); + CollectionAssert.AreEqual(new[] { (byte)'X', (byte)'Y', (byte)'Z' }, entry.ValueBytes); + + Assert.Throws(typeof(ArgumentException), () => new Metadata.Entry("abc-bin", "xyz")); + + Assert.AreEqual("[Entry: key=abc, value=XYZ]", entry.ToString()); + } + + [Test] + public void BinaryEntry() + { + var bytes = new byte[] { 1, 2, 3 }; + var entry = new Metadata.Entry("ABC-BIN", bytes); + Assert.IsTrue(entry.IsBinary); + Assert.AreEqual("abc-bin", entry.Key); // key is in lowercase. + Assert.Throws(typeof(InvalidOperationException), () => { var v = entry.Value; }); + CollectionAssert.AreEqual(bytes, entry.ValueBytes); + + Assert.Throws(typeof(ArgumentException), () => new Metadata.Entry("abc", bytes)); + + Assert.AreEqual("[Entry: key=abc-bin, valueBytes=System.Byte[]]", entry.ToString()); + } + + [Test] + public void AsciiEntry_KeyValidity() + { + new Metadata.Entry("ABC", "XYZ"); + new Metadata.Entry("0123456789abc", "XYZ"); + new Metadata.Entry("-abc", "XYZ"); + new Metadata.Entry("a_bc_", "XYZ"); + new Metadata.Entry("abc.xyz", "XYZ"); + new Metadata.Entry("abc.xyz-bin", new byte[] {1, 2, 3}); + Assert.Throws(typeof(ArgumentException), () => new Metadata.Entry("abc[", "xyz")); + Assert.Throws(typeof(ArgumentException), () => new Metadata.Entry("abc/", "xyz")); + } + + [Test] + public void KeysAreNormalized_UppercaseKey() + { + var uppercaseKey = "ABC"; + var entry = new Metadata.Entry(uppercaseKey, "XYZ"); + Assert.AreEqual("abc", entry.Key); + } + + [Test] + public void KeysAreNormalized_LowercaseKey() + { + var lowercaseKey = "abc"; + var entry = new Metadata.Entry(lowercaseKey, "XYZ"); + // no allocation if key already lowercase + Assert.AreSame(lowercaseKey, entry.Key); + } + + [Test] + public void Entry_ConstructionPreconditions() + { + Assert.Throws(typeof(ArgumentNullException), () => new Metadata.Entry(null, "xyz")); + Assert.Throws(typeof(ArgumentNullException), () => new Metadata.Entry("abc", (string)null)); + Assert.Throws(typeof(ArgumentNullException), () => new Metadata.Entry("abc-bin", (byte[])null)); + } + + [Test] + public void Entry_Immutable() + { + var origBytes = new byte[] { 1, 2, 3 }; + var bytes = new byte[] { 1, 2, 3 }; + var entry = new Metadata.Entry("ABC-BIN", bytes); + bytes[0] = 255; // changing the array passed to constructor should have any effect. + CollectionAssert.AreEqual(origBytes, entry.ValueBytes); + + entry.ValueBytes[0] = 255; + CollectionAssert.AreEqual(origBytes, entry.ValueBytes); + } + + [Test] + public unsafe void Entry_CreateUnsafe_Ascii() + { + var bytes = new byte[] { (byte)'X', (byte)'y' }; + fixed (byte* ptr = bytes) + { + var entry = Metadata.Entry.CreateUnsafe("abc", new IntPtr(ptr), bytes.Length); + Assert.IsFalse(entry.IsBinary); + Assert.AreEqual("abc", entry.Key); + Assert.AreEqual("Xy", entry.Value); + CollectionAssert.AreEqual(bytes, entry.ValueBytes); + } + } + + [Test] + public unsafe void Entry_CreateUnsafe_Binary() + { + var bytes = new byte[] { 1, 2, 3 }; + fixed (byte* ptr = bytes) + { + var entry = Metadata.Entry.CreateUnsafe("abc-bin", new IntPtr(ptr), bytes.Length); + Assert.IsTrue(entry.IsBinary); + Assert.AreEqual("abc-bin", entry.Key); + Assert.Throws(typeof(InvalidOperationException), () => { var v = entry.Value; }); + CollectionAssert.AreEqual(bytes, entry.ValueBytes); + } + } + + [Test] + public void IndexOf() + { + var metadata = CreateMetadata(); + Assert.AreEqual(0, metadata.IndexOf(metadata[0])); + Assert.AreEqual(1, metadata.IndexOf(metadata[1])); + } + + [Test] + public void Insert() + { + var metadata = CreateMetadata(); + metadata.Insert(0, new Metadata.Entry("new-key", "new-value")); + Assert.AreEqual(3, metadata.Count); + Assert.AreEqual("new-key", metadata[0].Key); + Assert.AreEqual("abc", metadata[1].Key); + } + + [Test] + public void RemoveAt() + { + var metadata = CreateMetadata(); + metadata.RemoveAt(0); + Assert.AreEqual(1, metadata.Count); + Assert.AreEqual("xyz", metadata[0].Key); + } + + [Test] + public void Remove() + { + var metadata = CreateMetadata(); + metadata.Remove(metadata[0]); + Assert.AreEqual(1, metadata.Count); + Assert.AreEqual("xyz", metadata[0].Key); + } + + [Test] + public void Indexer_Set() + { + var metadata = CreateMetadata(); + var entry = new Metadata.Entry("new-key", "new-value"); + + metadata[1] = entry; + Assert.AreEqual(entry, metadata[1]); + } + + [Test] + public void Clear() + { + var metadata = CreateMetadata(); + metadata.Clear(); + Assert.AreEqual(0, metadata.Count); + } + + [Test] + public void Contains() + { + var metadata = CreateMetadata(); + Assert.IsTrue(metadata.Contains(metadata[0])); + Assert.IsFalse(metadata.Contains(new Metadata.Entry("new-key", "new-value"))); + } + + [Test] + public void CopyTo() + { + var metadata = CreateMetadata(); + var array = new Metadata.Entry[metadata.Count + 1]; + + metadata.CopyTo(array, 1); + Assert.AreEqual(default(Metadata.Entry), array[0]); + Assert.AreEqual(metadata[0], array[1]); + } + + [Test] + public void IEnumerableGetEnumerator() + { + var metadata = CreateMetadata(); + var enumerator = (metadata as System.Collections.IEnumerable).GetEnumerator(); + + int i = 0; + while (enumerator.MoveNext()) + { + Assert.AreEqual(metadata[i], enumerator.Current); + i++; + } + } + + [Test] + public void FreezeMakesReadOnly() + { + var entry = new Metadata.Entry("new-key", "new-value"); + var metadata = CreateMetadata().Freeze(); + + Assert.IsTrue(metadata.IsReadOnly); + Assert.Throws(() => metadata.Insert(0, entry)); + Assert.Throws(() => metadata.RemoveAt(0)); + Assert.Throws(() => metadata[0] = entry); + Assert.Throws(() => metadata.Add(entry)); + Assert.Throws(() => metadata.Add("new-key", "new-value")); + Assert.Throws(() => metadata.Add("new-key-bin", new byte[] { 0xaa })); + Assert.Throws(() => metadata.Clear()); + Assert.Throws(() => metadata.Remove(metadata[0])); + } + + [Test] + public void GetAll() + { + var metadata = new Metadata + { + { "abc", "abc-value1" }, + { "abc", "abc-value2" }, + { "xyz", "xyz-value1" }, + }; + + var abcEntries = metadata.GetAll("abc").ToList(); + Assert.AreEqual(2, abcEntries.Count); + Assert.AreEqual("abc-value1", abcEntries[0].Value); + Assert.AreEqual("abc-value2", abcEntries[1].Value); + + var xyzEntries = metadata.GetAll("xyz").ToList(); + Assert.AreEqual(1, xyzEntries.Count); + Assert.AreEqual("xyz-value1", xyzEntries[0].Value); + + var xyzUppercaseEntries = metadata.GetAll("XYZ").ToList(); + Assert.AreEqual(1, xyzUppercaseEntries.Count); + Assert.AreEqual("xyz-value1", xyzUppercaseEntries[0].Value); + } + + [Test] + public void Get() + { + var metadata = new Metadata + { + { "abc", "abc-value1" }, + { "abc", "abc-value2" }, + { "xyz", "xyz-value1" }, + }; + + var abcEntry = metadata.Get("abc"); + Assert.AreEqual("abc-value2", abcEntry.Value); + + var xyzEntry = metadata.Get("xyz"); + Assert.AreEqual("xyz-value1", xyzEntry.Value); + + var abcUppercaseEntry = metadata.Get("AbC"); + Assert.AreEqual("abc-value2", abcUppercaseEntry.Value); + + var notFound = metadata.Get("not-found"); + Assert.AreEqual(null, notFound); + + } + + [Test] + public void GetValue() + { + var metadata = new Metadata + { + { "abc", "abc-value1" }, + { "abc", "abc-value2" }, + { "xyz", "xyz-value1" }, + { "xyz-bin", Encoding.ASCII.GetBytes("xyz-value1") }, + }; + + var abcValue = metadata.GetValue("abc"); + Assert.AreEqual("abc-value2", abcValue); + + var xyzValue = metadata.GetValue("xyz"); + Assert.AreEqual("xyz-value1", xyzValue); + + var abcUppercaseValue = metadata.GetValue("ABC"); + Assert.AreEqual("abc-value2", abcUppercaseValue); + + var notFound = metadata.GetValue("not-found"); + Assert.AreEqual(null, notFound); + } + + [Test] + public void GetValue_BytesValue() + { + var metadata = new Metadata + { + { "xyz-bin", Encoding.ASCII.GetBytes("xyz-value1") }, + }; + + Assert.Throws(() => metadata.GetValue("xyz-bin")); + } + + [Test] + public void GetValueBytes() + { + var metadata = new Metadata + { + { "abc-bin", Encoding.ASCII.GetBytes("abc-value1") }, + { "abc-bin", Encoding.ASCII.GetBytes("abc-value2") }, + { "xyz-bin", Encoding.ASCII.GetBytes("xyz-value1") }, + }; + + var abcValue = metadata.GetValueBytes("abc-bin"); + Assert.AreEqual(Encoding.ASCII.GetBytes("abc-value2"), abcValue); + + var xyzValue = metadata.GetValueBytes("xyz-bin"); + Assert.AreEqual(Encoding.ASCII.GetBytes("xyz-value1"), xyzValue); + + var xyzUppercaseValue = metadata.GetValueBytes("XYZ-BIN"); + Assert.AreEqual(Encoding.ASCII.GetBytes("xyz-value1"), xyzUppercaseValue); + + var notFound = metadata.GetValueBytes("not-found"); + Assert.AreEqual(null, notFound); + } + + [Test] + public void GetValueBytes_StringValue() + { + var metadata = new Metadata + { + { "xyz", "xyz-value1" }, + }; + + var xyzValue = metadata.GetValueBytes("xyz"); + Assert.AreEqual(Encoding.ASCII.GetBytes("xyz-value1"), xyzValue); + } + + private Metadata CreateMetadata() + { + return new Metadata + { + { "abc", "abc-value" }, + { "xyz", "xyz-value" }, + }; + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs b/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs new file mode 100644 index 00000000..a925f865 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs @@ -0,0 +1,234 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + /// + /// Allows setting up a mock service in the client-server tests easily. + /// + public class MockServiceHelper + { + public const string ServiceName = "tests.Test"; + + readonly string host; + readonly IEnumerable channelOptions; + + readonly Method unaryMethod; + readonly Method clientStreamingMethod; + readonly Method serverStreamingMethod; + readonly Method duplexStreamingMethod; + + UnaryServerMethod unaryHandler; + ClientStreamingServerMethod clientStreamingHandler; + ServerStreamingServerMethod serverStreamingHandler; + DuplexStreamingServerMethod duplexStreamingHandler; + + Server server; + Channel channel; + + public MockServiceHelper(string host = null, Marshaller marshaller = null, IEnumerable channelOptions = null) + { + this.host = host ?? "localhost"; + this.channelOptions = channelOptions; + marshaller = marshaller ?? Marshallers.StringMarshaller; + + unaryMethod = new Method( + MethodType.Unary, + ServiceName, + "Unary", + marshaller, + marshaller); + + clientStreamingMethod = new Method( + MethodType.ClientStreaming, + ServiceName, + "ClientStreaming", + marshaller, + marshaller); + + serverStreamingMethod = new Method( + MethodType.ServerStreaming, + ServiceName, + "ServerStreaming", + marshaller, + marshaller); + + duplexStreamingMethod = new Method( + MethodType.DuplexStreaming, + ServiceName, + "DuplexStreaming", + marshaller, + marshaller); + + ServiceDefinition = ServerServiceDefinition.CreateBuilder() + .AddMethod(unaryMethod, (request, context) => unaryHandler(request, context)) + .AddMethod(clientStreamingMethod, (requestStream, context) => clientStreamingHandler(requestStream, context)) + .AddMethod(serverStreamingMethod, (request, responseStream, context) => serverStreamingHandler(request, responseStream, context)) + .AddMethod(duplexStreamingMethod, (requestStream, responseStream, context) => duplexStreamingHandler(requestStream, responseStream, context)) + .Build(); + + var defaultStatus = new Status(StatusCode.Unknown, "Default mock implementation. Please provide your own."); + + unaryHandler = new UnaryServerMethod((request, context) => + { + context.Status = defaultStatus; + return Task.FromResult(""); + }); + + clientStreamingHandler = new ClientStreamingServerMethod((requestStream, context) => + { + context.Status = defaultStatus; + return Task.FromResult(""); + }); + + serverStreamingHandler = new ServerStreamingServerMethod((request, responseStream, context) => + { + context.Status = defaultStatus; + return TaskUtils.CompletedTask; + }); + + duplexStreamingHandler = new DuplexStreamingServerMethod((requestStream, responseStream, context) => + { + context.Status = defaultStatus; + return TaskUtils.CompletedTask; + }); + } + + /// + /// Returns the default server for this service and creates one if not yet created. + /// + public Server GetServer() + { + if (server == null) + { + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { ServiceDefinition }, + Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } + }; + } + return server; + } + + /// + /// Returns the default channel for this service and creates one if not yet created. + /// + public Channel GetChannel() + { + if (channel == null) + { + channel = new Channel(Host, GetServer().Ports.Single().BoundPort, ChannelCredentials.Insecure, channelOptions); + } + return channel; + } + + public CallInvocationDetails CreateUnaryCall(CallOptions options = default(CallOptions)) + { + return new CallInvocationDetails(channel, unaryMethod, options); + } + + public CallInvocationDetails CreateClientStreamingCall(CallOptions options = default(CallOptions)) + { + return new CallInvocationDetails(channel, clientStreamingMethod, options); + } + + public CallInvocationDetails CreateServerStreamingCall(CallOptions options = default(CallOptions)) + { + return new CallInvocationDetails(channel, serverStreamingMethod, options); + } + + public CallInvocationDetails CreateDuplexStreamingCall(CallOptions options = default(CallOptions)) + { + return new CallInvocationDetails(channel, duplexStreamingMethod, options); + } + + public string Host + { + get + { + return this.host; + } + } + + public ServerServiceDefinition ServiceDefinition { get; set; } + + public UnaryServerMethod UnaryHandler + { + get + { + return this.unaryHandler; + } + + set + { + unaryHandler = value; + } + } + + public ClientStreamingServerMethod ClientStreamingHandler + { + get + { + return this.clientStreamingHandler; + } + + set + { + clientStreamingHandler = value; + } + } + + public ServerStreamingServerMethod ServerStreamingHandler + { + get + { + return this.serverStreamingHandler; + } + + set + { + serverStreamingHandler = value; + } + } + + public DuplexStreamingServerMethod DuplexStreamingHandler + { + get + { + return this.duplexStreamingHandler; + } + + set + { + duplexStreamingHandler = value; + } + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/NUnitMain.cs b/src/csharp/Grpc.Core.Tests/NUnitMain.cs new file mode 100644 index 00000000..3b206603 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/NUnitMain.cs @@ -0,0 +1,40 @@ +#region Copyright notice and license + +// Copyright 2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Reflection; +using Grpc.Core; +using Grpc.Core.Logging; +using NUnit.Common; +using NUnitLite; + +namespace Grpc.Core.Tests +{ + /// + /// Provides entry point for NUnitLite + /// + public class NUnitMain + { + public static int Main(string[] args) + { + // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. + GrpcEnvironment.SetLogger(new ConsoleLogger()); + return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs new file mode 100644 index 00000000..43f816bb --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs @@ -0,0 +1,121 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class PInvokeTest + { + static readonly NativeMethods Native = NativeMethods.Get(); + + int counter; + + /// + /// (~1.26us .NET Windows) + /// + [Test] + public void CompletionQueueCreateSyncDestroyBenchmark() + { + GrpcEnvironment.AddRef(); // completion queue requires gRPC environment being initialized. + + BenchmarkUtil.RunBenchmark( + 10, 10, + () => + { + CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.CreateSync(); + cq.Dispose(); + }); + + GrpcEnvironment.ReleaseAsync().Wait(); + } + + /// + /// Approximate results: + /// (~80ns Mono Linux) + /// (~110ns .NET Windows) + /// + [Test] + [Category("Performance")] + [Ignore("Prevent running on Jenkins")] + public void NativeCallbackBenchmark() + { + NativeCallbackTestDelegate handler = Handler; + + counter = 0; + BenchmarkUtil.RunBenchmark( + 1000000, 10000000, + () => + { + Native.grpcsharp_test_callback(handler); + }); + Assert.AreNotEqual(0, counter); + } + + /// + /// Creating a new native-to-managed callback has significant overhead + /// compared to using an existing one. We need to be aware of this. + /// (~50us on Mono Linux!!!) + /// (~1.1us on .NET Windows) + /// + [Test] + [Category("Performance")] + [Ignore("Prevent running on Jenkins")] + public void NewNativeCallbackBenchmark() + { + counter = 0; + BenchmarkUtil.RunBenchmark( + 10000, 10000, + () => + { + Native.grpcsharp_test_callback(new NativeCallbackTestDelegate(Handler)); + }); + Assert.AreNotEqual(0, counter); + } + + /// + /// Tests overhead of a simple PInvoke call. + /// (~46ns .NET Windows) + /// + [Test] + [Category("Performance")] + [Ignore("Prevent running on Jenkins")] + public void NopPInvokeBenchmark() + { + BenchmarkUtil.RunBenchmark( + 1000000, 100000000, + () => + { + Native.grpcsharp_test_nop(IntPtr.Zero); + }); + } + + private void Handler(bool success) + { + counter++; + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/PerformanceTest.cs b/src/csharp/Grpc.Core.Tests/PerformanceTest.cs new file mode 100644 index 00000000..4b1d7452 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/PerformanceTest.cs @@ -0,0 +1,84 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Profiling; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class PerformanceTest + { + const string Host = "127.0.0.1"; + + MockServiceHelper helper; + Server server; + Channel channel; + + [SetUp] + public void Init() + { + helper = new MockServiceHelper(Host); + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + [Category("Performance")] + [Ignore("Prevent running on Jenkins")] + public void UnaryCallPerformance() + { + var profiler = new BasicProfiler(); + Profilers.SetForCurrentThread(profiler); + + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult(request); + }); + + var callDetails = helper.CreateUnaryCall(); + for(int i = 0; i < 3000; i++) + { + Calls.BlockingUnaryCall(callDetails, "ABC"); + } + + profiler.Reset(); + + for(int i = 0; i < 3000; i++) + { + Calls.BlockingUnaryCall(callDetails, "ABC"); + } + profiler.Dump("latency_trace_csharp.txt"); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..af264c9b --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.Core.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.Core.Tests/ResponseHeadersTest.cs b/src/csharp/Grpc.Core.Tests/ResponseHeadersTest.cs new file mode 100644 index 00000000..e318ee44 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ResponseHeadersTest.cs @@ -0,0 +1,192 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + /// + /// Tests for response headers support. + /// + public class ResponseHeadersTest + { + MockServiceHelper helper; + Server server; + Channel channel; + + Metadata headers; + + [SetUp] + public void Init() + { + helper = new MockServiceHelper(); + + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + + headers = new Metadata { { "ascii-header", "abcdefg" } }; + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public async Task ResponseHeadersAsync_UnaryCall() + { + helper.UnaryHandler = new UnaryServerMethod(async (request, context) => + { + await context.WriteResponseHeadersAsync(headers); + return "PASS"; + }); + + var call = Calls.AsyncUnaryCall(helper.CreateUnaryCall(), ""); + var responseHeaders = await call.ResponseHeadersAsync; + + Assert.AreEqual(headers.Count, responseHeaders.Count); + Assert.AreEqual("ascii-header", responseHeaders[0].Key); + Assert.AreEqual("abcdefg", responseHeaders[0].Value); + + Assert.AreEqual("PASS", await call.ResponseAsync); + } + + [Test] + public async Task ResponseHeadersAsync_ClientStreamingCall() + { + helper.ClientStreamingHandler = new ClientStreamingServerMethod(async (requestStream, context) => + { + await context.WriteResponseHeadersAsync(headers); + return "PASS"; + }); + + var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()); + await call.RequestStream.CompleteAsync(); + var responseHeaders = await call.ResponseHeadersAsync; + + Assert.AreEqual("ascii-header", responseHeaders[0].Key); + Assert.AreEqual("PASS", await call.ResponseAsync); + } + + [Test] + public async Task ResponseHeadersAsync_ServerStreamingCall() + { + helper.ServerStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => + { + await context.WriteResponseHeadersAsync(headers); + await responseStream.WriteAsync("PASS"); + }); + + var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), ""); + var responseHeaders = await call.ResponseHeadersAsync; + + Assert.AreEqual("ascii-header", responseHeaders[0].Key); + CollectionAssert.AreEqual(new[] { "PASS" }, await call.ResponseStream.ToListAsync()); + } + + [Test] + public async Task ResponseHeadersAsync_DuplexStreamingCall() + { + helper.DuplexStreamingHandler = new DuplexStreamingServerMethod(async (requestStream, responseStream, context) => + { + await context.WriteResponseHeadersAsync(headers); + while (await requestStream.MoveNext()) + { + await responseStream.WriteAsync(requestStream.Current); + } + }); + + var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall()); + var responseHeaders = await call.ResponseHeadersAsync; + + var messages = new[] { "PASS" }; + await call.RequestStream.WriteAllAsync(messages); + + Assert.AreEqual("ascii-header", responseHeaders[0].Key); + CollectionAssert.AreEqual(messages, await call.ResponseStream.ToListAsync()); + } + + [Test] + public void WriteResponseHeaders_NullNotAllowed() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + Assert.ThrowsAsync(typeof(ArgumentNullException), async () => await context.WriteResponseHeadersAsync(null)); + return Task.FromResult("PASS"); + }); + + Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "")); + } + + [Test] + public void WriteResponseHeaders_AllowedOnlyOnce() + { + helper.UnaryHandler = new UnaryServerMethod(async (request, context) => + { + await context.WriteResponseHeadersAsync(headers); + try + { + await context.WriteResponseHeadersAsync(headers); + Assert.Fail(); + } + catch (InvalidOperationException) + { + } + return "PASS"; + }); + + Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "")); + } + + [Test] + public async Task WriteResponseHeaders_NotAllowedAfterWrite() + { + helper.ServerStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => + { + await responseStream.WriteAsync("A"); + try + { + await context.WriteResponseHeadersAsync(headers); + Assert.Fail(); + } + catch (InvalidOperationException) + { + } + await responseStream.WriteAsync("B"); + }); + + var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), ""); + var responses = await call.ResponseStream.ToListAsync(); + CollectionAssert.AreEqual(new[] { "A", "B" }, responses); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/SanityTest.cs b/src/csharp/Grpc.Core.Tests/SanityTest.cs new file mode 100644 index 00000000..f785f70f --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/SanityTest.cs @@ -0,0 +1,116 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using Newtonsoft.Json; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class SanityTest + { + // TODO: make sanity test work for CoreCLR as well +#if !NETCOREAPP1_1 && !NETCOREAPP2_1 + /// + /// Because we depend on a native library, sometimes when things go wrong, the + /// entire NUnit test process crashes. To be able to track down problems better, + /// the NUnit tests are run by run_tests.py script in a separate process per test class. + /// The list of tests to run is stored in src/csharp/tests.json. + /// This test checks that the tests.json file is up to date by discovering all the + /// existing NUnit tests in all test assemblies and comparing to contents of tests.json. + /// + [Test] + public void TestsJsonUpToDate() + { + var discoveredTests = DiscoverAllTestClasses(); + var testsFromFile + = JsonConvert.DeserializeObject>>(ReadTestsJson()); + + Assert.AreEqual(discoveredTests, testsFromFile); + } + + /// + /// Gets list of all test classes obtained by inspecting all the test assemblies. + /// + private Dictionary> DiscoverAllTestClasses() + { + var assemblies = GetTestAssemblies(); + + var testsByAssembly = new Dictionary>(); + foreach (var assembly in assemblies) + { + var testClasses = new List(); + foreach (var t in assembly.GetTypes()) + { + foreach (var m in t.GetMethods()) + { + var testAttributes = m.GetCustomAttributes(typeof(NUnit.Framework.TestAttribute), true); + var testCaseAttributes = m.GetCustomAttributes(typeof(NUnit.Framework.TestCaseAttribute), true); + if (testAttributes.Length > 0 || testCaseAttributes.Length > 0) + { + testClasses.Add(t.FullName); + break; + } + } + } + testClasses.Sort(); + testsByAssembly.Add(assembly.GetName().Name, testClasses); + } + return testsByAssembly; + } + + /// + /// Reads contents of tests.json file. + /// + private string ReadTestsJson() + { + var assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var testsJsonFile = Path.Combine(assemblyDir, "..", "..", "..", "..", "tests.json"); + return File.ReadAllText(testsJsonFile); + } + + private List GetTestAssemblies() + { + var result = new List(); + var executingAssembly = Assembly.GetExecutingAssembly(); + + result.Add(executingAssembly); + + var otherAssemblies = new[] { + "Grpc.Examples.Tests", + "Grpc.HealthCheck.Tests", + "Grpc.IntegrationTesting", + "Grpc.Reflection.Tests", + "Grpc.Tools.Tests", + }; + foreach (var assemblyName in otherAssemblies) + { + var location = executingAssembly.Location.Replace("Grpc.Core.Tests", assemblyName); + result.Add(Assembly.LoadFrom(location)); + } + return result; + } +#endif + } +} diff --git a/src/csharp/Grpc.Core.Tests/ServerBindFailedTest.cs b/src/csharp/Grpc.Core.Tests/ServerBindFailedTest.cs new file mode 100644 index 00000000..2ae1f6f7 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ServerBindFailedTest.cs @@ -0,0 +1,90 @@ +#region Copyright notice and license + +// Copyright 2020 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Threading.Tasks; +using System.IO; +using System.Linq; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class ServerBindFailedTest + { + Method UnimplementedMethod = new Method( + MethodType.Unary, + "FooService", + "SomeNonExistentMethod", + Marshallers.StringMarshaller, + Marshallers.StringMarshaller); + + // https://github.com/grpc/grpc/issues/18100 + [Test] + public async Task Issue18100() + { + var server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }); + + // this port will successfully bind + int successfullyBoundPort = server.Ports.Add(new ServerPort("localhost", ServerPort.PickUnused, ServerCredentials.Insecure)); + Assert.AreNotEqual(0, successfullyBoundPort); + + // use bad ssl server credentials so this port is guaranteed to fail to bind + Assert.AreEqual(0, server.Ports.Add(new ServerPort("localhost", ServerPort.PickUnused, MakeBadSslServerCredentials()))); + + try + { + server.Start(); + } + catch (IOException ex) + { + // eat the expected "Failed to bind port" exception. + Console.Error.WriteLine($"Ignoring expected exception when starting the server: {ex}"); + } + + // Create a channel to the port that has been bound successfully + var channel = new Channel("localhost", successfullyBoundPort, ChannelCredentials.Insecure); + + var callDeadline = DateTime.UtcNow.AddSeconds(5); // set deadline to make sure we fail quickly if the server doesn't respond + + // call a method that's not implemented on the server. + var call = Calls.AsyncUnaryCall(new CallInvocationDetails(channel, UnimplementedMethod, new CallOptions(deadline: callDeadline)), "someRequest"); + try + { + await call; + Assert.Fail("the call should have failed."); + } + catch (RpcException) + { + // We called a nonexistent method. A healthy server should immediately respond with StatusCode.Unimplemented + Assert.AreEqual(StatusCode.Unimplemented, call.GetStatus().StatusCode); + } + + await channel.ShutdownAsync(); + await server.ShutdownAsync(); + } + + private static SslServerCredentials MakeBadSslServerCredentials() + { + var serverCert = new[] { new KeyCertificatePair("this is a bad certificate chain", "this is a bad private key") }; + return new SslServerCredentials(serverCert, "this is a bad root set", forceClientAuth: false); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/ServerTest.cs b/src/csharp/Grpc.Core.Tests/ServerTest.cs new file mode 100644 index 00000000..88441479 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ServerTest.cs @@ -0,0 +1,113 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.IO; +using System.Linq; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class ServerTest + { + [Test] + public void StartAndShutdownServer() + { + Server server = new Server + { + Ports = { new ServerPort("localhost", ServerPort.PickUnused, ServerCredentials.Insecure) } + }; + server.Start(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void StartAndKillServer() + { + Server server = new Server + { + Ports = { new ServerPort("localhost", ServerPort.PickUnused, ServerCredentials.Insecure) } + }; + server.Start(); + server.KillAsync().Wait(); + } + + [Test] + public void PickUnusedPort() + { + Server server = new Server + { + Ports = { new ServerPort("localhost", ServerPort.PickUnused, ServerCredentials.Insecure) } + }; + + var boundPort = server.Ports.Single(); + Assert.AreEqual(0, boundPort.Port); + Assert.Greater(boundPort.BoundPort, 0); + + server.Start(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void StartThrowsWithUnboundPorts() + { + int twiceBoundPort = 9999; + Server server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Ports = { + new ServerPort("localhost", twiceBoundPort, ServerCredentials.Insecure), + new ServerPort("localhost", twiceBoundPort, ServerCredentials.Insecure) + } + }; + Assert.Throws(typeof(IOException), () => server.Start()); + server.ShutdownAsync().Wait(); + } + + [Test] + public void CannotModifyAfterStarted() + { + Server server = new Server + { + Ports = { new ServerPort("localhost", ServerPort.PickUnused, ServerCredentials.Insecure) } + }; + server.Start(); + Assert.Throws(typeof(InvalidOperationException), () => server.Ports.Add("localhost", 9999, ServerCredentials.Insecure)); + Assert.Throws(typeof(InvalidOperationException), () => server.Services.Add(ServerServiceDefinition.CreateBuilder().Build())); + + server.ShutdownAsync().Wait(); + } + + [Test] + public void UnstartedServerCanBeShutdown() + { + var server = new Server(); + server.ShutdownAsync().Wait(); + Assert.Throws(typeof(InvalidOperationException), () => server.Start()); + } + + [Test] + public void UnstartedServerDoesNotPreventShutdown() + { + // just create a server, don't start it, and make sure it doesn't prevent shutdown. + var server = new Server(); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/ShutdownHookClientTest.cs b/src/csharp/Grpc.Core.Tests/ShutdownHookClientTest.cs new file mode 100644 index 00000000..87be3f82 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ShutdownHookClientTest.cs @@ -0,0 +1,42 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class ShutdownHookClientTest + { + const string Host = "127.0.0.1"; + + [Test] + public void ProcessExitHookCanCleanupAbandonedChannels() + { + var channel = new Channel(Host, 1000, ChannelCredentials.Insecure); + var channel2 = new Channel(Host, 1001, ChannelCredentials.Insecure); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/ShutdownHookPendingCallTest.cs b/src/csharp/Grpc.Core.Tests/ShutdownHookPendingCallTest.cs new file mode 100644 index 00000000..26d8faf2 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ShutdownHookPendingCallTest.cs @@ -0,0 +1,54 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class ShutdownHookPendingCallTest + { + const string Host = "127.0.0.1"; + + [Test] + public void ProcessExitHookCanCleanupAbandonedCall() + { + var helper = new MockServiceHelper(Host); + var server = helper.GetServer(); + server.Start(); + var channel = helper.GetChannel(); + + var readyToShutdown = new TaskCompletionSource(); + helper.DuplexStreamingHandler = new DuplexStreamingServerMethod(async (requestStream, responseStream, context) => + { + readyToShutdown.SetResult(null); + await requestStream.ToListAsync(); + }); + + var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall()); + readyToShutdown.Task.Wait(); // make sure handler is running + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/ShutdownHookServerTest.cs b/src/csharp/Grpc.Core.Tests/ShutdownHookServerTest.cs new file mode 100644 index 00000000..a6c450be --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ShutdownHookServerTest.cs @@ -0,0 +1,43 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class ShutdownHookServerTest + { + const string Host = "127.0.0.1"; + + [Test] + public void ProcessExitHookCanCleanupAbandonedServers() + { + var helper = new MockServiceHelper(Host); + var server = helper.GetServer(); + server.Start(); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/ShutdownTest.cs b/src/csharp/Grpc.Core.Tests/ShutdownTest.cs new file mode 100644 index 00000000..8654e339 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ShutdownTest.cs @@ -0,0 +1,65 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class ShutdownTest + { + const string Host = "127.0.0.1"; + + MockServiceHelper helper; + Server server; + Channel channel; + + [SetUp] + public void Init() + { + helper = new MockServiceHelper(Host); + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + } + + [Test] + public async Task AbandonedCall_ServerKillAsync() + { + var readyToShutdown = new TaskCompletionSource(); + helper.DuplexStreamingHandler = new DuplexStreamingServerMethod(async (requestStream, responseStream, context) => + { + readyToShutdown.SetResult(null); + await requestStream.ToListAsync(); + }); + + var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall()); + await readyToShutdown.Task; // make sure handler is running + + await channel.ShutdownAsync(); // channel.ShutdownAsync() works even if there's a pending call. + await server.KillAsync(); // server.ShutdownAsync() would freeze waiting for the call to finish. + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/ThreadingModelTest.cs b/src/csharp/Grpc.Core.Tests/ThreadingModelTest.cs new file mode 100644 index 00000000..9a828f30 --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/ThreadingModelTest.cs @@ -0,0 +1,99 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using NUnit.Framework; +using System.Threading; +using System.Threading.Tasks; + +namespace Grpc.Core.Tests +{ + public class ThreadingModelTest + { + const string Host = "127.0.0.1"; + + MockServiceHelper helper; + Server server; + Channel channel; + + [SetUp] + public void Init() + { + helper = new MockServiceHelper(Host); + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void BlockingCallInServerHandlerDoesNotDeadlock() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + int recursionDepth = int.Parse(request); + if (recursionDepth <= 0) { + return Task.FromResult("SUCCESS"); + } + var response = Calls.BlockingUnaryCall(helper.CreateUnaryCall(), (recursionDepth - 1).ToString()); + return Task.FromResult(response); + }); + + int maxRecursionDepth = Environment.ProcessorCount * 2; // make sure we have more pending blocking calls than threads in GrpcThreadPool + Assert.AreEqual("SUCCESS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), maxRecursionDepth.ToString())); + } + + [Test] + public void HandlerDoesNotRunOnGrpcThread() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + if (IsRunningOnGrpcThreadPool()) { + return Task.FromResult("Server handler should not run on gRPC threadpool thread."); + } + return Task.FromResult(request); + }); + + Assert.AreEqual("ABC", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "ABC")); + } + + [Test] + public async Task ContinuationDoesNotRunOnGrpcThread() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult(request); + }); + + await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "ABC"); + Assert.IsFalse(IsRunningOnGrpcThreadPool()); + } + + private static bool IsRunningOnGrpcThreadPool() + { + var threadName = Thread.CurrentThread.Name ?? ""; + return threadName.Contains("grpc"); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/TimeoutsTest.cs b/src/csharp/Grpc.Core.Tests/TimeoutsTest.cs new file mode 100644 index 00000000..d92a2b9f --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/TimeoutsTest.cs @@ -0,0 +1,135 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + /// + /// Tests for Deadline support. + /// + public class TimeoutsTest + { + MockServiceHelper helper; + Server server; + Channel channel; + + [SetUp] + public void Init() + { + helper = new MockServiceHelper(); + + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void InfiniteDeadline() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + Assert.AreEqual(DateTime.MaxValue, context.Deadline); + return Task.FromResult("PASS"); + }); + + // no deadline specified, check server sees infinite deadline + Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc")); + + // DateTime.MaxValue deadline specified, check server sees infinite deadline + Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: DateTime.MaxValue)), "abc")); + } + + [Test] + public void DeadlineTransferredToServer() + { + var clientDeadline = DateTime.UtcNow + TimeSpan.FromDays(7); + + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + // A fairly relaxed check that the deadline set by client and deadline seen by server + // are in agreement. C core takes care of the work with transferring deadline over the wire, + // so we don't need an exact check here. + Assert.IsTrue(Math.Abs((clientDeadline - context.Deadline).TotalHours) < 1); + return Task.FromResult("PASS"); + }); + Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: clientDeadline)), "abc"); + } + + [Test] + public void DeadlineInThePast() + { + helper.UnaryHandler = new UnaryServerMethod(async (request, context) => + { + await Task.Delay(60000); + return "FAIL"; + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: DateTime.MinValue)), "abc")); + Assert.AreEqual(StatusCode.DeadlineExceeded, ex.Status.StatusCode); + } + + [Test] + public void DeadlineExceededStatusOnTimeout() + { + helper.UnaryHandler = new UnaryServerMethod(async (request, context) => + { + await Task.Delay(60000); + return "FAIL"; + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: DateTime.UtcNow.Add(TimeSpan.FromSeconds(5)))), "abc")); + Assert.AreEqual(StatusCode.DeadlineExceeded, ex.Status.StatusCode); + } + + [Test] + public async Task ServerReceivesCancellationOnTimeout() + { + var serverReceivedCancellationTcs = new TaskCompletionSource(); + + helper.UnaryHandler = new UnaryServerMethod(async (request, context) => + { + // wait until cancellation token is fired. + var tcs = new TaskCompletionSource(); + context.CancellationToken.Register(() => { tcs.SetResult(null); }); + await tcs.Task; + serverReceivedCancellationTcs.SetResult(true); + return ""; + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(new CallOptions(deadline: DateTime.UtcNow.Add(TimeSpan.FromSeconds(5)))), "abc")); + Assert.AreEqual(StatusCode.DeadlineExceeded, ex.Status.StatusCode); + Assert.IsTrue(await serverReceivedCancellationTcs.Task); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/UserAgentStringTest.cs b/src/csharp/Grpc.Core.Tests/UserAgentStringTest.cs new file mode 100644 index 00000000..baf7ca5c --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/UserAgentStringTest.cs @@ -0,0 +1,88 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Profiling; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class UserAgentStringTest + { + const string Host = "127.0.0.1"; + + MockServiceHelper helper; + Server server; + Channel channel; + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void DefaultUserAgentString() + { + helper = new MockServiceHelper(Host); + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + var userAgentString = context.RequestHeaders.GetValue("user-agent"); + var parts = userAgentString.Split(new [] {' '}, 2); + Assert.AreEqual($"grpc-csharp/{VersionInfo.CurrentVersion}", parts[0]); + Assert.That(parts[1], Does.Match(@"\(.*\) grpc-c/.*")); + return Task.FromResult("PASS"); + }); + + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + + Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "")); + } + + [Test] + public void ApplicationUserAgentString() + { + helper = new MockServiceHelper(Host, + channelOptions: new[] { new ChannelOption(ChannelOptions.PrimaryUserAgentString, "XYZ") }); + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + var userAgentString = context.RequestHeaders.GetValue("user-agent"); + var parts = userAgentString.Split(new[] { ' ' }, 3); + Assert.AreEqual("XYZ", parts[0]); + Assert.AreEqual($"grpc-csharp/{VersionInfo.CurrentVersion}", parts[1]); + return Task.FromResult("PASS"); + }); + + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + + Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "")); + } + } +} diff --git a/src/csharp/Grpc.Core.Xamarin/Internal.cs b/src/csharp/Grpc.Core.Xamarin/Internal.cs new file mode 100644 index 00000000..abd18fe2 --- /dev/null +++ b/src/csharp/Grpc.Core.Xamarin/Internal.cs @@ -0,0 +1,24 @@ +#region Copyright notice and license +// Copyright 2020 The gRPC Authors +// +// 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. +#endregion + +namespace Grpc.Core +{ + + // Generate an empty assembly + internal static class UnusedClass + { + } +} diff --git a/src/csharp/Grpc.Core/CallInvocationDetails.cs b/src/csharp/Grpc.Core/CallInvocationDetails.cs new file mode 100644 index 00000000..a4c04132 --- /dev/null +++ b/src/csharp/Grpc.Core/CallInvocationDetails.cs @@ -0,0 +1,158 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Details about a client-side call to be invoked. + /// + /// Request message type for the call. + /// Response message type for the call. + public struct CallInvocationDetails + { + readonly Channel channel; + readonly string method; + readonly string host; + readonly Marshaller requestMarshaller; + readonly Marshaller responseMarshaller; + CallOptions options; + + /// + /// Initializes a new instance of the struct. + /// + /// Channel to use for this call. + /// Method to call. + /// Call options. + public CallInvocationDetails(Channel channel, Method method, CallOptions options) : + this(channel, method, null, options) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// Channel to use for this call. + /// Method to call. + /// Host that contains the method. if null, default host will be used. + /// Call options. + public CallInvocationDetails(Channel channel, Method method, string host, CallOptions options) : + this(channel, method.FullName, host, method.RequestMarshaller, method.ResponseMarshaller, options) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// Channel to use for this call. + /// Qualified method name. + /// Host that contains the method. + /// Request marshaller. + /// Response marshaller. + /// Call options. + public CallInvocationDetails(Channel channel, string method, string host, Marshaller requestMarshaller, Marshaller responseMarshaller, CallOptions options) + { + this.channel = GrpcPreconditions.CheckNotNull(channel, "channel"); + this.method = GrpcPreconditions.CheckNotNull(method, "method"); + this.host = host; + this.requestMarshaller = GrpcPreconditions.CheckNotNull(requestMarshaller, "requestMarshaller"); + this.responseMarshaller = GrpcPreconditions.CheckNotNull(responseMarshaller, "responseMarshaller"); + this.options = options; + } + + /// + /// Get channel associated with this call. + /// + public Channel Channel + { + get + { + return this.channel; + } + } + + /// + /// Gets name of method to be called. + /// + public string Method + { + get + { + return this.method; + } + } + + /// + /// Get name of host. + /// + public string Host + { + get + { + return this.host; + } + } + + /// + /// Gets marshaller used to serialize requests. + /// + public Marshaller RequestMarshaller + { + get + { + return this.requestMarshaller; + } + } + + /// + /// Gets marshaller used to deserialized responses. + /// + public Marshaller ResponseMarshaller + { + get + { + return this.responseMarshaller; + } + } + + /// + /// Gets the call options. + /// + public CallOptions Options + { + get + { + return options; + } + } + + /// + /// Returns new instance of with + /// Options set to the value provided. Values of all other fields are preserved. + /// + public CallInvocationDetails WithOptions(CallOptions options) + { + var newDetails = this; + newDetails.options = options; + return newDetails; + } + } +} diff --git a/src/csharp/Grpc.Core/Calls.cs b/src/csharp/Grpc.Core/Calls.cs new file mode 100644 index 00000000..5700e398 --- /dev/null +++ b/src/csharp/Grpc.Core/Calls.cs @@ -0,0 +1,143 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading.Tasks; +using Grpc.Core.Internal; + +namespace Grpc.Core +{ + /// + /// Helper methods for generated clients to make RPC calls. + /// Most users will use this class only indirectly and will be + /// making calls using client object generated from protocol + /// buffer definition files. + /// + public static class Calls + { + /// + /// Invokes a simple remote call in a blocking fashion. + /// + /// The response. + /// The call definition. + /// Request message. + /// Type of request message. + /// The of response message. + public static TResponse BlockingUnaryCall(CallInvocationDetails call, TRequest req) + where TRequest : class + where TResponse : class + { + var asyncCall = new AsyncCall(call); + return asyncCall.UnaryCall(req); + } + + /// + /// Invokes a simple remote call asynchronously. + /// + /// An awaitable call object providing access to the response. + /// The call definition. + /// Request message. + /// Type of request message. + /// The of response message. + public static AsyncUnaryCall AsyncUnaryCall(CallInvocationDetails call, TRequest req) + where TRequest : class + where TResponse : class + { + var asyncCall = new AsyncCall(call); + var asyncResult = asyncCall.UnaryCallAsync(req); + return new AsyncUnaryCall(asyncResult, + Callbacks.GetHeaders, Callbacks.GetStatus, + Callbacks.GetTrailers, Callbacks.Cancel, + asyncCall); + } + + /// + /// Invokes a server streaming call asynchronously. + /// In server streaming scenario, client sends on request and server responds with a stream of responses. + /// + /// A call object providing access to the asynchronous response stream. + /// The call definition. + /// Request message. + /// Type of request message. + /// The of response messages. + public static AsyncServerStreamingCall AsyncServerStreamingCall(CallInvocationDetails call, TRequest req) + where TRequest : class + where TResponse : class + { + var asyncCall = new AsyncCall(call); + asyncCall.StartServerStreamingCall(req); + var responseStream = new ClientResponseStream(asyncCall); + return new AsyncServerStreamingCall(responseStream, + Callbacks.GetHeaders, Callbacks.GetStatus, + Callbacks.GetTrailers, Callbacks.Cancel, + asyncCall); + } + + /// + /// Invokes a client streaming call asynchronously. + /// In client streaming scenario, client sends a stream of requests and server responds with a single response. + /// + /// The call definition. + /// An awaitable call object providing access to the response. + /// Type of request messages. + /// The of response message. + public static AsyncClientStreamingCall AsyncClientStreamingCall(CallInvocationDetails call) + where TRequest : class + where TResponse : class + { + var asyncCall = new AsyncCall(call); + var resultTask = asyncCall.ClientStreamingCallAsync(); + var requestStream = new ClientRequestStream(asyncCall); + return new AsyncClientStreamingCall(requestStream, resultTask, + Callbacks.GetHeaders, Callbacks.GetStatus, + Callbacks.GetTrailers, Callbacks.Cancel, + asyncCall); + } + + /// + /// Invokes a duplex streaming call asynchronously. + /// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses. + /// The response stream is completely independent and both side can be sending messages at the same time. + /// + /// A call object providing access to the asynchronous request and response streams. + /// The call definition. + /// Type of request messages. + /// Type of responsemessages. + public static AsyncDuplexStreamingCall AsyncDuplexStreamingCall(CallInvocationDetails call) + where TRequest : class + where TResponse : class + { + var asyncCall = new AsyncCall(call); + asyncCall.StartDuplexStreamingCall(); + var requestStream = new ClientRequestStream(asyncCall); + var responseStream = new ClientResponseStream(asyncCall); + return new AsyncDuplexStreamingCall(requestStream, responseStream, + Callbacks.GetHeaders, Callbacks.GetStatus, + Callbacks.GetTrailers, Callbacks.Cancel, + asyncCall); + } + + private static class Callbacks + { + internal static readonly Func> GetHeaders = state => ((AsyncCall)state).ResponseHeadersAsync; + internal static readonly Func GetStatus = state => ((AsyncCall)state).GetStatus(); + internal static readonly Func GetTrailers = state => ((AsyncCall)state).GetTrailers(); + internal static readonly Action Cancel = state => ((AsyncCall)state).Cancel(); + } + } +} diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs new file mode 100644 index 00000000..e2d69e40 --- /dev/null +++ b/src/csharp/Grpc.Core/Channel.cs @@ -0,0 +1,340 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +using Grpc.Core.Internal; +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Represents a gRPC channel. Channels are an abstraction of long-lived connections to remote servers. + /// More client objects can reuse the same channel. Creating a channel is an expensive operation compared to invoking + /// a remote call so in general you should reuse a single channel for as many calls as possible. + /// + public class Channel : ChannelBase + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + + readonly object myLock = new object(); + readonly AtomicCounter activeCallCounter = new AtomicCounter(); + readonly CancellationTokenSource shutdownTokenSource = new CancellationTokenSource(); + + readonly GrpcEnvironment environment; + readonly CompletionQueueSafeHandle completionQueue; + readonly ChannelSafeHandle handle; + readonly Dictionary options; + + bool shutdownRequested; + + /// + /// Creates a channel that connects to a specific host. + /// Port will default to 80 for an unsecure channel and to 443 for a secure channel. + /// + /// Target of the channel. + /// Credentials to secure the channel. + public Channel(string target, ChannelCredentials credentials) : + this(target, credentials, null) + { + } + + /// + /// Creates a channel that connects to a specific host. + /// Port will default to 80 for an unsecure channel or to 443 for a secure channel. + /// + /// Target of the channel. + /// Credentials to secure the channel. + /// Channel options. + public Channel(string target, ChannelCredentials credentials, IEnumerable options) : base(target) + { + this.options = CreateOptionsDictionary(options); + EnsureUserAgentChannelOption(this.options); + this.environment = GrpcEnvironment.AddRef(); + + this.completionQueue = this.environment.PickCompletionQueue(); + using (var nativeChannelArgs = ChannelOptions.CreateChannelArgs(this.options.Values)) + { + var nativeCredentials = credentials.ToNativeCredentials(); + if (nativeCredentials != null) + { + this.handle = ChannelSafeHandle.CreateSecure(nativeCredentials, target, nativeChannelArgs); + } + else + { + this.handle = ChannelSafeHandle.CreateInsecure(target, nativeChannelArgs); + } + } + GrpcEnvironment.RegisterChannel(this); + } + + /// + /// Creates a channel that connects to a specific host and port. + /// + /// The name or IP address of the host. + /// The port. + /// Credentials to secure the channel. + public Channel(string host, int port, ChannelCredentials credentials) : + this(host, port, credentials, null) + { + } + + /// + /// Creates a channel that connects to a specific host and port. + /// + /// The name or IP address of the host. + /// The port. + /// Credentials to secure the channel. + /// Channel options. + public Channel(string host, int port, ChannelCredentials credentials, IEnumerable options) : + this(string.Format("{0}:{1}", host, port), credentials, options) + { + } + + /// + /// Gets current connectivity state of this channel. + /// After channel has been shutdown, ChannelState.Shutdown will be returned. + /// + public ChannelState State + { + get + { + return GetConnectivityState(false); + } + } + + // cached handler for watch connectivity state + static readonly BatchCompletionDelegate WatchConnectivityStateHandler = (success, ctx, state) => + { + var tcs = (TaskCompletionSource) state; + tcs.SetResult(success); + }; + + /// + /// Returned tasks completes once channel state has become different from + /// given lastObservedState. + /// If deadline is reached or an error occurs, returned task is cancelled. + /// + public async Task WaitForStateChangedAsync(ChannelState lastObservedState, DateTime? deadline = null) + { + var result = await TryWaitForStateChangedAsync(lastObservedState, deadline).ConfigureAwait(false); + if (!result) + { + throw new TaskCanceledException("Reached deadline."); + } + } + + /// + /// Returned tasks completes once channel state has become different from + /// given lastObservedState (true is returned) or if the wait has timed out (false is returned). + /// + public Task TryWaitForStateChangedAsync(ChannelState lastObservedState, DateTime? deadline = null) + { + GrpcPreconditions.CheckArgument(lastObservedState != ChannelState.Shutdown, + "Shutdown is a terminal state. No further state changes can occur."); + var tcs = new TaskCompletionSource(); + var deadlineTimespec = deadline.HasValue ? Timespec.FromDateTime(deadline.Value) : Timespec.InfFuture; + lock (myLock) + { + if (handle.IsClosed) + { + // If channel has been already shutdown and handle was disposed, we would end up with + // an abandoned completion added to the completion registry. Instead, we make sure we fail early. + throw new ObjectDisposedException(nameof(handle), "Channel handle has already been disposed."); + } + else + { + // pass "tcs" as "state" for WatchConnectivityStateHandler. + handle.WatchConnectivityState(lastObservedState, deadlineTimespec, completionQueue, WatchConnectivityStateHandler, tcs); + } + } + return tcs.Task; + } + + /// Resolved address of the remote endpoint in URI format. + public string ResolvedTarget + { + get + { + return handle.GetTarget(); + } + } + + /// + /// Returns a token that gets cancelled once ShutdownAsync is invoked. + /// + public CancellationToken ShutdownToken + { + get + { + return this.shutdownTokenSource.Token; + } + } + + /// + /// Allows explicitly requesting channel to connect without starting an RPC. + /// Returned task completes once state Ready was seen. If the deadline is reached, + /// or channel enters the Shutdown state, the task is cancelled. + /// There is no need to call this explicitly unless your use case requires that. + /// Starting an RPC on a new channel will request connection implicitly. + /// + /// The deadline. null indicates no deadline. + public async Task ConnectAsync(DateTime? deadline = null) + { + var currentState = GetConnectivityState(true); + while (currentState != ChannelState.Ready) + { + if (currentState == ChannelState.Shutdown) + { + throw new OperationCanceledException("Channel has reached Shutdown state."); + } + await WaitForStateChangedAsync(currentState, deadline).ConfigureAwait(false); + currentState = GetConnectivityState(false); + } + } + + /// Provides implementation of a non-virtual public member. + protected override async Task ShutdownAsyncCore() + { + lock (myLock) + { + GrpcPreconditions.CheckState(!shutdownRequested); + shutdownRequested = true; + } + GrpcEnvironment.UnregisterChannel(this); + + shutdownTokenSource.Cancel(); + + var activeCallCount = activeCallCounter.Count; + if (activeCallCount > 0) + { + Logger.Warning("Channel shutdown was called but there are still {0} active calls for that channel.", activeCallCount); + } + + lock (myLock) + { + handle.Dispose(); + } + + await GrpcEnvironment.ReleaseAsync().ConfigureAwait(false); + } + + /// + /// Create a new for the channel. + /// + /// A new . + public override CallInvoker CreateCallInvoker() + { + return new DefaultCallInvoker(this); + } + + internal ChannelSafeHandle Handle + { + get + { + return this.handle; + } + } + + internal GrpcEnvironment Environment + { + get + { + return this.environment; + } + } + + internal CompletionQueueSafeHandle CompletionQueue + { + get + { + return this.completionQueue; + } + } + + internal void AddCallReference(object call) + { + activeCallCounter.Increment(); + + bool success = false; + handle.DangerousAddRef(ref success); + GrpcPreconditions.CheckState(success); + } + + internal void RemoveCallReference(object call) + { + handle.DangerousRelease(); + + activeCallCounter.Decrement(); + } + + // for testing only + internal long GetCallReferenceCount() + { + return activeCallCounter.Count; + } + + private ChannelState GetConnectivityState(bool tryToConnect) + { + try + { + lock (myLock) + { + return handle.CheckConnectivityState(tryToConnect); + } + } + catch (ObjectDisposedException) + { + return ChannelState.Shutdown; + } + } + + private static void EnsureUserAgentChannelOption(Dictionary options) + { + var key = ChannelOptions.PrimaryUserAgentString; + var userAgentString = ""; + + ChannelOption option; + if (options.TryGetValue(key, out option)) + { + // user-provided userAgentString needs to be at the beginning + userAgentString = option.StringValue + " "; + }; + + userAgentString += UserAgentStringProvider.DefaultInstance.GrpcCsharpUserAgentString; + + options[ChannelOptions.PrimaryUserAgentString] = new ChannelOption(key, userAgentString); + } + + private static Dictionary CreateOptionsDictionary(IEnumerable options) + { + var dict = new Dictionary(); + if (options == null) + { + return dict; + } + foreach (var option in options) + { + dict.Add(option.Name, option); + } + return dict; + } + } +} diff --git a/src/csharp/Grpc.Core/ChannelOptions.cs b/src/csharp/Grpc.Core/ChannelOptions.cs new file mode 100644 index 00000000..880f2bef --- /dev/null +++ b/src/csharp/Grpc.Core/ChannelOptions.cs @@ -0,0 +1,258 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Channel option specified when creating a channel. + /// Corresponds to grpc_channel_args from grpc/grpc.h. + /// Commonly used channel option names are defined in ChannelOptions, + /// but any of the GRPC_ARG_* channel options names defined in grpc_types.h can be used. + /// + public sealed class ChannelOption : IEquatable + { + /// + /// Type of ChannelOption. + /// + public enum OptionType + { + /// + /// Channel option with integer value. + /// + Integer, + + /// + /// Channel option with string value. + /// + String + } + + private readonly OptionType type; + private readonly string name; + private readonly int intValue; + private readonly string stringValue; + + /// + /// Creates a channel option with a string value. + /// + /// Name. + /// String value. + public ChannelOption(string name, string stringValue) + { + this.type = OptionType.String; + this.name = GrpcPreconditions.CheckNotNull(name, "name"); + this.stringValue = GrpcPreconditions.CheckNotNull(stringValue, "stringValue"); + } + + /// + /// Creates a channel option with an integer value. + /// + /// Name. + /// Integer value. + public ChannelOption(string name, int intValue) + { + this.type = OptionType.Integer; + this.name = GrpcPreconditions.CheckNotNull(name, "name"); + this.intValue = intValue; + } + + /// + /// Gets the type of the ChannelOption. + /// + public OptionType Type + { + get + { + return type; + } + } + + /// + /// Gets the name of the ChannelOption. + /// + public string Name + { + get + { + return name; + } + } + + /// + /// Gets the integer value the ChannelOption. + /// + public int IntValue + { + get + { + GrpcPreconditions.CheckState(type == OptionType.Integer); + return intValue; + } + } + + /// + /// Gets the string value the ChannelOption. + /// + public string StringValue + { + get + { + GrpcPreconditions.CheckState(type == OptionType.String); + return stringValue; + } + } + + /// + /// Determines whether the specified object is equal to the current object. + /// + public override bool Equals(object obj) + { + return Equals(obj as ChannelOption); + } + + /// + /// Determines whether the specified object is equal to the current object. + /// + public bool Equals(ChannelOption other) + { + return other != null && + type == other.type && + name == other.name && + intValue == other.intValue && + stringValue == other.stringValue; + } + + /// + /// A hash code for the current object. + /// + public override int GetHashCode() + { + var hashCode = 1412678443; + hashCode = hashCode * -1521134295 + type.GetHashCode(); + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(name); + hashCode = hashCode * -1521134295 + intValue.GetHashCode(); + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(stringValue); + return hashCode; + } + + /// + /// Equality operator. + /// + public static bool operator ==(ChannelOption option1, ChannelOption option2) + { + return EqualityComparer.Default.Equals(option1, option2); + } + + /// + /// Inequality operator. + /// + public static bool operator !=(ChannelOption option1, ChannelOption option2) + { + return !(option1 == option2); + } + } + + /// + /// Defines names of most commonly used channel options. + /// Other supported options names can be found in grpc_types.h (GRPC_ARG_* definitions) + /// + public static class ChannelOptions + { + /// Override SSL target check. Only to be used for testing. + public const string SslTargetNameOverride = "grpc.ssl_target_name_override"; + + /// Enable census for tracing and stats collection + public const string Census = "grpc.census"; + + /// Maximum number of concurrent incoming streams to allow on a http2 connection + public const string MaxConcurrentStreams = "grpc.max_concurrent_streams"; + + /// Maximum message length that the channel can receive + public const string MaxReceiveMessageLength = "grpc.max_receive_message_length"; + + /// Maximum message length that the channel can send + public const string MaxSendMessageLength = "grpc.max_send_message_length"; + + /// Obsolete, for backward compatibility only. + [Obsolete("Use MaxReceiveMessageLength instead.")] + public const string MaxMessageLength = MaxReceiveMessageLength; + + /// Initial sequence number for http2 transports + public const string Http2InitialSequenceNumber = "grpc.http2.initial_sequence_number"; + + /// Default authority for calls. + public const string DefaultAuthority = "grpc.default_authority"; + + /// Primary user agent: goes at the start of the user-agent metadata + public const string PrimaryUserAgentString = "grpc.primary_user_agent"; + + /// Secondary user agent: goes at the end of the user-agent metadata + public const string SecondaryUserAgentString = "grpc.secondary_user_agent"; + + /// If non-zero, allow the use of SO_REUSEPORT for server if it's available (default 1) + public const string SoReuseport = "grpc.so_reuseport"; + + /// + /// Creates native object for a collection of channel options. + /// + /// The native channel arguments. + internal static ChannelArgsSafeHandle CreateChannelArgs(ICollection options) + { + if (options == null || options.Count == 0) + { + return ChannelArgsSafeHandle.CreateNull(); + } + ChannelArgsSafeHandle nativeArgs = null; + try + { + nativeArgs = ChannelArgsSafeHandle.Create(options.Count); + int i = 0; + foreach (var option in options) + { + if (option.Type == ChannelOption.OptionType.Integer) + { + nativeArgs.SetInteger(i, option.Name, option.IntValue); + } + else if (option.Type == ChannelOption.OptionType.String) + { + nativeArgs.SetString(i, option.Name, option.StringValue); + } + else + { + throw new InvalidOperationException("Unknown option type"); + } + i++; + } + return nativeArgs; + } + catch (Exception) + { + if (nativeArgs != null) + { + nativeArgs.Dispose(); + } + throw; + } + } + } +} diff --git a/src/csharp/Grpc.Core/ChannelState.cs b/src/csharp/Grpc.Core/ChannelState.cs new file mode 100644 index 00000000..14c21392 --- /dev/null +++ b/src/csharp/Grpc.Core/ChannelState.cs @@ -0,0 +1,54 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; + +namespace Grpc.Core +{ + /// + /// Connectivity state of a channel. + /// Based on grpc_connectivity_state from grpc/grpc.h + /// + public enum ChannelState + { + /// + /// Channel is idle + /// + Idle, + + /// + /// Channel is connecting + /// + Connecting, + + /// + /// Channel is ready for work + /// + Ready, + + /// + /// Channel has seen a failure but expects to recover + /// + TransientFailure, + + /// + /// Channel has seen a failure that it cannot recover from + /// + Shutdown + } +} diff --git a/src/csharp/Grpc.Core/CompressionLevel.cs b/src/csharp/Grpc.Core/CompressionLevel.cs new file mode 100644 index 00000000..1e8aaa74 --- /dev/null +++ b/src/csharp/Grpc.Core/CompressionLevel.cs @@ -0,0 +1,48 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; + +namespace Grpc.Core +{ + /// + /// Compression level based on grpc_compression_level from grpc/compression.h + /// + public enum CompressionLevel + { + /// + /// No compression. + /// + None = 0, + + /// + /// Low compression. + /// + Low, + + /// + /// Medium compression. + /// + Medium, + + /// + /// High compression. + /// + High, + } +} diff --git a/src/csharp/Grpc.Core/DefaultCallInvoker.cs b/src/csharp/Grpc.Core/DefaultCallInvoker.cs new file mode 100644 index 00000000..796a7c17 --- /dev/null +++ b/src/csharp/Grpc.Core/DefaultCallInvoker.cs @@ -0,0 +1,98 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System.Threading.Tasks; +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Invokes client RPCs using . + /// + public class DefaultCallInvoker : CallInvoker + { + readonly Channel channel; + + /// + /// Initializes a new instance of the class. + /// + /// Channel to use. + public DefaultCallInvoker(Channel channel) + { + this.channel = GrpcPreconditions.CheckNotNull(channel); + } + + /// + /// Invokes a simple remote call in a blocking fashion. + /// + public override TResponse BlockingUnaryCall(Method method, string host, CallOptions options, TRequest request) + { + var call = CreateCall(method, host, options); + return Calls.BlockingUnaryCall(call, request); + } + + /// + /// Invokes a simple remote call asynchronously. + /// + public override AsyncUnaryCall AsyncUnaryCall(Method method, string host, CallOptions options, TRequest request) + { + var call = CreateCall(method, host, options); + return Calls.AsyncUnaryCall(call, request); + } + + /// + /// Invokes a server streaming call asynchronously. + /// In server streaming scenario, client sends on request and server responds with a stream of responses. + /// + public override AsyncServerStreamingCall AsyncServerStreamingCall(Method method, string host, CallOptions options, TRequest request) + { + var call = CreateCall(method, host, options); + return Calls.AsyncServerStreamingCall(call, request); + } + + /// + /// Invokes a client streaming call asynchronously. + /// In client streaming scenario, client sends a stream of requests and server responds with a single response. + /// + public override AsyncClientStreamingCall AsyncClientStreamingCall(Method method, string host, CallOptions options) + { + var call = CreateCall(method, host, options); + return Calls.AsyncClientStreamingCall(call); + } + + /// + /// Invokes a duplex streaming call asynchronously. + /// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses. + /// The response stream is completely independent and both side can be sending messages at the same time. + /// + public override AsyncDuplexStreamingCall AsyncDuplexStreamingCall(Method method, string host, CallOptions options) + { + var call = CreateCall(method, host, options); + return Calls.AsyncDuplexStreamingCall(call); + } + + /// Creates call invocation details for given method. + protected virtual CallInvocationDetails CreateCall(Method method, string host, CallOptions options) + where TRequest : class + where TResponse : class + { + return new CallInvocationDetails(channel, method, host, options); + } + } +} diff --git a/src/csharp/Grpc.Core/ForwardedTypes.cs b/src/csharp/Grpc.Core/ForwardedTypes.cs new file mode 100644 index 00000000..eaf974c3 --- /dev/null +++ b/src/csharp/Grpc.Core/ForwardedTypes.cs @@ -0,0 +1,78 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System.Runtime.CompilerServices; +using Grpc.Core; +using Grpc.Core.Interceptors; +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +// API types that used to be in Grpc.Core package, but were moved to Grpc.Core.Api +// https://docs.microsoft.com/en-us/dotnet/framework/app-domains/type-forwarding-in-the-common-language-runtime + +[assembly:TypeForwardedToAttribute(typeof(GrpcPreconditions))] +[assembly:TypeForwardedToAttribute(typeof(AsyncClientStreamingCall<,>))] +[assembly:TypeForwardedToAttribute(typeof(AsyncDuplexStreamingCall<,>))] +[assembly:TypeForwardedToAttribute(typeof(AsyncServerStreamingCall<>))] +[assembly:TypeForwardedToAttribute(typeof(AsyncUnaryCall<>))] +[assembly:TypeForwardedToAttribute(typeof(AuthContext))] +[assembly:TypeForwardedToAttribute(typeof(AsyncAuthInterceptor))] +[assembly:TypeForwardedToAttribute(typeof(AuthInterceptorContext))] +[assembly:TypeForwardedToAttribute(typeof(CallCredentials))] +[assembly:TypeForwardedToAttribute(typeof(CallFlags))] +[assembly:TypeForwardedToAttribute(typeof(CallInvoker))] +[assembly:TypeForwardedToAttribute(typeof(CallInvokerExtensions))] +[assembly:TypeForwardedToAttribute(typeof(CallOptions))] +[assembly:TypeForwardedToAttribute(typeof(ChannelExtensions))] +[assembly:TypeForwardedToAttribute(typeof(ClientBase))] +[assembly:TypeForwardedToAttribute(typeof(ClientBase<>))] +[assembly:TypeForwardedToAttribute(typeof(ChannelCredentials))] +[assembly:TypeForwardedToAttribute(typeof(ClientInterceptorContext<,>))] +[assembly:TypeForwardedToAttribute(typeof(ContextPropagationOptions))] +[assembly:TypeForwardedToAttribute(typeof(ContextPropagationToken))] +[assembly:TypeForwardedToAttribute(typeof(DeserializationContext))] +[assembly:TypeForwardedToAttribute(typeof(IAsyncStreamReader<>))] +[assembly:TypeForwardedToAttribute(typeof(IAsyncStreamWriter<>))] +[assembly:TypeForwardedToAttribute(typeof(IClientStreamWriter<>))] +[assembly:TypeForwardedToAttribute(typeof(Interceptor))] +[assembly:TypeForwardedToAttribute(typeof(InterceptingCallInvoker))] +[assembly:TypeForwardedToAttribute(typeof(IServerStreamWriter<>))] +[assembly:TypeForwardedToAttribute(typeof(KeyCertificatePair))] +[assembly:TypeForwardedToAttribute(typeof(Marshaller<>))] +[assembly:TypeForwardedToAttribute(typeof(Marshallers))] +[assembly:TypeForwardedToAttribute(typeof(Metadata))] +[assembly:TypeForwardedToAttribute(typeof(MethodType))] +[assembly:TypeForwardedToAttribute(typeof(IMethod))] +[assembly:TypeForwardedToAttribute(typeof(Method<,>))] +[assembly:TypeForwardedToAttribute(typeof(RpcException))] +[assembly:TypeForwardedToAttribute(typeof(SerializationContext))] +[assembly:TypeForwardedToAttribute(typeof(ServerCallContext))] +[assembly:TypeForwardedToAttribute(typeof(UnaryServerMethod<,>))] +[assembly:TypeForwardedToAttribute(typeof(ClientStreamingServerMethod<,>))] +[assembly:TypeForwardedToAttribute(typeof(ServerStreamingServerMethod<,>))] +[assembly:TypeForwardedToAttribute(typeof(DuplexStreamingServerMethod<,>))] +[assembly:TypeForwardedToAttribute(typeof(ServerServiceDefinition))] +[assembly:TypeForwardedToAttribute(typeof(ServiceBinderBase))] +[assembly:TypeForwardedToAttribute(typeof(SslCredentials))] +[assembly:TypeForwardedToAttribute(typeof(Status))] +[assembly:TypeForwardedToAttribute(typeof(StatusCode))] +[assembly:TypeForwardedToAttribute(typeof(VerifyPeerCallback))] +[assembly:TypeForwardedToAttribute(typeof(VerifyPeerContext))] +[assembly:TypeForwardedToAttribute(typeof(VersionInfo))] +[assembly:TypeForwardedToAttribute(typeof(WriteOptions))] +[assembly:TypeForwardedToAttribute(typeof(WriteFlags))] diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs new file mode 100644 index 00000000..45e44e6f --- /dev/null +++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs @@ -0,0 +1,490 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Grpc.Core.Internal; +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Encapsulates initialization and shutdown of gRPC library. + /// + public class GrpcEnvironment + { + const int MinDefaultThreadPoolSize = 4; + const int DefaultBatchContextPoolSharedCapacity = 10000; + const int DefaultBatchContextPoolThreadLocalCapacity = 64; + const int DefaultRequestCallContextPoolSharedCapacity = 10000; + const int DefaultRequestCallContextPoolThreadLocalCapacity = 64; + + static object staticLock = new object(); + static GrpcEnvironment instance; + static int refCount; + static int? customThreadPoolSize; + static int? customCompletionQueueCount; + static bool inlineHandlers; + static int batchContextPoolSharedCapacity = DefaultBatchContextPoolSharedCapacity; + static int batchContextPoolThreadLocalCapacity = DefaultBatchContextPoolThreadLocalCapacity; + static int requestCallContextPoolSharedCapacity = DefaultRequestCallContextPoolSharedCapacity; + static int requestCallContextPoolThreadLocalCapacity = DefaultRequestCallContextPoolThreadLocalCapacity; + static readonly HashSet registeredChannels = new HashSet(); + static readonly HashSet registeredServers = new HashSet(); + static readonly AtomicCounter nativeInitCounter = new AtomicCounter(); + + static ILogger logger = new LogLevelFilterLogger(new ConsoleLogger(), LogLevel.Off, true); + + readonly IObjectPool batchContextPool; + readonly IObjectPool requestCallContextPool; + readonly GrpcThreadPool threadPool; + readonly DebugStats debugStats = new DebugStats(); + readonly AtomicCounter cqPickerCounter = new AtomicCounter(); + + bool isShutdown; + + /// + /// Returns a reference-counted instance of initialized gRPC environment. + /// Subsequent invocations return the same instance unless reference count has dropped to zero previously. + /// + internal static GrpcEnvironment AddRef() + { + ShutdownHooks.Register(); + + lock (staticLock) + { + refCount++; + if (instance == null) + { + instance = new GrpcEnvironment(); + } + return instance; + } + } + + /// + /// Decrements the reference count for currently active environment and asynchronously shuts down the gRPC environment if reference count drops to zero. + /// + internal static async Task ReleaseAsync() + { + GrpcEnvironment instanceToShutdown = null; + lock (staticLock) + { + GrpcPreconditions.CheckState(refCount > 0); + refCount--; + if (refCount == 0) + { + instanceToShutdown = instance; + instance = null; + } + } + + if (instanceToShutdown != null) + { + await instanceToShutdown.ShutdownAsync().ConfigureAwait(false); + } + } + + internal static int GetRefCount() + { + lock (staticLock) + { + return refCount; + } + } + + internal static void RegisterChannel(Channel channel) + { + lock (staticLock) + { + GrpcPreconditions.CheckNotNull(channel); + registeredChannels.Add(channel); + } + } + + internal static void UnregisterChannel(Channel channel) + { + lock (staticLock) + { + GrpcPreconditions.CheckNotNull(channel); + GrpcPreconditions.CheckArgument(registeredChannels.Remove(channel), "Channel not found in the registered channels set."); + } + } + + internal static void RegisterServer(Server server) + { + lock (staticLock) + { + GrpcPreconditions.CheckNotNull(server); + registeredServers.Add(server); + } + } + + internal static void UnregisterServer(Server server) + { + lock (staticLock) + { + GrpcPreconditions.CheckNotNull(server); + GrpcPreconditions.CheckArgument(registeredServers.Remove(server), "Server not found in the registered servers set."); + } + } + + /// + /// Requests shutdown of all channels created by the current process. + /// + public static Task ShutdownChannelsAsync() + { + HashSet snapshot = null; + lock (staticLock) + { + snapshot = new HashSet(registeredChannels); + } + return Task.WhenAll(snapshot.Select((channel) => channel.ShutdownAsync())); + } + + /// + /// Requests immediate shutdown of all servers created by the current process. + /// + public static Task KillServersAsync() + { + HashSet snapshot = null; + lock (staticLock) + { + snapshot = new HashSet(registeredServers); + } + return Task.WhenAll(snapshot.Select((server) => server.KillAsync())); + } + + /// + /// Gets application-wide logger used by gRPC. + /// + /// The logger. + public static ILogger Logger + { + get + { + return logger; + } + } + + /// + /// Sets the application-wide logger that should be used by gRPC. + /// + public static void SetLogger(ILogger customLogger) + { + GrpcPreconditions.CheckNotNull(customLogger, "customLogger"); + logger = customLogger; + } + + /// + /// Sets the number of threads in the gRPC thread pool that polls for internal RPC events. + /// Can be only invoked before the GrpcEnviroment is started and cannot be changed afterwards. + /// Setting thread pool size is an advanced setting and you should only use it if you know what you are doing. + /// Most users should rely on the default value provided by gRPC library. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// + public static void SetThreadPoolSize(int threadCount) + { + lock (staticLock) + { + GrpcPreconditions.CheckState(instance == null, "Can only be set before GrpcEnvironment is initialized"); + GrpcPreconditions.CheckArgument(threadCount > 0, "threadCount needs to be a positive number"); + customThreadPoolSize = threadCount; + } + } + + /// + /// Sets the number of completion queues in the gRPC thread pool that polls for internal RPC events. + /// Can be only invoked before the GrpcEnviroment is started and cannot be changed afterwards. + /// Setting the number of completions queues is an advanced setting and you should only use it if you know what you are doing. + /// Most users should rely on the default value provided by gRPC library. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// + public static void SetCompletionQueueCount(int completionQueueCount) + { + lock (staticLock) + { + GrpcPreconditions.CheckState(instance == null, "Can only be set before GrpcEnvironment is initialized"); + GrpcPreconditions.CheckArgument(completionQueueCount > 0, "threadCount needs to be a positive number"); + customCompletionQueueCount = completionQueueCount; + } + } + + /// + /// By default, gRPC's internal event handlers get offloaded to .NET default thread pool thread (inlineHandlers=false). + /// Setting inlineHandlers to true will allow scheduling the event handlers directly to + /// GrpcThreadPool internal threads. That can lead to significant performance gains in some situations, + /// but requires user to never block in async code (incorrectly written code can easily lead to deadlocks). + /// Inlining handlers is an advanced setting and you should only use it if you know what you are doing. + /// Most users should rely on the default value provided by gRPC library. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Note: inlineHandlers=true was the default in gRPC C# v1.4.x and earlier. + /// + public static void SetHandlerInlining(bool inlineHandlers) + { + lock (staticLock) + { + GrpcPreconditions.CheckState(instance == null, "Can only be set before GrpcEnvironment is initialized"); + GrpcEnvironment.inlineHandlers = inlineHandlers; + } + } + + /// + /// Sets the parameters for a pool that caches batch context instances. Reusing batch context instances + /// instead of creating a new one for every C core operation helps reducing the GC pressure. + /// Can be only invoked before the GrpcEnviroment is started and cannot be changed afterwards. + /// This is an advanced setting and you should only use it if you know what you are doing. + /// Most users should rely on the default value provided by gRPC library. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// + public static void SetBatchContextPoolParams(int sharedCapacity, int threadLocalCapacity) + { + lock (staticLock) + { + GrpcPreconditions.CheckState(instance == null, "Can only be set before GrpcEnvironment is initialized"); + GrpcPreconditions.CheckArgument(sharedCapacity >= 0, "Shared capacity needs to be a non-negative number"); + GrpcPreconditions.CheckArgument(threadLocalCapacity >= 0, "Thread local capacity needs to be a non-negative number"); + batchContextPoolSharedCapacity = sharedCapacity; + batchContextPoolThreadLocalCapacity = threadLocalCapacity; + } + } + + /// + /// Sets the parameters for a pool that caches request call context instances. Reusing request call context instances + /// instead of creating a new one for every requested call in C core helps reducing the GC pressure. + /// Can be only invoked before the GrpcEnviroment is started and cannot be changed afterwards. + /// This is an advanced setting and you should only use it if you know what you are doing. + /// Most users should rely on the default value provided by gRPC library. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// + public static void SetRequestCallContextPoolParams(int sharedCapacity, int threadLocalCapacity) + { + lock (staticLock) + { + GrpcPreconditions.CheckState(instance == null, "Can only be set before GrpcEnvironment is initialized"); + GrpcPreconditions.CheckArgument(sharedCapacity >= 0, "Shared capacity needs to be a non-negative number"); + GrpcPreconditions.CheckArgument(threadLocalCapacity >= 0, "Thread local capacity needs to be a non-negative number"); + requestCallContextPoolSharedCapacity = sharedCapacity; + requestCallContextPoolThreadLocalCapacity = threadLocalCapacity; + } + } + + /// + /// Occurs when GrpcEnvironment is about the start the shutdown logic. + /// If GrpcEnvironment is later initialized and shutdown, the event will be fired again (unless unregistered first). + /// + public static event EventHandler ShuttingDown; + + /// + /// Creates gRPC environment. + /// + private GrpcEnvironment() + { + GrpcNativeInit(); + batchContextPool = new DefaultObjectPool(() => BatchContextSafeHandle.Create(), batchContextPoolSharedCapacity, batchContextPoolThreadLocalCapacity); + requestCallContextPool = new DefaultObjectPool(() => RequestCallContextSafeHandle.Create(), requestCallContextPoolSharedCapacity, requestCallContextPoolThreadLocalCapacity); + threadPool = new GrpcThreadPool(this, GetThreadPoolSizeOrDefault(), GetCompletionQueueCountOrDefault(), inlineHandlers); + threadPool.Start(); + } + + /// + /// Gets the completion queues used by this gRPC environment. + /// + internal IReadOnlyCollection CompletionQueues + { + get + { + return this.threadPool.CompletionQueues; + } + } + + internal IObjectPool BatchContextPool => batchContextPool; + + internal IObjectPool RequestCallContextPool => requestCallContextPool; + + internal bool IsAlive + { + get + { + return this.threadPool.IsAlive; + } + } + + /// + /// Picks a completion queue in a round-robin fashion. + /// Shouldn't be invoked on a per-call basis (used at per-channel basis). + /// + internal CompletionQueueSafeHandle PickCompletionQueue() + { + var cqIndex = (int) ((cqPickerCounter.Increment() - 1) % this.threadPool.CompletionQueues.Count); + return this.threadPool.CompletionQueues.ElementAt(cqIndex); + } + + /// + /// Gets the completion queue used by this gRPC environment. + /// + internal DebugStats DebugStats + { + get + { + return this.debugStats; + } + } + + /// + /// Gets version of gRPC C core. + /// + internal static string GetCoreVersionString() + { + var ptr = NativeMethods.Get().grpcsharp_version_string(); // the pointer is not owned + return Marshal.PtrToStringAnsi(ptr); + } + + internal static void GrpcNativeInit() + { + if (!IsNativeShutdownAllowed && nativeInitCounter.Count > 0) + { + // Normally grpc_init and grpc_shutdown calls should come in pairs (C core does reference counting), + // but in case we avoid grpc_shutdown calls altogether, calling grpc_init has no effect + // besides incrementing an internal C core counter that could theoretically overflow. + // To avoid this theoretical possibility we guard repeated calls to grpc_init() + // with a 64-bit atomic counter (that can't realistically overflow). + return; + } + NativeMethods.Get().grpcsharp_init(); + nativeInitCounter.Increment(); + } + + internal static void GrpcNativeShutdown() + { + if (IsNativeShutdownAllowed) + { + NativeMethods.Get().grpcsharp_shutdown(); + } + } + + /// + /// Shuts down this environment. + /// + private async Task ShutdownAsync() + { + if (isShutdown) + { + throw new InvalidOperationException("ShutdownAsync has already been called"); + } + + await Task.Run(() => ShuttingDown?.Invoke(this, null)).ConfigureAwait(false); + + await threadPool.StopAsync().ConfigureAwait(false); + requestCallContextPool.Dispose(); + batchContextPool.Dispose(); + GrpcNativeShutdown(); + isShutdown = true; + + debugStats.CheckOK(); + } + + private int GetThreadPoolSizeOrDefault() + { + if (customThreadPoolSize.HasValue) + { + return customThreadPoolSize.Value; + } + // In systems with many cores, use half of the cores for GrpcThreadPool + // and the other half for .NET thread pool. This heuristic definitely needs + // more work, but seems to work reasonably well for a start. + return Math.Max(MinDefaultThreadPoolSize, Environment.ProcessorCount / 2); + } + + private int GetCompletionQueueCountOrDefault() + { + if (customCompletionQueueCount.HasValue) + { + return customCompletionQueueCount.Value; + } + // by default, create a completion queue for each thread + return GetThreadPoolSizeOrDefault(); + } + + // On some platforms (specifically iOS), thread local variables in native code + // require initialization/destruction. By skipping the grpc_shutdown() call, + // we avoid a potential crash where grpc_shutdown() has already destroyed + // the thread local variables, but some C core's *_destroy() methods still + // need to run (e.g. they may be run by finalizer thread which is out of our control) + // For more context, see https://github.com/grpc/grpc/issues/16294 + private static bool IsNativeShutdownAllowed => !PlatformApis.IsXamarinIOS && !PlatformApis.IsUnityIOS; + + private static class ShutdownHooks + { + static object staticLock = new object(); + static bool hooksRegistered; + + public static void Register() + { + lock (staticLock) + { + if (!hooksRegistered) + { + // Under normal circumstances, the user is expected to shutdown all + // the gRPC channels and servers before the application exits. The following + // hooks provide some extra handling for cases when this is not the case, + // in the effort to achieve a reasonable behavior on shutdown. +#if NETSTANDARD + // No action required at shutdown on .NET Core + // - In-progress P/Invoke calls (such as grpc_completion_queue_next) don't seem + // to prevent a .NET core application from terminating, so no special handling + // is needed. + // - .NET core doesn't run finalizers on shutdown, so there's no risk of getting + // a crash because grpc_*_destroy methods for native objects being invoked + // in wrong order. + // TODO(jtattermusch): Verify that the shutdown hooks are still not needed + // once we add support for new platforms using netstandard (e.g. Xamarin). +#else + // On desktop .NET framework and Mono, we need to register for a shutdown + // event to explicitly shutdown the GrpcEnvironment. + // - On Desktop .NET framework, we need to do a proper shutdown to prevent a crash + // when the framework attempts to run the finalizers for SafeHandle object representing the native + // grpc objects. The finalizers calls the native grpc_*_destroy methods (e.g. grpc_server_destroy) + // in a random order, which is not supported by gRPC. + // - On Mono, the process would freeze as the GrpcThreadPool threads are sleeping + // in grpc_completion_queue_next P/Invoke invocation and mono won't let the + // process shutdown until the P/Invoke calls return. We achieve that by shutting down + // the completion queue(s) which associated with the GrpcThreadPool, which will + // cause the grpc_completion_queue_next calls to return immediately. + AppDomain.CurrentDomain.ProcessExit += (sender, eventArgs) => { HandleShutdown(); }; + AppDomain.CurrentDomain.DomainUnload += (sender, eventArgs) => { HandleShutdown(); }; +#endif + } + hooksRegistered = true; + } + } + + /// + /// Handler for AppDomain.DomainUnload, AppDomain.ProcessExit and AssemblyLoadContext.Unloading hooks. + /// + private static void HandleShutdown() + { + Task.WaitAll(GrpcEnvironment.ShutdownChannelsAsync(), GrpcEnvironment.KillServersAsync()); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs b/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs new file mode 100644 index 00000000..321cf080 --- /dev/null +++ b/src/csharp/Grpc.Core/Interceptors/ServerServiceDefinitionExtensions.cs @@ -0,0 +1,129 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Linq; +using Grpc.Core.Utils; + +namespace Grpc.Core.Interceptors +{ + /// + /// Extends the ServerServiceDefinition class to add methods used to register interceptors on the server side. + /// + public static class ServerServiceDefinitionExtensions + { + /// + /// Returns a instance that + /// intercepts incoming calls to the underlying service handler through the given interceptor. + /// + /// The instance to register interceptors on. + /// The interceptor to intercept the incoming invocations with. + /// + /// Multiple interceptors can be added on top of each other by calling + /// "serverServiceDefinition.Intercept(a, b, c)". The order of invocation will be "a", "b", and then "c". + /// Interceptors can be later added to an existing intercepted service definition, effectively + /// building a chain like "serverServiceDefinition.Intercept(c).Intercept(b).Intercept(a)". Note that + /// in this case, the last interceptor added will be the first to take control. + /// + public static ServerServiceDefinition Intercept(this ServerServiceDefinition serverServiceDefinition, Interceptor interceptor) + { + GrpcPreconditions.CheckNotNull(serverServiceDefinition, nameof(serverServiceDefinition)); + GrpcPreconditions.CheckNotNull(interceptor, nameof(interceptor)); + + var binder = new InterceptingServiceBinder(interceptor); + serverServiceDefinition.BindService(binder); + return binder.GetInterceptedServerServiceDefinition(); + } + + /// + /// Returns a instance that + /// intercepts incoming calls to the underlying service handler through the given interceptors. + /// + /// The instance to register interceptors on. + /// + /// An array of interceptors to intercept the incoming invocations with. + /// Control is passed to the interceptors in the order specified. + /// + /// + /// Multiple interceptors can be added on top of each other by calling + /// "serverServiceDefinition.Intercept(a, b, c)". The order of invocation will be "a", "b", and then "c". + /// Interceptors can be later added to an existing intercepted service definition, effectively + /// building a chain like "serverServiceDefinition.Intercept(c).Intercept(b).Intercept(a)". Note that + /// in this case, the last interceptor added will be the first to take control. + /// + public static ServerServiceDefinition Intercept(this ServerServiceDefinition serverServiceDefinition, params Interceptor[] interceptors) + { + GrpcPreconditions.CheckNotNull(serverServiceDefinition, nameof(serverServiceDefinition)); + GrpcPreconditions.CheckNotNull(interceptors, nameof(interceptors)); + + foreach (var interceptor in interceptors.Reverse()) + { + serverServiceDefinition = Intercept(serverServiceDefinition, interceptor); + } + + return serverServiceDefinition; + } + + /// + /// Helper for creating ServerServiceDefinition with intercepted handlers. + /// + private class InterceptingServiceBinder : ServiceBinderBase + { + readonly ServerServiceDefinition.Builder builder = ServerServiceDefinition.CreateBuilder(); + readonly Interceptor interceptor; + + public InterceptingServiceBinder(Interceptor interceptor) + { + this.interceptor = GrpcPreconditions.CheckNotNull(interceptor, nameof(interceptor)); + } + + internal ServerServiceDefinition GetInterceptedServerServiceDefinition() + { + return builder.Build(); + } + + public override void AddMethod( + Method method, + UnaryServerMethod handler) + { + builder.AddMethod(method, (request, context) => interceptor.UnaryServerHandler(request, context, handler)); + } + + public override void AddMethod( + Method method, + ClientStreamingServerMethod handler) + { + builder.AddMethod(method, (requestStream, context) => interceptor.ClientStreamingServerHandler(requestStream, context, handler)); + } + + public override void AddMethod( + Method method, + ServerStreamingServerMethod handler) + { + builder.AddMethod(method, (request, responseStream, context) => interceptor.ServerStreamingServerHandler(request, responseStream, context, handler)); + } + + public override void AddMethod( + Method method, + DuplexStreamingServerMethod handler) + { + builder.AddMethod(method, (requestStream, responseStream, context) => interceptor.DuplexStreamingServerHandler(requestStream, responseStream, context, handler)); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs new file mode 100644 index 00000000..500842f7 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs @@ -0,0 +1,681 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core.Logging; +using Grpc.Core.Profiling; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Manages client side native call lifecycle. + /// + internal class AsyncCall : AsyncCallBase, IUnaryResponseClientCallback, IReceivedStatusOnClientCallback, IReceivedResponseHeadersCallback + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType>(); + + readonly CallInvocationDetails details; + readonly INativeCall injectedNativeCall; // for testing + + bool registeredWithChannel; + + // Dispose of to de-register cancellation token registration + CancellationTokenRegistration cancellationTokenRegistration; + + // Completion of a pending unary response if not null. + TaskCompletionSource unaryResponseTcs; + + // Completion of a streaming response call if not null. + TaskCompletionSource streamingResponseCallFinishedTcs; + + // TODO(jtattermusch): this field could be lazy-initialized (only if someone requests the response headers). + // Response headers set here once received. + TaskCompletionSource responseHeadersTcs = new TaskCompletionSource(); + + // Set after status is received. Used for both unary and streaming response calls. + ClientSideStatus? finishedStatus; + + public AsyncCall(CallInvocationDetails callDetails) + : base(callDetails.RequestMarshaller.ContextualSerializer, callDetails.ResponseMarshaller.ContextualDeserializer) + { + this.details = callDetails.WithOptions(callDetails.Options.Normalize()); + this.initialMetadataSent = true; // we always send metadata at the very beginning of the call. + } + + /// + /// This constructor should only be used for testing. + /// + public AsyncCall(CallInvocationDetails callDetails, INativeCall injectedNativeCall) : this(callDetails) + { + this.injectedNativeCall = injectedNativeCall; + } + + // TODO: this method is not Async, so it shouldn't be in AsyncCall class, but + // it is reusing fair amount of code in this class, so we are leaving it here. + /// + /// Blocking unary request - unary response call. + /// + public TResponse UnaryCall(TRequest msg) + { + var profiler = Profilers.ForCurrentThread(); + + using (profiler.NewScope("AsyncCall.UnaryCall")) + using (CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.CreateSync()) + { + bool callStartedOk = false; + try + { + unaryResponseTcs = new TaskCompletionSource(); + + lock (myLock) + { + GrpcPreconditions.CheckState(!started); + started = true; + Initialize(cq); + + halfcloseRequested = true; + readingDone = true; + } + + using (var serializationScope = DefaultSerializationContext.GetInitializedThreadLocalScope()) + using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) + { + var payload = UnsafeSerialize(msg, serializationScope.Context); // do before metadata array? + var ctx = details.Channel.Environment.BatchContextPool.Lease(); + try + { + call.StartUnary(ctx, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags); + callStartedOk = true; + + var ev = cq.Pluck(ctx.Handle); + bool success = (ev.success != 0); + try + { + using (profiler.NewScope("AsyncCall.UnaryCall.HandleBatch")) + { + HandleUnaryResponse(success, ctx.GetReceivedStatusOnClient(), ctx.GetReceivedMessageReader(), ctx.GetReceivedInitialMetadata()); + } + } + catch (Exception e) + { + Logger.Error(e, "Exception occurred while invoking completion delegate."); + } + } + finally + { + ctx.Recycle(); + } + } + } + finally + { + if (!callStartedOk) + { + lock (myLock) + { + OnFailedToStartCallLocked(); + } + } + } + + // Once the blocking call returns, the result should be available synchronously. + // Note that GetAwaiter().GetResult() doesn't wrap exceptions in AggregateException. + return unaryResponseTcs.Task.GetAwaiter().GetResult(); + } + } + + /// + /// Starts a unary request - unary response call. + /// + public Task UnaryCallAsync(TRequest msg) + { + lock (myLock) + { + bool callStartedOk = false; + try + { + GrpcPreconditions.CheckState(!started); + started = true; + + Initialize(details.Channel.CompletionQueue); + + halfcloseRequested = true; + readingDone = true; + + using (var serializationScope = DefaultSerializationContext.GetInitializedThreadLocalScope()) + { + var payload = UnsafeSerialize(msg, serializationScope.Context); + unaryResponseTcs = new TaskCompletionSource(); + using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) + { + call.StartUnary(UnaryResponseClientCallback, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags); + callStartedOk = true; + } + } + + return unaryResponseTcs.Task; + } + finally + { + if (!callStartedOk) + { + OnFailedToStartCallLocked(); + } + } + } + } + + /// + /// Starts a streamed request - unary response call. + /// Use StartSendMessage and StartSendCloseFromClient to stream requests. + /// + public Task ClientStreamingCallAsync() + { + lock (myLock) + { + bool callStartedOk = false; + try + { + GrpcPreconditions.CheckState(!started); + started = true; + + Initialize(details.Channel.CompletionQueue); + + readingDone = true; + + unaryResponseTcs = new TaskCompletionSource(); + using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) + { + call.StartClientStreaming(UnaryResponseClientCallback, metadataArray, details.Options.Flags); + callStartedOk = true; + } + + return unaryResponseTcs.Task; + } + finally + { + if (!callStartedOk) + { + OnFailedToStartCallLocked(); + } + } + } + } + + /// + /// Starts a unary request - streamed response call. + /// + public void StartServerStreamingCall(TRequest msg) + { + lock (myLock) + { + bool callStartedOk = false; + try + { + GrpcPreconditions.CheckState(!started); + started = true; + + Initialize(details.Channel.CompletionQueue); + + halfcloseRequested = true; + receiveResponseHeadersPending = true; + + using (var serializationScope = DefaultSerializationContext.GetInitializedThreadLocalScope()) + { + var payload = UnsafeSerialize(msg, serializationScope.Context); + streamingResponseCallFinishedTcs = new TaskCompletionSource(); + using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) + { + call.StartServerStreaming(ReceivedStatusOnClientCallback, payload, GetWriteFlagsForCall(), metadataArray, details.Options.Flags); + callStartedOk = true; + } + } + call.StartReceiveInitialMetadata(ReceivedResponseHeadersCallback); + } + finally + { + if (!callStartedOk) + { + OnFailedToStartCallLocked(); + } + } + } + } + + /// + /// Starts a streaming request - streaming response call. + /// Use StartSendMessage and StartSendCloseFromClient to stream requests. + /// + public void StartDuplexStreamingCall() + { + lock (myLock) + { + bool callStartedOk = false; + try + { + GrpcPreconditions.CheckState(!started); + started = true; + receiveResponseHeadersPending = true; + + Initialize(details.Channel.CompletionQueue); + + streamingResponseCallFinishedTcs = new TaskCompletionSource(); + using (var metadataArray = MetadataArraySafeHandle.Create(details.Options.Headers)) + { + call.StartDuplexStreaming(ReceivedStatusOnClientCallback, metadataArray, details.Options.Flags); + callStartedOk = true; + } + call.StartReceiveInitialMetadata(ReceivedResponseHeadersCallback); + } + finally + { + if (!callStartedOk) + { + OnFailedToStartCallLocked(); + } + } + } + } + + /// + /// Sends a streaming request. Only one pending send action is allowed at any given time. + /// + public Task SendMessageAsync(TRequest msg, WriteFlags writeFlags) + { + return SendMessageInternalAsync(msg, writeFlags); + } + + /// + /// Receives a streaming response. Only one pending read action is allowed at any given time. + /// + public Task ReadMessageAsync() + { + return ReadMessageInternalAsync(); + } + + /// + /// Sends halfclose, indicating client is done with streaming requests. + /// Only one pending send action is allowed at any given time. + /// + public Task SendCloseFromClientAsync() + { + lock (myLock) + { + GrpcPreconditions.CheckState(started); + + var earlyResult = CheckSendPreconditionsClientSide(); + if (earlyResult != null) + { + return earlyResult; + } + + if (disposed || finished) + { + // In case the call has already been finished by the serverside, + // the halfclose has already been done implicitly, so just return + // completed task here. + halfcloseRequested = true; + return TaskUtils.CompletedTask; + } + call.StartSendCloseFromClient(SendCompletionCallback); + + halfcloseRequested = true; + streamingWriteTcs = new TaskCompletionSource(); + return streamingWriteTcs.Task; + } + } + + /// + /// Get the task that completes once if streaming response call finishes with ok status and throws RpcException with given status otherwise. + /// + public Task StreamingResponseCallFinishedTask + { + get + { + return streamingResponseCallFinishedTcs.Task; + } + } + + /// + /// Get the task that completes once response headers are received. + /// + public Task ResponseHeadersAsync + { + get + { + return responseHeadersTcs.Task; + } + } + + /// + /// Gets the resulting status if the call has already finished. + /// Throws InvalidOperationException otherwise. + /// + public Status GetStatus() + { + lock (myLock) + { + GrpcPreconditions.CheckState(finishedStatus.HasValue, "Status can only be accessed once the call has finished."); + return finishedStatus.Value.Status; + } + } + + /// + /// Gets the trailing metadata if the call has already finished. + /// Throws InvalidOperationException otherwise. + /// + public Metadata GetTrailers() + { + lock (myLock) + { + GrpcPreconditions.CheckState(finishedStatus.HasValue, "Trailers can only be accessed once the call has finished."); + return finishedStatus.Value.Trailers; + } + } + + public CallInvocationDetails Details + { + get + { + return this.details; + } + } + + protected override void OnAfterReleaseResourcesLocked() + { + if (registeredWithChannel) + { + details.Channel.RemoveCallReference(this); + registeredWithChannel = false; + } + } + + protected override void OnAfterReleaseResourcesUnlocked() + { + // If cancellation callback is in progress, this can block + // so we need to do this outside of call's lock to prevent + // deadlock. + // See https://github.com/grpc/grpc/issues/14777 + // See https://github.com/dotnet/corefx/issues/14903 + cancellationTokenRegistration.Dispose(); + } + + protected override bool IsClient + { + get { return true; } + } + + protected override Exception GetRpcExceptionClientOnly() + { + return new RpcException(finishedStatus.Value.Status, finishedStatus.Value.Trailers); + } + + protected override Task CheckSendAllowedOrEarlyResult() + { + var earlyResult = CheckSendPreconditionsClientSide(); + if (earlyResult != null) + { + return earlyResult; + } + + if (finishedStatus.HasValue) + { + // throwing RpcException if we already received status on client + // side makes the most sense. + // Note that this throws even for StatusCode.OK. + // Writing after the call has finished is not a programming error because server can close + // the call anytime, so don't throw directly, but let the write task finish with an error. + var tcs = new TaskCompletionSource(); + tcs.SetException(new RpcException(finishedStatus.Value.Status, finishedStatus.Value.Trailers)); + return tcs.Task; + } + + return null; + } + + private Task CheckSendPreconditionsClientSide() + { + GrpcPreconditions.CheckState(!halfcloseRequested, "Request stream has already been completed."); + GrpcPreconditions.CheckState(streamingWriteTcs == null, "Only one write can be pending at a time."); + + if (cancelRequested) + { + // Return a cancelled task. + var tcs = new TaskCompletionSource(); + tcs.SetCanceled(); + return tcs.Task; + } + + return null; + } + + private void Initialize(CompletionQueueSafeHandle cq) + { + var call = CreateNativeCall(cq); + + details.Channel.AddCallReference(this); + registeredWithChannel = true; + InitializeInternal(call); + + RegisterCancellationCallback(); + } + + private void OnFailedToStartCallLocked() + { + ReleaseResources(); + + // We need to execute the hook that disposes the cancellation token + // registration, but it cannot be done from under a lock. + // To make things simple, we just schedule the unregistering + // on a threadpool. + // - Once the native call is disposed, the Cancel() calls are ignored anyway + // - We don't care about the overhead as OnFailedToStartCallLocked() only happens + // when something goes very bad when initializing a call and that should + // never happen when gRPC is used correctly. + ThreadPool.QueueUserWorkItem((state) => OnAfterReleaseResourcesUnlocked()); + } + + private INativeCall CreateNativeCall(CompletionQueueSafeHandle cq) + { + if (injectedNativeCall != null) + { + return injectedNativeCall; // allows injecting a mock INativeCall in tests. + } + + var parentCall = details.Options.PropagationToken.AsImplOrNull()?.ParentCall ?? CallSafeHandle.NullInstance; + + var credentials = details.Options.Credentials; + using (var nativeCredentials = credentials != null ? credentials.ToNativeCredentials() : null) + { + var result = details.Channel.Handle.CreateCall( + parentCall, ContextPropagationTokenImpl.DefaultMask, cq, + details.Method, details.Host, Timespec.FromDateTime(details.Options.Deadline.Value), nativeCredentials); + return result; + } + } + + // Make sure that once cancellationToken for this call is cancelled, Cancel() will be called. + private void RegisterCancellationCallback() + { + cancellationTokenRegistration = RegisterCancellationCallbackForToken(details.Options.CancellationToken); + } + + /// + /// Gets WriteFlags set in callDetails.Options.WriteOptions + /// + private WriteFlags GetWriteFlagsForCall() + { + var writeOptions = details.Options.WriteOptions; + return writeOptions != null ? writeOptions.Flags : default(WriteFlags); + } + + /// + /// Handles receive status completion for calls with streaming response. + /// + private void HandleReceivedResponseHeaders(bool success, Metadata responseHeaders) + { + // TODO(jtattermusch): handle success==false + + bool releasedResources; + lock (myLock) + { + receiveResponseHeadersPending = false; + releasedResources = ReleaseResourcesIfPossible(); + } + + if (releasedResources) + { + OnAfterReleaseResourcesUnlocked(); + } + + responseHeadersTcs.SetResult(responseHeaders); + } + + /// + /// Handler for unary response completion. + /// + private void HandleUnaryResponse(bool success, ClientSideStatus receivedStatus, IBufferReader receivedMessageReader, Metadata responseHeaders) + { + // NOTE: because this event is a result of batch containing GRPC_OP_RECV_STATUS_ON_CLIENT, + // success will be always set to true. + + TaskCompletionSource delayedStreamingWriteTcs = null; + TResponse msg = default(TResponse); + var deserializeException = TryDeserialize(receivedMessageReader, out msg); + + bool releasedResources; + lock (myLock) + { + finished = true; + + if (deserializeException != null && receivedStatus.Status.StatusCode == StatusCode.OK) + { + receivedStatus = new ClientSideStatus(DeserializeResponseFailureStatus, receivedStatus.Trailers); + } + finishedStatus = receivedStatus; + + if (isStreamingWriteCompletionDelayed) + { + delayedStreamingWriteTcs = streamingWriteTcs; + streamingWriteTcs = null; + } + + releasedResources = ReleaseResourcesIfPossible(); + } + + if (releasedResources) + { + OnAfterReleaseResourcesUnlocked(); + } + + responseHeadersTcs.SetResult(responseHeaders); + + if (delayedStreamingWriteTcs != null) + { + delayedStreamingWriteTcs.SetException(GetRpcExceptionClientOnly()); + } + + var status = receivedStatus.Status; + if (status.StatusCode != StatusCode.OK) + { + unaryResponseTcs.SetException(new RpcException(status, receivedStatus.Trailers)); + return; + } + + unaryResponseTcs.SetResult(msg); + } + + /// + /// Handles receive status completion for calls with streaming response. + /// + private void HandleFinished(bool success, ClientSideStatus receivedStatus) + { + // NOTE: because this event is a result of batch containing GRPC_OP_RECV_STATUS_ON_CLIENT, + // success will be always set to true. + + TaskCompletionSource delayedStreamingWriteTcs = null; + + bool releasedResources; + bool origCancelRequested; + lock (myLock) + { + finished = true; + finishedStatus = receivedStatus; + if (isStreamingWriteCompletionDelayed) + { + delayedStreamingWriteTcs = streamingWriteTcs; + streamingWriteTcs = null; + } + + releasedResources = ReleaseResourcesIfPossible(); + origCancelRequested = cancelRequested; + } + + if (releasedResources) + { + OnAfterReleaseResourcesUnlocked(); + } + + if (delayedStreamingWriteTcs != null) + { + delayedStreamingWriteTcs.SetException(GetRpcExceptionClientOnly()); + } + + var status = receivedStatus.Status; + if (status.StatusCode != StatusCode.OK) + { + streamingResponseCallFinishedTcs.SetException(new RpcException(status, receivedStatus.Trailers)); + if (status.StatusCode == StatusCode.Cancelled || origCancelRequested) + { + // Make sure the exception set to the Task is observed, + // otherwise this can trigger "Unobserved exception" when the response stream + // is not read until its end and the task created by the TCS is garbage collected. + // See https://github.com/grpc/grpc/issues/17458 + var _ = streamingResponseCallFinishedTcs.Task.Exception; + } + return; + } + + streamingResponseCallFinishedTcs.SetResult(null); + } + + IUnaryResponseClientCallback UnaryResponseClientCallback => this; + + void IUnaryResponseClientCallback.OnUnaryResponseClient(bool success, ClientSideStatus receivedStatus, IBufferReader receivedMessageReader, Metadata responseHeaders) + { + HandleUnaryResponse(success, receivedStatus, receivedMessageReader, responseHeaders); + } + + IReceivedStatusOnClientCallback ReceivedStatusOnClientCallback => this; + + void IReceivedStatusOnClientCallback.OnReceivedStatusOnClient(bool success, ClientSideStatus receivedStatus) + { + HandleFinished(success, receivedStatus); + } + + IReceivedResponseHeadersCallback ReceivedResponseHeadersCallback => this; + + void IReceivedResponseHeadersCallback.OnReceivedResponseHeaders(bool success, Metadata responseHeaders) + { + HandleReceivedResponseHeaders(success, responseHeaders); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs new file mode 100644 index 00000000..e5d30e90 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs @@ -0,0 +1,401 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +using Grpc.Core.Internal; +using Grpc.Core.Logging; +using Grpc.Core.Profiling; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Base for handling both client side and server side calls. + /// Manages native call lifecycle and provides convenience methods. + /// + internal abstract class AsyncCallBase : IReceivedMessageCallback, ISendCompletionCallback + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType>(); + protected static readonly Status DeserializeResponseFailureStatus = new Status(StatusCode.Internal, "Failed to deserialize response message."); + + readonly Action serializer; + readonly Func deserializer; + + protected readonly object myLock = new object(); + + protected INativeCall call; + protected bool disposed; + + protected bool started; + protected bool cancelRequested; + + protected TaskCompletionSource streamingReadTcs; // Completion of a pending streaming read if not null. + protected TaskCompletionSource streamingWriteTcs; // Completion of a pending streaming write or send close from client if not null. + protected TaskCompletionSource sendStatusFromServerTcs; + protected bool isStreamingWriteCompletionDelayed; // Only used for the client side. + + protected bool readingDone; // True if last read (i.e. read with null payload) was already received. + protected bool halfcloseRequested; // True if send close have been initiated. + protected bool finished; // True if close has been received from the peer. + + protected bool initialMetadataSent; + protected long streamingWritesCounter; // Number of streaming send operations started so far. + protected bool receiveResponseHeadersPending; // True if this is a call with streaming response and the recv_initial_metadata_on_client operation hasn't finished yet. + + public AsyncCallBase(Action serializer, Func deserializer) + { + this.serializer = GrpcPreconditions.CheckNotNull(serializer); + this.deserializer = GrpcPreconditions.CheckNotNull(deserializer); + } + + /// + /// Requests cancelling the call. + /// + public void Cancel() + { + lock (myLock) + { + GrpcPreconditions.CheckState(started); + cancelRequested = true; + + if (!disposed) + { + call.Cancel(); + } + } + } + + /// + /// Requests cancelling the call with given status. + /// + protected void CancelWithStatus(Status status) + { + lock (myLock) + { + cancelRequested = true; + + if (!disposed) + { + call.CancelWithStatus(status); + } + } + } + + protected void InitializeInternal(INativeCall call) + { + lock (myLock) + { + this.call = call; + } + } + + /// + /// Initiates sending a message. Only one send operation can be active at a time. + /// + protected Task SendMessageInternalAsync(TWrite msg, WriteFlags writeFlags) + { + using (var serializationScope = DefaultSerializationContext.GetInitializedThreadLocalScope()) + { + var payload = UnsafeSerialize(msg, serializationScope.Context); + lock (myLock) + { + GrpcPreconditions.CheckState(started); + var earlyResult = CheckSendAllowedOrEarlyResult(); + if (earlyResult != null) + { + return earlyResult; + } + + call.StartSendMessage(SendCompletionCallback, payload, writeFlags, !initialMetadataSent); + + initialMetadataSent = true; + streamingWritesCounter++; + streamingWriteTcs = new TaskCompletionSource(); + return streamingWriteTcs.Task; + } + } + } + + /// + /// Initiates reading a message. Only one read operation can be active at a time. + /// + protected Task ReadMessageInternalAsync() + { + lock (myLock) + { + GrpcPreconditions.CheckState(started); + if (readingDone) + { + // the last read that returns null or throws an exception is idempotent + // and maintains its state. + GrpcPreconditions.CheckState(streamingReadTcs != null, "Call does not support streaming reads."); + return streamingReadTcs.Task; + } + + GrpcPreconditions.CheckState(streamingReadTcs == null, "Only one read can be pending at a time"); + GrpcPreconditions.CheckState(!disposed); + + call.StartReceiveMessage(ReceivedMessageCallback); + streamingReadTcs = new TaskCompletionSource(); + return streamingReadTcs.Task; + } + } + + /// + /// If there are no more pending actions and no new actions can be started, releases + /// the underlying native resources. + /// + protected bool ReleaseResourcesIfPossible() + { + if (!disposed && call != null) + { + bool noMoreSendCompletions = streamingWriteTcs == null && (halfcloseRequested || cancelRequested || finished); + if (noMoreSendCompletions && readingDone && finished && !receiveResponseHeadersPending) + { + ReleaseResources(); + return true; + } + } + return false; + } + + protected abstract bool IsClient + { + get; + } + + /// + /// Returns an exception to throw for a failed send operation. + /// It is only allowed to call this method for a call that has already finished. + /// + protected abstract Exception GetRpcExceptionClientOnly(); + + protected void ReleaseResources() + { + if (call != null) + { + call.Dispose(); + } + disposed = true; + OnAfterReleaseResourcesLocked(); + } + + protected virtual void OnAfterReleaseResourcesLocked() + { + } + + protected virtual void OnAfterReleaseResourcesUnlocked() + { + } + + /// + /// Checks if sending is allowed and possibly returns a Task that allows short-circuiting the send + /// logic by directly returning the write operation result task. Normally, null is returned. + /// + protected abstract Task CheckSendAllowedOrEarlyResult(); + + // runs the serializer, propagating any exceptions being thrown without modifying them + protected SliceBufferSafeHandle UnsafeSerialize(TWrite msg, DefaultSerializationContext context) + { + serializer(msg, context); + return context.GetPayload(); + } + + protected Exception TryDeserialize(IBufferReader reader, out TRead msg) + { + DefaultDeserializationContext context = null; + try + { + context = DefaultDeserializationContext.GetInitializedThreadLocal(reader); + msg = deserializer(context); + return null; + } + catch (Exception e) + { + msg = default(TRead); + return e; + } + finally + { + context?.Reset(); + } + } + + /// + /// Handles send completion (including SendCloseFromClient). + /// + protected void HandleSendFinished(bool success) + { + bool delayCompletion = false; + TaskCompletionSource origTcs = null; + bool releasedResources; + lock (myLock) + { + if (!success && !finished && IsClient) { + // We should be setting this only once per call, following writes will be short circuited + // because they cannot start until the entire call finishes. + GrpcPreconditions.CheckState(!isStreamingWriteCompletionDelayed); + + // leave streamingWriteTcs set, it will be completed once call finished. + isStreamingWriteCompletionDelayed = true; + delayCompletion = true; + } + else + { + origTcs = streamingWriteTcs; + streamingWriteTcs = null; + } + + releasedResources = ReleaseResourcesIfPossible(); + } + + if (releasedResources) + { + OnAfterReleaseResourcesUnlocked(); + } + + if (!success) + { + if (!delayCompletion) + { + if (IsClient) + { + GrpcPreconditions.CheckState(finished); // implied by !success && !delayCompletion && IsClient + origTcs.SetException(GetRpcExceptionClientOnly()); + } + else + { + origTcs.SetException (new IOException("Error sending from server.")); + } + } + // if delayCompletion == true, postpone SetException until call finishes. + } + else + { + origTcs.SetResult(null); + } + } + + /// + /// Handles send status from server completion. + /// + protected void HandleSendStatusFromServerFinished(bool success) + { + bool releasedResources; + lock (myLock) + { + releasedResources = ReleaseResourcesIfPossible(); + } + + if (releasedResources) + { + OnAfterReleaseResourcesUnlocked(); + } + + if (!success) + { + sendStatusFromServerTcs.SetException(new IOException("Error sending status from server.")); + } + else + { + sendStatusFromServerTcs.SetResult(null); + } + } + + /// + /// Handles streaming read completion. + /// + protected void HandleReadFinished(bool success, IBufferReader receivedMessageReader) + { + // if success == false, the message reader will report null payload. It that case we will + // treat this completion as the last read an rely on C core to handle the failed + // read (e.g. deliver approriate statusCode on the clientside). + + TRead msg = default(TRead); + var deserializeException = (success && receivedMessageReader.TotalLength.HasValue) ? TryDeserialize(receivedMessageReader, out msg) : null; + + TaskCompletionSource origTcs = null; + bool releasedResources; + lock (myLock) + { + origTcs = streamingReadTcs; + if (!receivedMessageReader.TotalLength.HasValue) + { + // This was the last read. + readingDone = true; + } + + if (deserializeException != null && IsClient) + { + readingDone = true; + + // TODO(jtattermusch): it might be too late to set the status + CancelWithStatus(DeserializeResponseFailureStatus); + } + + if (!readingDone) + { + streamingReadTcs = null; + } + + releasedResources = ReleaseResourcesIfPossible(); + } + + if (releasedResources) + { + OnAfterReleaseResourcesUnlocked(); + } + + if (deserializeException != null && !IsClient) + { + origTcs.SetException(new IOException("Failed to deserialize request message.", deserializeException)); + return; + } + origTcs.SetResult(msg); + } + + protected ISendCompletionCallback SendCompletionCallback => this; + + void ISendCompletionCallback.OnSendCompletion(bool success) + { + HandleSendFinished(success); + } + + IReceivedMessageCallback ReceivedMessageCallback => this; + + void IReceivedMessageCallback.OnReceivedMessage(bool success, IBufferReader receivedMessageReader) + { + HandleReadFinished(success, receivedMessageReader); + } + + internal CancellationTokenRegistration RegisterCancellationCallbackForToken(CancellationToken cancellationToken) + { + if (cancellationToken.CanBeCanceled) return cancellationToken.Register(CancelCallFromToken, this); + return default(CancellationTokenRegistration); + } + + private static readonly Action CancelCallFromToken = state => ((AsyncCallBase)state).Cancel(); + } +} diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs new file mode 100644 index 00000000..58bc40b0 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs @@ -0,0 +1,266 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Manages server side native call lifecycle. + /// + internal class AsyncCallServer : AsyncCallBase, IReceivedCloseOnServerCallback, ISendStatusFromServerCompletionCallback + { + readonly TaskCompletionSource finishedServersideTcs = new TaskCompletionSource(); + readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); + readonly Server server; + + public AsyncCallServer(Action serializer, Func deserializer, Server server) : base(serializer, deserializer) + { + this.server = GrpcPreconditions.CheckNotNull(server); + } + + public void Initialize(CallSafeHandle call, CompletionQueueSafeHandle completionQueue) + { + call.Initialize(completionQueue); + + server.AddCallReference(this); + InitializeInternal(call); + } + + /// + /// Only for testing purposes. + /// + public void InitializeForTesting(INativeCall call) + { + server.AddCallReference(this); + InitializeInternal(call); + } + + /// + /// Starts a server side call. + /// + public Task ServerSideCallAsync() + { + lock (myLock) + { + GrpcPreconditions.CheckNotNull(call); + + started = true; + + call.StartServerSide(ReceiveCloseOnServerCallback); + return finishedServersideTcs.Task; + } + } + + /// + /// Sends a streaming response. Only one pending send action is allowed at any given time. + /// + public Task SendMessageAsync(TResponse msg, WriteFlags writeFlags) + { + return SendMessageInternalAsync(msg, writeFlags); + } + + /// + /// Receives a streaming request. Only one pending read action is allowed at any given time. + /// + public Task ReadMessageAsync() + { + return ReadMessageInternalAsync(); + } + + /// + /// Initiates sending a initial metadata. + /// Even though C-core allows sending metadata in parallel to sending messages, we will treat sending metadata as a send message operation + /// to make things simpler. + /// + public Task SendInitialMetadataAsync(Metadata headers) + { + lock (myLock) + { + GrpcPreconditions.CheckNotNull(headers, "metadata"); + + GrpcPreconditions.CheckState(started); + GrpcPreconditions.CheckState(!initialMetadataSent, "Response headers can only be sent once per call."); + GrpcPreconditions.CheckState(streamingWritesCounter == 0, "Response headers can only be sent before the first write starts."); + + var earlyResult = CheckSendAllowedOrEarlyResult(); + if (earlyResult != null) + { + return earlyResult; + } + + using (var metadataArray = MetadataArraySafeHandle.Create(headers)) + { + call.StartSendInitialMetadata(SendCompletionCallback, metadataArray); + } + + this.initialMetadataSent = true; + streamingWriteTcs = new TaskCompletionSource(); + return streamingWriteTcs.Task; + } + } + + /// + /// Sends call result status, indicating we are done with writes. + /// Sending a status different from StatusCode.OK will also implicitly cancel the call. + /// + public Task SendStatusFromServerAsync(Status status, Metadata trailers, ResponseWithFlags? optionalWrite) + { + using (var serializationScope = DefaultSerializationContext.GetInitializedThreadLocalScope()) + { + var payload = optionalWrite.HasValue ? UnsafeSerialize(optionalWrite.Value.Response, serializationScope.Context) : SliceBufferSafeHandle.NullInstance; + var writeFlags = optionalWrite.HasValue ? optionalWrite.Value.WriteFlags : default(WriteFlags); + + lock (myLock) + { + GrpcPreconditions.CheckState(started); + GrpcPreconditions.CheckState(!disposed); + GrpcPreconditions.CheckState(!halfcloseRequested, "Can only send status from server once."); + + using (var metadataArray = MetadataArraySafeHandle.Create(trailers)) + { + call.StartSendStatusFromServer(SendStatusFromServerCompletionCallback, status, metadataArray, !initialMetadataSent, + payload, writeFlags); + } + halfcloseRequested = true; + initialMetadataSent = true; + sendStatusFromServerTcs = new TaskCompletionSource(); + if (optionalWrite.HasValue) + { + streamingWritesCounter++; + } + return sendStatusFromServerTcs.Task; + } + } + } + + /// + /// Gets cancellation token that gets cancelled once close completion + /// is received and the cancelled flag is set. + /// + public CancellationToken CancellationToken + { + get + { + return cancellationTokenSource.Token; + } + } + + public string Peer + { + get + { + return call.GetPeer(); + } + } + + protected override bool IsClient + { + get { return false; } + } + + protected override Exception GetRpcExceptionClientOnly() + { + throw new InvalidOperationException("Call be only called for client calls"); + } + + protected override void OnAfterReleaseResourcesLocked() + { + server.RemoveCallReference(this); + } + + protected override Task CheckSendAllowedOrEarlyResult() + { + GrpcPreconditions.CheckState(!halfcloseRequested, "Response stream has already been completed."); + GrpcPreconditions.CheckState(!finished, "Already finished."); + GrpcPreconditions.CheckState(streamingWriteTcs == null, "Only one write can be pending at a time"); + GrpcPreconditions.CheckState(!disposed); + + return null; + } + + /// + /// Handles the server side close completion. + /// + private void HandleFinishedServerside(bool success, bool cancelled) + { + // NOTE: because this event is a result of batch containing GRPC_OP_RECV_CLOSE_ON_SERVER, + // success will be always set to true. + bool releasedResources; + lock (myLock) + { + finished = true; + if (streamingReadTcs == null) + { + // if there's no pending read, readingDone=true will dispose now. + // if there is a pending read, we will dispose once that read finishes. + readingDone = true; + streamingReadTcs = new TaskCompletionSource(); + streamingReadTcs.SetResult(default(TRequest)); + } + releasedResources = ReleaseResourcesIfPossible(); + } + + if (releasedResources) + { + OnAfterReleaseResourcesUnlocked(); + } + + if (cancelled) + { + cancellationTokenSource.Cancel(); + } + + finishedServersideTcs.SetResult(null); + } + + IReceivedCloseOnServerCallback ReceiveCloseOnServerCallback => this; + + void IReceivedCloseOnServerCallback.OnReceivedCloseOnServer(bool success, bool cancelled) + { + HandleFinishedServerside(success, cancelled); + } + + ISendStatusFromServerCompletionCallback SendStatusFromServerCompletionCallback => this; + + void ISendStatusFromServerCompletionCallback.OnSendStatusFromServerCompletion(bool success) + { + HandleSendStatusFromServerFinished(success); + } + + public struct ResponseWithFlags + { + public ResponseWithFlags(TResponse response, WriteFlags writeFlags) + { + this.Response = response; + this.WriteFlags = writeFlags; + } + + public TResponse Response { get; } + public WriteFlags WriteFlags { get; } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/AtomicCounter.cs b/src/csharp/Grpc.Core/Internal/AtomicCounter.cs new file mode 100644 index 00000000..20e25f9d --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/AtomicCounter.cs @@ -0,0 +1,71 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading; + +namespace Grpc.Core.Internal +{ + internal class AtomicCounter + { + long counter = 0; + + public AtomicCounter(long initialCount = 0) + { + this.counter = initialCount; + } + + public long Increment() + { + return Interlocked.Increment(ref counter); + } + + public void IncrementIfNonzero(ref bool success) + { + long origValue = counter; + while (true) + { + if (origValue == 0) + { + success = false; + return; + } + long result = Interlocked.CompareExchange(ref counter, origValue + 1, origValue); + if (result == origValue) + { + success = true; + return; + }; + origValue = result; + } + } + + public long Decrement() + { + return Interlocked.Decrement(ref counter); + } + + public long Count + { + get + { + return Interlocked.Read(ref counter); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/AuthContextSafeHandle.cs b/src/csharp/Grpc.Core/Internal/AuthContextSafeHandle.cs new file mode 100644 index 00000000..e8e61ebf --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/AuthContextSafeHandle.cs @@ -0,0 +1,107 @@ +#region Copyright notice and license + +// Copyright 2017 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using Grpc.Core; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// grpc_auth_context + /// + internal class AuthContextSafeHandle : SafeHandleZeroIsInvalid + { + static readonly NativeMethods Native = NativeMethods.Get(); + + private AuthContextSafeHandle() + { + } + + /// + /// Copies contents of the native auth context into a new AuthContext instance. + /// + public AuthContext ToAuthContext() + { + if (IsInvalid) + { + return new AuthContext(null, new Dictionary>()); + } + + var peerIdentityPropertyName = Marshal.PtrToStringAnsi(Native.grpcsharp_auth_context_peer_identity_property_name(this)); + + var propertiesDict = new Dictionary>(); + + var it = Native.grpcsharp_auth_context_property_iterator(this); + IntPtr authPropertyPtr = IntPtr.Zero; + while ((authPropertyPtr = Native.grpcsharp_auth_property_iterator_next(ref it)) != IntPtr.Zero) + { + var authProperty = PtrToAuthProperty(authPropertyPtr); + + if (!propertiesDict.ContainsKey(authProperty.Name)) + { + propertiesDict[authProperty.Name] = new List(); + } + propertiesDict[authProperty.Name].Add(authProperty); + } + + return new AuthContext(peerIdentityPropertyName, propertiesDict); + } + + protected override bool ReleaseHandle() + { + Native.grpcsharp_auth_context_release(handle); + return true; + } + + private AuthProperty PtrToAuthProperty(IntPtr authPropertyPtr) + { + #pragma warning disable 0618 + // We need to use the obsolete non-generic version of Marshal.PtrToStructure, because the generic version is not available in net45 + var nativeAuthProperty = (NativeAuthProperty) Marshal.PtrToStructure(authPropertyPtr, typeof(NativeAuthProperty)); + #pragma warning restore 0618 + var name = Marshal.PtrToStringAnsi(nativeAuthProperty.Name); + var valueBytes = new byte[(int) nativeAuthProperty.ValueLength]; + Marshal.Copy(nativeAuthProperty.Value, valueBytes, 0, (int)nativeAuthProperty.ValueLength); + return AuthProperty.CreateUnsafe(name, valueBytes); + } + + /// + /// grpc_auth_property + /// + internal struct NativeAuthProperty + { + public IntPtr Name; + public IntPtr Value; + public UIntPtr ValueLength; + } + + /// + /// grpc_auth_property_iterator + /// + internal struct NativeAuthPropertyIterator + { + public IntPtr AuthContext; + public UIntPtr Index; + public IntPtr Name; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs new file mode 100644 index 00000000..025f93e8 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs @@ -0,0 +1,191 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Runtime.InteropServices; +using System.Text; +using Grpc.Core; +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + internal interface IOpCompletionCallback + { + void OnComplete(bool success); + } + + internal interface IBufferReader + { + int? TotalLength { get; } + + bool TryGetNextSlice(out Slice slice); + } + + /// + /// grpcsharp_batch_context + /// + internal class BatchContextSafeHandle : SafeHandleZeroIsInvalid, IOpCompletionCallback, IPooledObject, IBufferReader + { + static readonly NativeMethods Native = NativeMethods.Get(); + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + + Action returnToPoolAction; + CompletionCallbackData completionCallbackData; + + private BatchContextSafeHandle() + { + } + + public static BatchContextSafeHandle Create() + { + var ctx = Native.grpcsharp_batch_context_create(); + return ctx; + } + + public IntPtr Handle + { + get + { + return handle; + } + } + + public void SetReturnToPoolAction(Action returnAction) + { + GrpcPreconditions.CheckState(returnToPoolAction == null); + returnToPoolAction = returnAction; + } + + public void SetCompletionCallback(BatchCompletionDelegate callback, object state) + { + GrpcPreconditions.CheckState(completionCallbackData.Callback == null); + GrpcPreconditions.CheckNotNull(callback, nameof(callback)); + completionCallbackData = new CompletionCallbackData(callback, state); + } + + // Gets data of recv_initial_metadata completion. + public Metadata GetReceivedInitialMetadata() + { + IntPtr metadataArrayPtr = Native.grpcsharp_batch_context_recv_initial_metadata(this); + return MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr); + } + + // Gets data of recv_status_on_client completion. + public ClientSideStatus GetReceivedStatusOnClient() + { + UIntPtr detailsLength; + IntPtr detailsPtr = Native.grpcsharp_batch_context_recv_status_on_client_details(this, out detailsLength); + string details = MarshalUtils.PtrToStringUTF8(detailsPtr, (int)detailsLength.ToUInt32()); + string debugErrorString = Marshal.PtrToStringAnsi(Native.grpcsharp_batch_context_recv_status_on_client_error_string(this)); + var status = new Status(Native.grpcsharp_batch_context_recv_status_on_client_status(this), details, debugErrorString != null ? new CoreErrorDetailException(debugErrorString) : null); + + IntPtr metadataArrayPtr = Native.grpcsharp_batch_context_recv_status_on_client_trailing_metadata(this); + var metadata = MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr); + + return new ClientSideStatus(status, metadata); + } + + public IBufferReader GetReceivedMessageReader() + { + return this; + } + + // Gets data of receive_close_on_server completion. + public bool GetReceivedCloseOnServerCancelled() + { + return Native.grpcsharp_batch_context_recv_close_on_server_cancelled(this) != 0; + } + + public void Recycle() + { + if (returnToPoolAction != null) + { + Native.grpcsharp_batch_context_reset(this); + + var origReturnAction = returnToPoolAction; + // Not clearing all the references to the pool could prevent garbage collection of the pool object + // and thus cause memory leaks. + returnToPoolAction = null; + origReturnAction(this); + } + else + { + Dispose(); + } + } + + protected override bool ReleaseHandle() + { + Native.grpcsharp_batch_context_destroy(handle); + return true; + } + + void IOpCompletionCallback.OnComplete(bool success) + { + try + { + completionCallbackData.Callback(success, this, completionCallbackData.State); + } + catch (Exception e) + { + Logger.Error(e, "Exception occurred while invoking batch completion delegate."); + } + finally + { + completionCallbackData = default(CompletionCallbackData); + Recycle(); + } + } + + int? IBufferReader.TotalLength + { + get + { + var len = Native.grpcsharp_batch_context_recv_message_length(this); + return len != new IntPtr(-1) ? (int?) len : null; + } + } + + bool IBufferReader.TryGetNextSlice(out Slice slice) + { + UIntPtr sliceLen; + IntPtr sliceDataPtr; + + if (0 == Native.grpcsharp_batch_context_recv_message_next_slice_peek(this, out sliceLen, out sliceDataPtr)) + { + slice = default(Slice); + return false; + } + slice = new Slice(sliceDataPtr, (int) sliceLen); + return true; + } + + struct CompletionCallbackData + { + public CompletionCallbackData(BatchCompletionDelegate callback, object state) + { + this.Callback = callback; + this.State = state; + } + + public BatchCompletionDelegate Callback { get; } + public object State { get; } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/CStringSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CStringSafeHandle.cs new file mode 100644 index 00000000..c0d9d8a1 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CStringSafeHandle.cs @@ -0,0 +1,44 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace Grpc.Core.Internal +{ + /// + /// Owned char* object. + /// + internal class CStringSafeHandle : SafeHandleZeroIsInvalid + { + static readonly NativeMethods Native = NativeMethods.Get(); + + private CStringSafeHandle() + { + } + + public string GetValue() + { + return Marshal.PtrToStringAnsi(handle); + } + + protected override bool ReleaseHandle() + { + Native.gprsharp_free(handle); + return true; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs new file mode 100644 index 00000000..ef280593 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs @@ -0,0 +1,45 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +namespace Grpc.Core.Internal +{ + /// + /// grpc_call_credentials from grpc/grpc_security.h + /// + internal class CallCredentialsSafeHandle : SafeHandleZeroIsInvalid + { + static readonly NativeMethods Native = NativeMethods.Get(); + + private CallCredentialsSafeHandle() + { + } + + public static CallCredentialsSafeHandle CreateComposite(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2) + { + return Native.grpcsharp_composite_call_credentials_create(creds1, creds2); + } + + protected override bool ReleaseHandle() + { + Native.grpcsharp_call_credentials_release(handle); + return true; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/CallError.cs b/src/csharp/Grpc.Core/Internal/CallError.cs new file mode 100644 index 00000000..b35788d8 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CallError.cs @@ -0,0 +1,79 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Runtime.InteropServices; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// grpc_call_error from grpc/grpc.h + /// + internal enum CallError + { + /* everything went ok */ + OK = 0, + /* something failed, we don't know what */ + Error, + /* this method is not available on the server */ + NotOnServer, + /* this method is not available on the client */ + NotOnClient, + /* this method must be called before server_accept */ + AlreadyAccepted, + /* this method must be called before invoke */ + AlreadyInvoked, + /* this method must be called after invoke */ + NotInvoked, + /* this call is already finished + (writes_done or write_status has already been called) */ + AlreadyFinished, + /* there is already an outstanding read/write operation on the call */ + TooManyOperations, + /* the flags value was illegal for this call */ + InvalidFlags, + /* invalid metadata was passed to this call */ + InvalidMetadata, + /* invalid message was passed to this call */ + InvalidMessage, + /* completion queue for notification has not been registered + with the server */ + NotServerCompletionQueue, + /* this batch of operations leads to more operations than allowed */ + BatchTooBig, + /* payload type requested is not the type registered */ + PayloadTypeMismatch, + /* completion queue has been shutdown */ + CompletionQueueShutdown + } + + internal static class CallErrorExtensions + { + /// + /// Checks the call API invocation's result is OK. + /// + public static void CheckOk(this CallError callError) + { + if (callError != CallError.OK) + { + throw new InvalidOperationException("Call error: " + callError); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/CallOptionsExtensions.cs b/src/csharp/Grpc.Core/Internal/CallOptionsExtensions.cs new file mode 100644 index 00000000..24bc227c --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CallOptionsExtensions.cs @@ -0,0 +1,57 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + internal static class CallOptionsExtensions + { + /// + /// Returns a new instance of with + /// all previously unset values set to their defaults and deadline and cancellation + /// token propagated when appropriate. + /// + internal static CallOptions Normalize(this CallOptions options) + { + var newOptions = options; + // silently ignore the context propagation token if it wasn't produced by "us" + var propagationTokenImpl = options.PropagationToken.AsImplOrNull(); + if (propagationTokenImpl != null) + { + if (propagationTokenImpl.Options.IsPropagateDeadline) + { + GrpcPreconditions.CheckArgument(!newOptions.Deadline.HasValue, + "Cannot propagate deadline from parent call. The deadline has already been set explicitly."); + newOptions = newOptions.WithDeadline(propagationTokenImpl.ParentDeadline); + } + if (propagationTokenImpl.Options.IsPropagateCancellation) + { + GrpcPreconditions.CheckArgument(!newOptions.CancellationToken.CanBeCanceled, + "Cannot propagate cancellation token from parent call. The cancellation token has already been set to a non-default value."); + newOptions = newOptions.WithCancellationToken(propagationTokenImpl.ParentCancellationToken); + } + } + + newOptions = newOptions.WithHeaders(newOptions.Headers ?? Metadata.Empty); + newOptions = newOptions.WithDeadline(newOptions.Deadline ?? DateTime.MaxValue); + return newOptions; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs new file mode 100644 index 00000000..f5ee50be --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs @@ -0,0 +1,263 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Text; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Core.Profiling; +using System.Buffers; + +namespace Grpc.Core.Internal +{ + /// + /// grpc_call from grpc/grpc.h + /// + internal class CallSafeHandle : SafeHandleZeroIsInvalid, INativeCall + { + public static readonly CallSafeHandle NullInstance = new CallSafeHandle(); + static readonly NativeMethods Native = NativeMethods.Get(); + + // Completion handlers are pre-allocated to avoid unnecessary delegate allocations. + // The "state" field is used to store the actual callback to invoke. + static readonly BatchCompletionDelegate CompletionHandler_IUnaryResponseClientCallback = + (success, context, state) => ((IUnaryResponseClientCallback)state).OnUnaryResponseClient(success, context.GetReceivedStatusOnClient(), context.GetReceivedMessageReader(), context.GetReceivedInitialMetadata()); + static readonly BatchCompletionDelegate CompletionHandler_IReceivedStatusOnClientCallback = + (success, context, state) => ((IReceivedStatusOnClientCallback)state).OnReceivedStatusOnClient(success, context.GetReceivedStatusOnClient()); + static readonly BatchCompletionDelegate CompletionHandler_IReceivedMessageCallback = + (success, context, state) => ((IReceivedMessageCallback)state).OnReceivedMessage(success, context.GetReceivedMessageReader()); + static readonly BatchCompletionDelegate CompletionHandler_IReceivedResponseHeadersCallback = + (success, context, state) => ((IReceivedResponseHeadersCallback)state).OnReceivedResponseHeaders(success, context.GetReceivedInitialMetadata()); + static readonly BatchCompletionDelegate CompletionHandler_ISendCompletionCallback = + (success, context, state) => ((ISendCompletionCallback)state).OnSendCompletion(success); + static readonly BatchCompletionDelegate CompletionHandler_ISendStatusFromServerCompletionCallback = + (success, context, state) => ((ISendStatusFromServerCompletionCallback)state).OnSendStatusFromServerCompletion(success); + static readonly BatchCompletionDelegate CompletionHandler_IReceivedCloseOnServerCallback = + (success, context, state) => ((IReceivedCloseOnServerCallback)state).OnReceivedCloseOnServer(success, context.GetReceivedCloseOnServerCancelled()); + + const uint GRPC_WRITE_BUFFER_HINT = 1; + CompletionQueueSafeHandle completionQueue; + + private CallSafeHandle() + { + } + + public void Initialize(CompletionQueueSafeHandle completionQueue) + { + this.completionQueue = completionQueue; + } + + public void SetCredentials(CallCredentialsSafeHandle credentials) + { + Native.grpcsharp_call_set_credentials(this, credentials).CheckOk(); + } + + public void StartUnary(IUnaryResponseClientCallback callback, SliceBufferSafeHandle payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) + { + using (completionQueue.NewScope()) + { + var ctx = completionQueue.CompletionRegistry.RegisterBatchCompletion(CompletionHandler_IUnaryResponseClientCallback, callback); + Native.grpcsharp_call_start_unary(this, ctx, payload, writeFlags, metadataArray, callFlags) + .CheckOk(); + } + } + + public void StartUnary(BatchContextSafeHandle ctx, SliceBufferSafeHandle payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) + { + Native.grpcsharp_call_start_unary(this, ctx, payload, writeFlags, metadataArray, callFlags) + .CheckOk(); + } + + public void StartClientStreaming(IUnaryResponseClientCallback callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags) + { + using (completionQueue.NewScope()) + { + var ctx = completionQueue.CompletionRegistry.RegisterBatchCompletion(CompletionHandler_IUnaryResponseClientCallback, callback); + Native.grpcsharp_call_start_client_streaming(this, ctx, metadataArray, callFlags).CheckOk(); + } + } + + public void StartServerStreaming(IReceivedStatusOnClientCallback callback, SliceBufferSafeHandle payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags) + { + using (completionQueue.NewScope()) + { + var ctx = completionQueue.CompletionRegistry.RegisterBatchCompletion(CompletionHandler_IReceivedStatusOnClientCallback, callback); + Native.grpcsharp_call_start_server_streaming(this, ctx, payload, writeFlags, metadataArray, callFlags).CheckOk(); + } + } + + public void StartDuplexStreaming(IReceivedStatusOnClientCallback callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags) + { + using (completionQueue.NewScope()) + { + var ctx = completionQueue.CompletionRegistry.RegisterBatchCompletion(CompletionHandler_IReceivedStatusOnClientCallback, callback); + Native.grpcsharp_call_start_duplex_streaming(this, ctx, metadataArray, callFlags).CheckOk(); + } + } + + public void StartSendMessage(ISendCompletionCallback callback, SliceBufferSafeHandle payload, WriteFlags writeFlags, bool sendEmptyInitialMetadata) + { + using (completionQueue.NewScope()) + { + var ctx = completionQueue.CompletionRegistry.RegisterBatchCompletion(CompletionHandler_ISendCompletionCallback, callback); + Native.grpcsharp_call_send_message(this, ctx, payload, writeFlags, sendEmptyInitialMetadata ? 1 : 0).CheckOk(); + } + } + + public void StartSendCloseFromClient(ISendCompletionCallback callback) + { + using (completionQueue.NewScope()) + { + var ctx = completionQueue.CompletionRegistry.RegisterBatchCompletion(CompletionHandler_ISendCompletionCallback, callback); + Native.grpcsharp_call_send_close_from_client(this, ctx).CheckOk(); + } + } + + public void StartSendStatusFromServer(ISendStatusFromServerCompletionCallback callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, + SliceBufferSafeHandle optionalPayload, WriteFlags writeFlags) + { + using (completionQueue.NewScope()) + { + var ctx = completionQueue.CompletionRegistry.RegisterBatchCompletion(CompletionHandler_ISendStatusFromServerCompletionCallback, callback); + + const int MaxStackAllocBytes = 256; + int maxBytes = MarshalUtils.GetMaxByteCountUTF8(status.Detail); + if (maxBytes > MaxStackAllocBytes) + { + // pay the extra to get the *actual* size; this could mean that + // it ends up fitting on the stack after all, but even if not + // it will mean that we ask for a *much* smaller buffer + maxBytes = MarshalUtils.GetByteCountUTF8(status.Detail); + } + + unsafe + { + if (maxBytes <= MaxStackAllocBytes) + { // for small status, we can encode on the stack without touching arrays + // note: if init-locals is disabled, it would be more efficient + // to just stackalloc[MaxStackAllocBytes]; but by default, since we + // expect this to be small and it needs to wipe, just use maxBytes + byte* ptr = stackalloc byte[maxBytes]; + int statusBytes = MarshalUtils.GetBytesUTF8(status.Detail, ptr, maxBytes); + Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, new IntPtr(ptr), new UIntPtr((ulong)statusBytes), metadataArray, sendEmptyInitialMetadata ? 1 : 0, + optionalPayload, writeFlags).CheckOk(); + } + else + { // for larger status (rare), rent a buffer from the pool and + // use that for encoding + var statusBuffer = ArrayPool.Shared.Rent(maxBytes); + try + { + fixed (byte* ptr = statusBuffer) + { + int statusBytes = MarshalUtils.GetBytesUTF8(status.Detail, ptr, maxBytes); + Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, new IntPtr(ptr), new UIntPtr((ulong)statusBytes), metadataArray, sendEmptyInitialMetadata ? 1 : 0, + optionalPayload, writeFlags).CheckOk(); + } + } + finally + { + ArrayPool.Shared.Return(statusBuffer); + } + } + } + } + } + + public void StartReceiveMessage(IReceivedMessageCallback callback) + { + using (completionQueue.NewScope()) + { + var ctx = completionQueue.CompletionRegistry.RegisterBatchCompletion(CompletionHandler_IReceivedMessageCallback, callback); + Native.grpcsharp_call_recv_message(this, ctx).CheckOk(); + } + } + + public void StartReceiveInitialMetadata(IReceivedResponseHeadersCallback callback) + { + using (completionQueue.NewScope()) + { + var ctx = completionQueue.CompletionRegistry.RegisterBatchCompletion(CompletionHandler_IReceivedResponseHeadersCallback, callback); + Native.grpcsharp_call_recv_initial_metadata(this, ctx).CheckOk(); + } + } + + public void StartServerSide(IReceivedCloseOnServerCallback callback) + { + using (completionQueue.NewScope()) + { + var ctx = completionQueue.CompletionRegistry.RegisterBatchCompletion(CompletionHandler_IReceivedCloseOnServerCallback, callback); + Native.grpcsharp_call_start_serverside(this, ctx).CheckOk(); + } + } + + public void StartSendInitialMetadata(ISendCompletionCallback callback, MetadataArraySafeHandle metadataArray) + { + using (completionQueue.NewScope()) + { + var ctx = completionQueue.CompletionRegistry.RegisterBatchCompletion(CompletionHandler_ISendCompletionCallback, callback); + Native.grpcsharp_call_send_initial_metadata(this, ctx, metadataArray).CheckOk(); + } + } + + public void Cancel() + { + Native.grpcsharp_call_cancel(this).CheckOk(); + } + + public void CancelWithStatus(Status status) + { + Native.grpcsharp_call_cancel_with_status(this, status.StatusCode, status.Detail).CheckOk(); + } + + public string GetPeer() + { + using (var cstring = Native.grpcsharp_call_get_peer(this)) + { + return cstring.GetValue(); + } + } + + public AuthContextSafeHandle GetAuthContext() + { + return Native.grpcsharp_call_auth_context(this); + } + + protected override bool ReleaseHandle() + { + Native.grpcsharp_call_destroy(handle); + return true; + } + + private static uint GetFlags(bool buffered) + { + return buffered ? 0 : GRPC_WRITE_BUFFER_HINT; + } + + /// + /// Only for testing. + /// + public static CallSafeHandle CreateFake(IntPtr ptr, CompletionQueueSafeHandle cq) + { + var call = new CallSafeHandle(); + call.SetHandle(ptr); + call.Initialize(cq); + return call; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs new file mode 100644 index 00000000..c0df59f0 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs @@ -0,0 +1,59 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace Grpc.Core.Internal +{ + /// + /// grpc_channel_args from grpc/grpc.h + /// + internal class ChannelArgsSafeHandle : SafeHandleZeroIsInvalid + { + static readonly NativeMethods Native = NativeMethods.Get(); + + private ChannelArgsSafeHandle() + { + } + + public static ChannelArgsSafeHandle CreateNull() + { + return new ChannelArgsSafeHandle(); + } + + public static ChannelArgsSafeHandle Create(int size) + { + return Native.grpcsharp_channel_args_create(new UIntPtr((uint)size)); + } + + public void SetString(int index, string key, string value) + { + Native.grpcsharp_channel_args_set_string(this, new UIntPtr((uint)index), key, value); + } + + public void SetInteger(int index, string key, int value) + { + Native.grpcsharp_channel_args_set_integer(this, new UIntPtr((uint)index), key, value); + } + + protected override bool ReleaseHandle() + { + Native.grpcsharp_channel_args_destroy(handle); + return true; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs new file mode 100644 index 00000000..d4f50344 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs @@ -0,0 +1,64 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +namespace Grpc.Core.Internal +{ + /// + /// grpc_channel_credentials from grpc/grpc_security.h + /// + internal class ChannelCredentialsSafeHandle : SafeHandleZeroIsInvalid + { + static readonly NativeMethods Native = NativeMethods.Get(); + + private ChannelCredentialsSafeHandle() + { + } + + public static ChannelCredentialsSafeHandle CreateNullCredentials() + { + var creds = new ChannelCredentialsSafeHandle(); + creds.SetHandle(IntPtr.Zero); + return creds; + } + + public static ChannelCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, KeyCertificatePair keyCertPair, IntPtr verifyPeerCallbackTag) + { + if (keyCertPair != null) + { + return Native.grpcsharp_ssl_credentials_create(pemRootCerts, keyCertPair.CertificateChain, keyCertPair.PrivateKey, verifyPeerCallbackTag); + } + else + { + return Native.grpcsharp_ssl_credentials_create(pemRootCerts, null, null, verifyPeerCallbackTag); + } + } + + public static ChannelCredentialsSafeHandle CreateComposite(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds) + { + return Native.grpcsharp_composite_channel_credentials_create(channelCreds, callCreds); + } + + protected override bool ReleaseHandle() + { + Native.grpcsharp_channel_credentials_release(handle); + return true; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs new file mode 100644 index 00000000..cd5f8ed9 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs @@ -0,0 +1,88 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core.Profiling; + +namespace Grpc.Core.Internal +{ + /// + /// grpc_channel from grpc/grpc.h + /// + internal class ChannelSafeHandle : SafeHandleZeroIsInvalid + { + static readonly NativeMethods Native = NativeMethods.Get(); + + private ChannelSafeHandle() + { + } + + public static ChannelSafeHandle CreateInsecure(string target, ChannelArgsSafeHandle channelArgs) + { + // Increment reference count for the native gRPC environment to make sure we don't do grpc_shutdown() before destroying the server handle. + // Doing so would make object finalizer crash if we end up abandoning the handle. + GrpcEnvironment.GrpcNativeInit(); + return Native.grpcsharp_insecure_channel_create(target, channelArgs); + } + + public static ChannelSafeHandle CreateSecure(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs) + { + // Increment reference count for the native gRPC environment to make sure we don't do grpc_shutdown() before destroying the server handle. + // Doing so would make object finalizer crash if we end up abandoning the handle. + GrpcEnvironment.GrpcNativeInit(); + return Native.grpcsharp_secure_channel_create(credentials, target, channelArgs); + } + + public CallSafeHandle CreateCall(CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline, CallCredentialsSafeHandle credentials) + { + var result = Native.grpcsharp_channel_create_call(this, parentCall, propagationMask, cq, method, host, deadline); + if (credentials != null) + { + result.SetCredentials(credentials); + } + result.Initialize(cq); + return result; + } + + public ChannelState CheckConnectivityState(bool tryToConnect) + { + return Native.grpcsharp_channel_check_connectivity_state(this, tryToConnect ? 1 : 0); + } + + public void WatchConnectivityState(ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq, BatchCompletionDelegate callback, object callbackState) + { + var ctx = cq.CompletionRegistry.RegisterBatchCompletion(callback, callbackState); + Native.grpcsharp_channel_watch_connectivity_state(this, lastObservedState, deadline, cq, ctx); + } + + public string GetTarget() + { + using (var cstring = Native.grpcsharp_channel_get_target(this)) + { + return cstring.GetValue(); + } + } + + protected override bool ReleaseHandle() + { + Native.grpcsharp_channel_destroy(handle); + GrpcEnvironment.GrpcNativeShutdown(); + return true; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ClientRequestStream.cs b/src/csharp/Grpc.Core/Internal/ClientRequestStream.cs new file mode 100644 index 00000000..aa7d6fae --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ClientRequestStream.cs @@ -0,0 +1,65 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion +using System; +using System.Threading.Tasks; +using Grpc.Core.Internal; + +namespace Grpc.Core.Internal +{ + /// + /// Writes requests asynchronously to an underlying AsyncCall object. + /// + internal class ClientRequestStream : IClientStreamWriter + { + readonly AsyncCall call; + WriteOptions writeOptions; + + public ClientRequestStream(AsyncCall call) + { + this.call = call; + this.writeOptions = call.Details.Options.WriteOptions; + } + + public Task WriteAsync(TRequest message) + { + return call.SendMessageAsync(message, GetWriteFlags()); + } + + public Task CompleteAsync() + { + return call.SendCloseFromClientAsync(); + } + + public WriteOptions WriteOptions + { + get + { + return this.writeOptions; + } + + set + { + writeOptions = value; + } + } + + private WriteFlags GetWriteFlags() + { + var options = writeOptions; + return options != null ? options.Flags : default(WriteFlags); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs b/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs new file mode 100644 index 00000000..ff73b26d --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ClientResponseStream.cs @@ -0,0 +1,71 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Grpc.Core.Internal +{ + internal class ClientResponseStream : IAsyncStreamReader + where TRequest : class + where TResponse : class + { + readonly AsyncCall call; + TResponse current; + + public ClientResponseStream(AsyncCall call) + { + this.call = call; + } + + public TResponse Current + { + get + { + if (current == null) + { + throw new InvalidOperationException("No current element is available."); + } + return current; + } + } + + public async Task MoveNext(CancellationToken token) + { + using (call.RegisterCancellationCallbackForToken(token)) + { + var result = await call.ReadMessageAsync().ConfigureAwait(false); + this.current = result; + + if (result == null) + { + await call.StreamingResponseCallFinishedTask.ConfigureAwait(false); + return false; + } + return true; + } + } + + public void Dispose() + { + // TODO(jtattermusch): implement the semantics of stream disposal. + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ClientSideStatus.cs b/src/csharp/Grpc.Core/Internal/ClientSideStatus.cs new file mode 100644 index 00000000..d19c6538 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ClientSideStatus.cs @@ -0,0 +1,55 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.Core; + +namespace Grpc.Core.Internal +{ + /// + /// Status + metadata received on client side when call finishes. + /// (when receive_status_on_client operation finishes). + /// + internal struct ClientSideStatus + { + readonly Status status; + readonly Metadata trailers; + + public ClientSideStatus(Status status, Metadata trailers) + { + this.status = status; + this.trailers = trailers; + } + + public Status Status + { + get + { + return this.status; + } + } + + public Metadata Trailers + { + get + { + return this.trailers; + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ClockType.cs b/src/csharp/Grpc.Core/Internal/ClockType.cs new file mode 100644 index 00000000..35433913 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ClockType.cs @@ -0,0 +1,38 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +namespace Grpc.Core.Internal +{ + /// + /// gpr_clock_type from grpc/support/time.h + /// + internal enum ClockType + { + /* Monotonic clock */ + Monotonic, + + /* Realtime clock */ + Realtime, + + /* Precise clock good for performance profiling. */ + Precise, + + /* Timespan - the distance between two time points */ + Timespan + } +} diff --git a/src/csharp/Grpc.Core/Internal/CommonPlatformDetection.cs b/src/csharp/Grpc.Core/Internal/CommonPlatformDetection.cs new file mode 100644 index 00000000..56e24b87 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CommonPlatformDetection.cs @@ -0,0 +1,129 @@ +#region Copyright notice and license + +// Copyright 2021 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Grpc.Core.Internal +{ + /// + /// This source file is shared by both Grpc.Core and Grpc.Tools to avoid duplication + /// of platform detection code. + /// + internal static class CommonPlatformDetection + { + public enum OSKind { Unknown, Windows, Linux, MacOSX }; + public enum CpuArchitecture { Unknown, X86, X64, Arm64 }; + + public static OSKind GetOSKind() + { +#if NETSTANDARD || NETCORE + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return OSKind.Windows; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return OSKind.Linux; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return OSKind.MacOSX; + } + else + { + return OSKind.Unknown; + } +#else + var platform = Environment.OSVersion.Platform; + if (platform == PlatformID.Win32NT || platform == PlatformID.Win32S || platform == PlatformID.Win32Windows) + { + return OSKind.Windows; + } + else if (platform == PlatformID.Unix && GetUname() == "Darwin") + { + // PlatformID.MacOSX is never returned, commonly used trick is to identify Mac is by using uname. + return OSKind.MacOSX; + } + else if (platform == PlatformID.Unix) + { + // on legacy .NET Framework, our detection options are limited, so we treat + // all other unix systems as Linux. + return OSKind.Linux; + } + else + { + return OSKind.Unknown; + } +#endif + } + + public static CpuArchitecture GetProcessArchitecture() + { +#if NETSTANDARD || NETCORE + switch (RuntimeInformation.ProcessArchitecture) + { + case Architecture.X86: + return CpuArchitecture.X86; + case Architecture.X64: + return CpuArchitecture.X64; + case Architecture.Arm64: + return CpuArchitecture.Arm64; + // We do not support other architectures, + // so we simply return "unrecognized". + default: + return CpuArchitecture.Unknown; + } +#else + // on legacy .NET Framework, RuntimeInformation is not available + // but our choice of supported architectures there + // is also very limited, so we simply take our best guess. + return Environment.Is64BitProcess ? CpuArchitecture.X64 : CpuArchitecture.X86; +#endif + } + + [DllImport("libc")] + static extern int uname(IntPtr buf); + + // This code is copied from Grpc.Core/PlatformApis.cs + static string GetUname() + { + var buffer = Marshal.AllocHGlobal(8192); + try + { + if (uname(buffer) == 0) + { + return Marshal.PtrToStringAnsi(buffer); + } + return string.Empty; + } + catch + { + return string.Empty; + } + finally + { + if (buffer != IntPtr.Zero) + { + Marshal.FreeHGlobal(buffer); + } + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs b/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs new file mode 100644 index 00000000..4c1b50b7 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs @@ -0,0 +1,59 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Runtime.InteropServices; + +namespace Grpc.Core.Internal +{ + /// + /// grpc_event from grpc/grpc.h + /// + [StructLayout(LayoutKind.Sequential)] + internal struct CompletionQueueEvent + { + static readonly NativeMethods Native = NativeMethods.Get(); + + public CompletionType type; + public int success; + public IntPtr tag; + + internal static int NativeSize + { + get + { + return Native.grpcsharp_sizeof_grpc_event(); + } + } + + /// + /// grpc_completion_type from grpc/grpc.h + /// + internal enum CompletionType + { + /* Shutting down */ + Shutdown, + + /* No event before timeout */ + Timeout, + + /* operation completion */ + OpComplete + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs new file mode 100644 index 00000000..6103ba99 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs @@ -0,0 +1,137 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Grpc.Core.Profiling; + +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// grpc_completion_queue from grpc/grpc.h + /// + internal class CompletionQueueSafeHandle : SafeHandleZeroIsInvalid + { + static readonly NativeMethods Native = NativeMethods.Get(); + + AtomicCounter shutdownRefcount; + CompletionRegistry completionRegistry; + + private CompletionQueueSafeHandle() + { + } + + /// + /// Create a completion queue that can only be used for Pluck operations. + /// + public static CompletionQueueSafeHandle CreateSync() + { + return Native.grpcsharp_completion_queue_create_sync(); + } + + /// + /// Create a completion queue that can only be used for Next operations. + /// + public static CompletionQueueSafeHandle CreateAsync(CompletionRegistry completionRegistry) + { + var cq = Native.grpcsharp_completion_queue_create_async(); + cq.completionRegistry = completionRegistry; + cq.shutdownRefcount = new AtomicCounter(1); + return cq; + } + + public CompletionQueueEvent Next() + { + return Native.grpcsharp_completion_queue_next(this); + } + + public CompletionQueueEvent Pluck(IntPtr tag) + { + return Native.grpcsharp_completion_queue_pluck(this, tag); + } + + /// + /// Creates a new usage scope for this completion queue. Once successfully created, + /// the completion queue won't be shutdown before scope.Dispose() is called. + /// + public UsageScope NewScope() + { + return new UsageScope(this); + } + + public void Shutdown() + { + DecrementShutdownRefcount(); + } + + /// + /// Completion registry associated with this completion queue. + /// Doesn't need to be set if only using Pluck() operations. + /// + public CompletionRegistry CompletionRegistry + { + get { return completionRegistry; } + } + + protected override bool ReleaseHandle() + { + Native.grpcsharp_completion_queue_destroy(handle); + return true; + } + + private void DecrementShutdownRefcount() + { + if (shutdownRefcount == null || shutdownRefcount.Decrement() == 0) + { + Native.grpcsharp_completion_queue_shutdown(this); + } + } + + private void BeginOp() + { + GrpcPreconditions.CheckNotNull(shutdownRefcount, nameof(shutdownRefcount)); + bool success = false; + shutdownRefcount.IncrementIfNonzero(ref success); + GrpcPreconditions.CheckState(success, "Shutdown has already been called"); + } + + private void EndOp() + { + GrpcPreconditions.CheckNotNull(shutdownRefcount, nameof(shutdownRefcount)); + DecrementShutdownRefcount(); + } + + // Allows declaring BeginOp and EndOp of a completion queue with a using statement. + // Declared as struct for better performance. + public struct UsageScope : IDisposable + { + readonly CompletionQueueSafeHandle cq; + + public UsageScope(CompletionQueueSafeHandle cq) + { + this.cq = cq; + this.cq.BeginOp(); + } + + public void Dispose() + { + cq.EndOp(); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs b/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs new file mode 100644 index 00000000..79d0c914 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CompletionRegistry.cs @@ -0,0 +1,129 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading; +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + internal delegate void BatchCompletionDelegate(bool success, BatchContextSafeHandle ctx, object state); + + internal delegate void RequestCallCompletionDelegate(bool success, RequestCallContextSafeHandle ctx); + + internal class CompletionRegistry + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + + readonly GrpcEnvironment environment; + readonly Func batchContextFactory; + readonly Func requestCallContextFactory; + readonly Dictionary dict = new Dictionary(new IntPtrComparer()); + SpinLock spinLock = new SpinLock(Debugger.IsAttached); + IntPtr lastRegisteredKey; // only for testing + + public CompletionRegistry(GrpcEnvironment environment, Func batchContextFactory, Func requestCallContextFactory) + { + this.environment = GrpcPreconditions.CheckNotNull(environment); + this.batchContextFactory = GrpcPreconditions.CheckNotNull(batchContextFactory); + this.requestCallContextFactory = GrpcPreconditions.CheckNotNull(requestCallContextFactory); + } + + public void Register(IntPtr key, IOpCompletionCallback callback) + { + environment.DebugStats.PendingBatchCompletions.Increment(); + + bool lockTaken = false; + try + { + spinLock.Enter(ref lockTaken); + + dict.Add(key, callback); + this.lastRegisteredKey = key; + } + finally + { + if (lockTaken) spinLock.Exit(); + } + } + + public BatchContextSafeHandle RegisterBatchCompletion(BatchCompletionDelegate callback, object state) + { + var ctx = batchContextFactory(); + ctx.SetCompletionCallback(callback, state); + Register(ctx.Handle, ctx); + return ctx; + } + + public RequestCallContextSafeHandle RegisterRequestCallCompletion(RequestCallCompletionDelegate callback) + { + var ctx = requestCallContextFactory(); + ctx.CompletionCallback = callback; + Register(ctx.Handle, ctx); + return ctx; + } + + public IOpCompletionCallback Extract(IntPtr key) + { + IOpCompletionCallback value = null; + bool lockTaken = false; + try + { + spinLock.Enter(ref lockTaken); + + value = dict[key]; + dict.Remove(key); + } + finally + { + if (lockTaken) spinLock.Exit(); + } + environment.DebugStats.PendingBatchCompletions.Decrement(); + return value; + } + + /// + /// For testing purposes only. NOT threadsafe. + /// + public IntPtr LastRegisteredKey + { + get { return this.lastRegisteredKey; } + } + + /// + /// IntPtr doesn't implement IEquatable{IntPtr} so we need to use custom comparer to avoid boxing. + /// + private class IntPtrComparer : IEqualityComparer + { + public bool Equals(IntPtr x, IntPtr y) + { + return x == y; + } + + public int GetHashCode(IntPtr obj) + { + return obj.GetHashCode(); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ContextPropagationFlags.cs b/src/csharp/Grpc.Core/Internal/ContextPropagationFlags.cs new file mode 100644 index 00000000..11a9c93a --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ContextPropagationFlags.cs @@ -0,0 +1,34 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; + +namespace Grpc.Core.Internal +{ + /// + /// Context propagation flags from grpc/grpc.h. + /// + [Flags] + internal enum ContextPropagationFlags + { + Deadline = 1, + CensusStatsContext = 2, + CensusTracingContext = 4, + Cancellation = 8 + } +} diff --git a/src/csharp/Grpc.Core/Internal/ContextPropagationTokenImpl.cs b/src/csharp/Grpc.Core/Internal/ContextPropagationTokenImpl.cs new file mode 100644 index 00000000..e2528e84 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ContextPropagationTokenImpl.cs @@ -0,0 +1,119 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Threading; + +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Implementation of ContextPropagationToken that carries + /// all fields needed for context propagation by C-core based implementation of gRPC. + /// Instances of ContextPropagationToken that are not of this + /// type will be recognized as "foreign" and will be silently ignored + /// (treated as if null). + /// + internal class ContextPropagationTokenImpl : ContextPropagationToken + { + /// + /// Default propagation mask used by C core. + /// + private const ContextPropagationFlags DefaultCoreMask = (ContextPropagationFlags)0xffff; + + /// + /// Default propagation mask used by C# - we want to propagate deadline + /// and cancellation token by our own means, everything else will be propagated + /// by C core automatically (according to DefaultCoreMask). + /// + internal const ContextPropagationFlags DefaultMask = DefaultCoreMask + & ~ContextPropagationFlags.Deadline & ~ContextPropagationFlags.Cancellation; + + readonly CallSafeHandle parentCall; + readonly DateTime deadline; + readonly CancellationToken cancellationToken; + readonly ContextPropagationOptions options; + + internal ContextPropagationTokenImpl(CallSafeHandle parentCall, DateTime deadline, CancellationToken cancellationToken, ContextPropagationOptions options) + { + this.parentCall = GrpcPreconditions.CheckNotNull(parentCall); + this.deadline = deadline; + this.cancellationToken = cancellationToken; + this.options = options ?? ContextPropagationOptions.Default; + } + + /// + /// Gets the native handle of the parent call. + /// + internal CallSafeHandle ParentCall + { + get + { + return this.parentCall; + } + } + + /// + /// Gets the parent call's deadline. + /// + internal DateTime ParentDeadline + { + get + { + return this.deadline; + } + } + + /// + /// Gets the parent call's cancellation token. + /// + internal CancellationToken ParentCancellationToken + { + get + { + return this.cancellationToken; + } + } + + /// + /// Get the context propagation options. + /// + internal ContextPropagationOptions Options + { + get + { + return this.options; + } + } + } + + internal static class ContextPropagationTokenExtensions + { + /// + /// Converts given ContextPropagationToken to ContextPropagationTokenImpl + /// if possible or returns null. + /// Being able to convert means that the context propagation token is recognized as + /// "ours" (was created by this implementation). + /// + public static ContextPropagationTokenImpl AsImplOrNull(this ContextPropagationToken instanceOrNull) + { + return instanceOrNull as ContextPropagationTokenImpl; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/CoreErrorDetailException.cs b/src/csharp/Grpc.Core/Internal/CoreErrorDetailException.cs new file mode 100644 index 00000000..ca688648 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CoreErrorDetailException.cs @@ -0,0 +1,35 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Runtime.InteropServices; +using System.Threading; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Represents error details provides by C-core's debug_error_string + /// + internal class CoreErrorDetailException : Exception + { + public CoreErrorDetailException(string message) : base(message) + { + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/DebugStats.cs b/src/csharp/Grpc.Core/Internal/DebugStats.cs new file mode 100644 index 00000000..36dd8912 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/DebugStats.cs @@ -0,0 +1,45 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading; + +namespace Grpc.Core.Internal +{ + internal class DebugStats + { + public readonly AtomicCounter PendingBatchCompletions = new AtomicCounter(); + + /// + /// Checks the debug stats and take action for any inconsistency found. + /// + public void CheckOK() + { + var pendingBatchCompletions = PendingBatchCompletions.Count; + if (pendingBatchCompletions != 0) + { + DebugWarning(string.Format("Detected {0} pending batch completions.", pendingBatchCompletions)); + } + } + + private void DebugWarning(string message) + { + throw new Exception("Shutdown check: " + message); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/DefaultCallCredentialsConfigurator.cs b/src/csharp/Grpc.Core/Internal/DefaultCallCredentialsConfigurator.cs new file mode 100644 index 00000000..a2c53a17 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/DefaultCallCredentialsConfigurator.cs @@ -0,0 +1,85 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Creates native call credential objects from instances of CallCredentials. + /// + internal class DefaultCallCredentialsConfigurator : CallCredentialsConfiguratorBase + { + CallCredentialsSafeHandle nativeCredentials; + + public CallCredentialsSafeHandle NativeCredentials => nativeCredentials; + + public override void SetAsyncAuthInterceptorCredentials(object state, AsyncAuthInterceptor interceptor) + { + GrpcPreconditions.CheckState(nativeCredentials == null); + + var plugin = new NativeMetadataCredentialsPlugin(interceptor); + nativeCredentials = plugin.Credentials; + } + + public override void SetCompositeCredentials(object state, IReadOnlyList credentials) + { + GrpcPreconditions.CheckState(nativeCredentials == null); + + GrpcPreconditions.CheckArgument(credentials.Count >= 2); + nativeCredentials = CompositeToNativeRecursive(credentials, 0); + } + + // Recursive descent makes managing lifetime of intermediate CredentialSafeHandle instances easier. + // In practice, we won't usually see composites from more than two credentials anyway. + private CallCredentialsSafeHandle CompositeToNativeRecursive(IReadOnlyList credentials, int startIndex) + { + if (startIndex == credentials.Count - 1) + { + return credentials[startIndex].ToNativeCredentials(); + } + + using (var cred1 = credentials[startIndex].ToNativeCredentials()) + using (var cred2 = CompositeToNativeRecursive(credentials, startIndex + 1)) + { + var nativeComposite = CallCredentialsSafeHandle.CreateComposite(cred1, cred2); + if (nativeComposite.IsInvalid) + { + throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials."); + } + return nativeComposite; + } + } + } + + internal static class CallCredentialsExtensions + { + /// + /// Creates native object for the credentials. + /// + /// The native credentials. + public static CallCredentialsSafeHandle ToNativeCredentials(this CallCredentials credentials) + { + var configurator = new DefaultCallCredentialsConfigurator(); + credentials.InternalPopulateConfiguration(configurator, credentials); + return configurator.NativeCredentials; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/DefaultChannelCredentialsConfigurator.cs b/src/csharp/Grpc.Core/Internal/DefaultChannelCredentialsConfigurator.cs new file mode 100644 index 00000000..c4c044cd --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/DefaultChannelCredentialsConfigurator.cs @@ -0,0 +1,163 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using Grpc.Core.Utils; +using Grpc.Core.Logging; + +namespace Grpc.Core.Internal +{ + /// + /// Creates native call credential objects from instances of ChannelCredentials. + /// + internal class DefaultChannelCredentialsConfigurator : ChannelCredentialsConfiguratorBase + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + + // Native credentials object need to be kept alive once initialized for subchannel sharing to work correctly + // with secure connections. See https://github.com/grpc/grpc/issues/15207. + // We rely on finalizer to clean up the native portion of ChannelCredentialsSafeHandle after the ChannelCredentials + // instance becomes unused. + static readonly ConditionalWeakTable> CachedNativeCredentials = new ConditionalWeakTable>(); + static readonly object StaticLock = new object(); + + bool configured; + ChannelCredentialsSafeHandle nativeCredentials; + + public ChannelCredentialsSafeHandle NativeCredentials => nativeCredentials; + + public override void SetInsecureCredentials(object state) + { + GrpcPreconditions.CheckState(!configured); + // null corresponds to insecure credentials. + configured = true; + nativeCredentials = null; + } + + public override void SetSslCredentials(object state, string rootCertificates, KeyCertificatePair keyCertificatePair, VerifyPeerCallback verifyPeerCallback) + { + GrpcPreconditions.CheckState(!configured); + configured = true; + nativeCredentials = GetOrCreateNativeCredentials((ChannelCredentials) state, + () => CreateNativeSslCredentials(rootCertificates, keyCertificatePair, verifyPeerCallback)); + } + + public override void SetCompositeCredentials(object state, ChannelCredentials channelCredentials, CallCredentials callCredentials) + { + GrpcPreconditions.CheckState(!configured); + configured = true; + nativeCredentials = GetOrCreateNativeCredentials((ChannelCredentials) state, + () => CreateNativeCompositeCredentials(channelCredentials, callCredentials)); + } + + private ChannelCredentialsSafeHandle CreateNativeSslCredentials(string rootCertificates, KeyCertificatePair keyCertificatePair, VerifyPeerCallback verifyPeerCallback) + { + IntPtr verifyPeerCallbackTag = IntPtr.Zero; + if (verifyPeerCallback != null) + { + verifyPeerCallbackTag = new VerifyPeerCallbackRegistration(verifyPeerCallback).CallbackRegistration.Tag; + } + return ChannelCredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair, verifyPeerCallbackTag); + } + + private ChannelCredentialsSafeHandle CreateNativeCompositeCredentials(ChannelCredentials channelCredentials, CallCredentials callCredentials) + { + using (var callCreds = callCredentials.ToNativeCredentials()) + { + var nativeComposite = ChannelCredentialsSafeHandle.CreateComposite(channelCredentials.ToNativeCredentials(), callCreds); + if (nativeComposite.IsInvalid) + { + throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials."); + } + return nativeComposite; + } + } + + private ChannelCredentialsSafeHandle GetOrCreateNativeCredentials(ChannelCredentials key, Func nativeCredentialsFactory) + { + Lazy lazyValue; + lock (StaticLock) { + if (!CachedNativeCredentials.TryGetValue(key, out lazyValue)) + { + lazyValue = new Lazy(nativeCredentialsFactory); + CachedNativeCredentials.Add(key, lazyValue); + } + } + return lazyValue.Value; + } + + private class VerifyPeerCallbackRegistration + { + readonly VerifyPeerCallback verifyPeerCallback; + readonly NativeCallbackRegistration callbackRegistration; + + public VerifyPeerCallbackRegistration(VerifyPeerCallback verifyPeerCallback) + { + this.verifyPeerCallback = verifyPeerCallback; + this.callbackRegistration = NativeCallbackDispatcher.RegisterCallback(HandleUniversalCallback); + } + + public NativeCallbackRegistration CallbackRegistration => callbackRegistration; + + private int HandleUniversalCallback(IntPtr arg0, IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5) + { + return VerifyPeerCallbackHandler(arg0, arg1, arg2 != IntPtr.Zero); + } + + private int VerifyPeerCallbackHandler(IntPtr targetName, IntPtr peerPem, bool isDestroy) + { + if (isDestroy) + { + this.callbackRegistration.Dispose(); + return 0; + } + + try + { + var context = new VerifyPeerContext(Marshal.PtrToStringAnsi(targetName), Marshal.PtrToStringAnsi(peerPem)); + + return this.verifyPeerCallback(context) ? 0 : 1; + } + catch (Exception e) + { + // eat the exception, we must not throw when inside callback from native code. + Logger.Error(e, "Exception occurred while invoking verify peer callback handler."); + // Return validation failure in case of exception. + return 1; + } + } + } + } + + internal static class ChannelCredentialsExtensions + { + /// + /// Creates native object for the credentials. + /// + /// The native credentials. + public static ChannelCredentialsSafeHandle ToNativeCredentials(this ChannelCredentials credentials) + { + var configurator = new DefaultChannelCredentialsConfigurator(); + credentials.InternalPopulateConfiguration(configurator, credentials); + return configurator.NativeCredentials; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/DefaultDeserializationContext.cs b/src/csharp/Grpc.Core/Internal/DefaultDeserializationContext.cs new file mode 100644 index 00000000..7b5997b3 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/DefaultDeserializationContext.cs @@ -0,0 +1,76 @@ +#region Copyright notice and license + +// Copyright 2018 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Buffers; +using System.Threading; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + internal class DefaultDeserializationContext : DeserializationContext + { + static readonly ThreadLocal threadLocalInstance = + new ThreadLocal(() => new DefaultDeserializationContext(), false); + + IBufferReader bufferReader; + int payloadLength; + ReusableSliceBuffer cachedSliceBuffer = new ReusableSliceBuffer(); + + public DefaultDeserializationContext() + { + Reset(); + } + + public override int PayloadLength => payloadLength; + + public override byte[] PayloadAsNewBuffer() + { + var buffer = new byte[payloadLength]; + PayloadAsReadOnlySequence().CopyTo(buffer); + return buffer; + } + + public override ReadOnlySequence PayloadAsReadOnlySequence() + { + var sequence = cachedSliceBuffer.PopulateFrom(bufferReader); + GrpcPreconditions.CheckState(sequence.Length == payloadLength); + return sequence; + } + + public void Initialize(IBufferReader bufferReader) + { + this.bufferReader = GrpcPreconditions.CheckNotNull(bufferReader); + this.payloadLength = bufferReader.TotalLength.Value; // payload must not be null + } + + public void Reset() + { + this.bufferReader = null; + this.payloadLength = 0; + this.cachedSliceBuffer.Invalidate(); + } + + public static DefaultDeserializationContext GetInitializedThreadLocal(IBufferReader bufferReader) + { + var instance = threadLocalInstance.Value; + instance.Initialize(bufferReader); + return instance; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/DefaultObjectPool.cs b/src/csharp/Grpc.Core/Internal/DefaultObjectPool.cs new file mode 100644 index 00000000..e98e9cae --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/DefaultObjectPool.cs @@ -0,0 +1,205 @@ +#region Copyright notice and license + +// Copyright 2017 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading; +using System.Collections.Generic; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Pool of objects that combines a shared pool and a thread local pool. + /// + internal class DefaultObjectPool : IObjectPool + where T : class, IPooledObject + { + readonly object myLock = new object(); + readonly Action returnAction; + readonly Func itemFactory; + + // Queue shared between threads, access needs to be synchronized. + readonly Queue sharedQueue; + readonly int sharedCapacity; + + readonly ThreadLocal threadLocalData; + readonly int threadLocalCapacity; + readonly int rentLimit; + + bool disposed; + + /// + /// Initializes a new instance of DefaultObjectPool with given shared capacity and thread local capacity. + /// Thread local capacity should be significantly smaller than the shared capacity as we don't guarantee immediately + /// disposing the objects in the thread local pool after this pool is disposed (they will eventually be garbage collected + /// after the thread that owns them has finished). + /// On average, the shared pool will only be accessed approx. once for every threadLocalCapacity / 2 rent or lease + /// operations. + /// + public DefaultObjectPool(Func itemFactory, int sharedCapacity, int threadLocalCapacity) + { + GrpcPreconditions.CheckArgument(sharedCapacity >= 0); + GrpcPreconditions.CheckArgument(threadLocalCapacity >= 0); + this.returnAction = Return; + this.itemFactory = GrpcPreconditions.CheckNotNull(itemFactory, nameof(itemFactory)); + this.sharedQueue = new Queue(sharedCapacity); + this.sharedCapacity = sharedCapacity; + this.threadLocalData = new ThreadLocal(() => new ThreadLocalData(threadLocalCapacity), false); + this.threadLocalCapacity = threadLocalCapacity; + this.rentLimit = threadLocalCapacity != 1 ? threadLocalCapacity / 2 : 1; + } + + /// + /// Leases an item from the pool or creates a new instance if the pool is empty. + /// Attempts to retrieve the item from the thread local pool first. + /// If the thread local pool is empty, the item is taken from the shared pool + /// along with more items that are moved to the thread local pool to avoid + /// prevent acquiring the lock for shared pool too often. + /// The methods should not be called after the pool is disposed, but it won't + /// results in an error to do so (after depleting the items potentially left + /// in the thread local pool, it will continue returning new objects created by the factory). + /// + public T Lease() + { + var item = LeaseInternal(); + item.SetReturnToPoolAction(returnAction); + return item; + } + + private T LeaseInternal() + { + var localData = threadLocalData.Value; + if (localData.Queue.Count > 0) + { + return localData.Queue.Dequeue(); + } + if (localData.CreateBudget > 0) + { + localData.CreateBudget --; + return itemFactory(); + } + + int itemsMoved = 0; + T leasedItem = null; + lock(myLock) + { + if (sharedQueue.Count > 0) + { + leasedItem = sharedQueue.Dequeue(); + } + while (sharedQueue.Count > 0 && itemsMoved < rentLimit) + { + localData.Queue.Enqueue(sharedQueue.Dequeue()); + itemsMoved ++; + } + } + + // If the shared pool didn't contain all rentLimit items, + // next time we try to lease we will just create those + // instead of trying to grab them from the shared queue. + // This is to guarantee we won't be accessing the shared queue too often. + localData.CreateBudget = rentLimit - itemsMoved; + + return leasedItem ?? itemFactory(); + } + + /// + /// Returns an item to the pool. + /// Attempts to add the item to the thread local pool first. + /// If the thread local pool is full, item is added to a shared pool, + /// along with half of the items for the thread local pool, which + /// should prevent acquiring the lock for shared pool too often. + /// If called after the pool is disposed, we make best effort not to + /// add anything to the thread local pool and we guarantee not to add + /// anything to the shared pool (items will be disposed instead). + /// + public void Return(T item) + { + GrpcPreconditions.CheckNotNull(item); + + var localData = threadLocalData.Value; + if (localData.Queue.Count < threadLocalCapacity && !disposed) + { + localData.Queue.Enqueue(item); + return; + } + if (localData.DisposeBudget > 0) + { + localData.DisposeBudget --; + item.Dispose(); + return; + } + + int itemsReturned = 0; + int returnLimit = rentLimit + 1; + lock (myLock) + { + if (sharedQueue.Count < sharedCapacity && !disposed) + { + sharedQueue.Enqueue(item); + itemsReturned ++; + } + while (sharedQueue.Count < sharedCapacity && itemsReturned < returnLimit && !disposed) + { + sharedQueue.Enqueue(localData.Queue.Dequeue()); + itemsReturned ++; + } + } + + // If the shared pool could not accommodate all returnLimit items, + // next time we try to return we will just dispose the item + // instead of trying to return them to the shared queue. + // This is to guarantee we won't be accessing the shared queue too often. + localData.DisposeBudget = returnLimit - itemsReturned; + + if (itemsReturned == 0) + { + localData.DisposeBudget --; + item.Dispose(); + } + } + + public void Dispose() + { + lock (myLock) + { + if (!disposed) + { + disposed = true; + + while (sharedQueue.Count > 0) + { + sharedQueue.Dequeue().Dispose(); + } + } + } + } + + class ThreadLocalData + { + public ThreadLocalData(int capacity) + { + this.Queue = new Queue(capacity); + } + + public Queue Queue { get; } + public int CreateBudget { get; set; } + public int DisposeBudget { get; set; } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/DefaultSerializationContext.cs b/src/csharp/Grpc.Core/Internal/DefaultSerializationContext.cs new file mode 100644 index 00000000..981ff69d --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/DefaultSerializationContext.cs @@ -0,0 +1,115 @@ +#region Copyright notice and license + +// Copyright 2018 The gRPC Authors +// +// 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. + +#endregion + +using Grpc.Core.Utils; +using System; +using System.Buffers; +using System.Threading; + +namespace Grpc.Core.Internal +{ + internal class DefaultSerializationContext : SerializationContext + { + static readonly ThreadLocal threadLocalInstance = + new ThreadLocal(() => new DefaultSerializationContext(), false); + + bool isComplete; + SliceBufferSafeHandle sliceBuffer = SliceBufferSafeHandle.Create(); + + public DefaultSerializationContext() + { + Reset(); + } + + public override void Complete(byte[] payload) + { + GrpcPreconditions.CheckState(!isComplete); + this.isComplete = true; + + var destSpan = sliceBuffer.GetSpan(payload.Length); + payload.AsSpan().CopyTo(destSpan); + sliceBuffer.Advance(payload.Length); + sliceBuffer.Complete(); + } + + /// + /// Expose serializer as buffer writer + /// + public override IBufferWriter GetBufferWriter() + { + GrpcPreconditions.CheckState(!isComplete); + return sliceBuffer; + } + + public override void SetPayloadLength(int payloadLength) + { + // Length is calculated using the buffer writer + } + + /// + /// Complete the payload written so far. + /// + public override void Complete() + { + GrpcPreconditions.CheckState(!isComplete); + sliceBuffer.Complete(); + this.isComplete = true; + } + + internal SliceBufferSafeHandle GetPayload() + { + if (!isComplete) + { + // mimic the legacy behavior when byte[] was used to represent the payload. + throw new NullReferenceException("No payload was set. Complete() needs to be called before payload can be used."); + } + return sliceBuffer; + } + + public void Reset() + { + this.isComplete = false; + this.sliceBuffer.Reset(); + } + + // Get a cached thread local instance of deserialization context + // and wrap it in a disposable struct that allows easy resetting + // via "using" statement. + public static UsageScope GetInitializedThreadLocalScope() + { + var instance = threadLocalInstance.Value; + return new UsageScope(instance); + } + + public struct UsageScope : IDisposable + { + readonly DefaultSerializationContext context; + + public UsageScope(DefaultSerializationContext context) + { + this.context = context; + } + + public DefaultSerializationContext Context => context; + public void Dispose() + { + context.Reset(); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/DefaultServerCallContext.cs b/src/csharp/Grpc.Core/Internal/DefaultServerCallContext.cs new file mode 100644 index 00000000..77e4ccd3 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/DefaultServerCallContext.cs @@ -0,0 +1,108 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Threading; +using System.Threading.Tasks; + +using Grpc.Core.Internal; + +namespace Grpc.Core +{ + /// + /// Default implementation of ServerCallContext. + /// + internal class DefaultServerCallContext : ServerCallContext + { + private readonly CallSafeHandle callHandle; + private readonly string method; + private readonly string host; + private readonly DateTime deadline; + private readonly Metadata requestHeaders; + private readonly CancellationToken cancellationToken; + private readonly Metadata responseTrailers; + private Status status; + private readonly IServerResponseStream serverResponseStream; + private AuthContext lazyAuthContext; + + /// + /// Creates a new instance of ServerCallContext. + /// To allow reuse of ServerCallContext API by different gRPC implementations, the implementation of some members is provided externally. + /// To provide state, this ServerCallContext instance and extraData will be passed to the member implementations. + /// + internal DefaultServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, + Metadata requestHeaders, CancellationToken cancellationToken, IServerResponseStream serverResponseStream) + { + this.callHandle = callHandle; + this.method = method; + this.host = host; + this.deadline = deadline; + this.requestHeaders = requestHeaders; + this.cancellationToken = cancellationToken; + this.responseTrailers = new Metadata(); + this.status = Status.DefaultSuccess; + this.serverResponseStream = serverResponseStream; + } + + protected override ContextPropagationToken CreatePropagationTokenCore(ContextPropagationOptions options) + { + return new ContextPropagationTokenImpl(callHandle, deadline, cancellationToken, options); + } + + protected override Task WriteResponseHeadersAsyncCore(Metadata responseHeaders) + { + return serverResponseStream.WriteResponseHeadersAsync(responseHeaders); + } + + protected override string MethodCore => method; + + protected override string HostCore => host; + + protected override string PeerCore => callHandle.GetPeer(); + + protected override DateTime DeadlineCore => deadline; + + protected override Metadata RequestHeadersCore => requestHeaders; + + protected override CancellationToken CancellationTokenCore => cancellationToken; + + protected override Metadata ResponseTrailersCore => responseTrailers; + + protected override Status StatusCore + { + get => status; + set => status = value; + } + + protected override WriteOptions WriteOptionsCore + { + get => serverResponseStream.WriteOptions; + set => serverResponseStream.WriteOptions = value; + } + + protected override AuthContext AuthContextCore => lazyAuthContext ?? (lazyAuthContext = GetAuthContextEager()); + + private AuthContext GetAuthContextEager() + { + using (var authContextNative = callHandle.GetAuthContext()) + { + return authContextNative.ToAuthContext(); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs b/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs new file mode 100644 index 00000000..02d2dcd1 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs @@ -0,0 +1,57 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; + +namespace Grpc.Core.Internal +{ + /// + /// Overrides the content of default SSL roots. + /// + internal static class DefaultSslRootsOverride + { + const string RootsPemResourceName = "Grpc.Core.roots.pem"; + static object staticLock = new object(); + + /// + /// Overrides C core's default roots with roots.pem loaded as embedded resource. + /// + public static void Override(NativeMethods native) + { + lock (staticLock) + { + var stream = typeof(DefaultSslRootsOverride).GetTypeInfo().Assembly.GetManifestResourceStream(RootsPemResourceName); + if (stream == null) + { + throw new IOException(string.Format("Error loading the embedded resource \"{0}\"", RootsPemResourceName)); + } + using (var streamReader = new StreamReader(stream)) + { + var pemRootCerts = streamReader.ReadToEnd(); + native.grpcsharp_override_default_ssl_roots(pemRootCerts); + } + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs new file mode 100644 index 00000000..622cfde9 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs @@ -0,0 +1,244 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core.Logging; +using Grpc.Core.Profiling; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Pool of threads polling on a set of completions queues. + /// + internal class GrpcThreadPool + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + const int FinishContinuationsSleepMillis = 10; + const int MaxFinishContinuationsSleepTotalMillis = 10000; + + readonly GrpcEnvironment environment; + readonly object myLock = new object(); + readonly List threads = new List(); + readonly int poolSize; + readonly int completionQueueCount; + readonly bool inlineHandlers; + readonly WaitCallback runCompletionQueueEventCallbackSuccess; + readonly WaitCallback runCompletionQueueEventCallbackFailure; + readonly AtomicCounter queuedContinuationCounter = new AtomicCounter(); + + readonly List threadProfilers = new List(); // profilers assigned to threadpool threads + + bool stopRequested; + + IReadOnlyCollection completionQueues; + + /// + /// Creates a thread pool threads polling on a set of completions queues. + /// + /// Environment. + /// Pool size. + /// Completion queue count. + /// Handler inlining. + public GrpcThreadPool(GrpcEnvironment environment, int poolSize, int completionQueueCount, bool inlineHandlers) + { + this.environment = environment; + this.poolSize = poolSize; + this.completionQueueCount = completionQueueCount; + this.inlineHandlers = inlineHandlers; + GrpcPreconditions.CheckArgument(poolSize >= completionQueueCount, + "Thread pool size cannot be smaller than the number of completion queues used."); + + this.runCompletionQueueEventCallbackSuccess = new WaitCallback((callback) => RunCompletionQueueEventCallback((IOpCompletionCallback) callback, true)); + this.runCompletionQueueEventCallbackFailure = new WaitCallback((callback) => RunCompletionQueueEventCallback((IOpCompletionCallback) callback, false)); + } + + public void Start() + { + lock (myLock) + { + GrpcPreconditions.CheckState(completionQueues == null, "Already started."); + completionQueues = CreateCompletionQueueList(environment, completionQueueCount); + + for (int i = 0; i < poolSize; i++) + { + var optionalProfiler = i < threadProfilers.Count ? threadProfilers[i] : null; + threads.Add(CreateAndStartThread(i, optionalProfiler)); + } + } + } + + public Task StopAsync() + { + lock (myLock) + { + GrpcPreconditions.CheckState(!stopRequested, "Stop already requested."); + stopRequested = true; + + foreach (var cq in completionQueues) + { + cq.Shutdown(); + } + } + + return Task.Run(() => + { + foreach (var thread in threads) + { + thread.Join(); + } + + foreach (var cq in completionQueues) + { + cq.Dispose(); + } + + for (int i = 0; i < threadProfilers.Count; i++) + { + threadProfilers[i].Dump(string.Format("grpc_trace_thread_{0}.txt", i)); + } + }); + } + + /// + /// Returns true if there is at least one thread pool thread that hasn't + /// already stopped. + /// Threads can either stop because all completion queues shut down or + /// because all foreground threads have already shutdown and process is + /// going to exit. + /// + internal bool IsAlive + { + get + { + return threads.Any(t => t.ThreadState != ThreadState.Stopped); + } + } + + internal IReadOnlyCollection CompletionQueues + { + get + { + return completionQueues; + } + } + + private Thread CreateAndStartThread(int threadIndex, IProfiler optionalProfiler) + { + var cqIndex = threadIndex % completionQueues.Count; + var cq = completionQueues.ElementAt(cqIndex); + + var thread = new Thread(new ThreadStart(() => RunHandlerLoop(cq, optionalProfiler))); + thread.IsBackground = true; + thread.Name = string.Format("grpc {0} (cq {1})", threadIndex, cqIndex); + thread.Start(); + + return thread; + } + + /// + /// Body of the polling thread. + /// + private void RunHandlerLoop(CompletionQueueSafeHandle cq, IProfiler optionalProfiler) + { + if (optionalProfiler != null) + { + Profilers.SetForCurrentThread(optionalProfiler); + } + + CompletionQueueEvent ev; + do + { + ev = cq.Next(); + if (ev.type == CompletionQueueEvent.CompletionType.OpComplete) + { + bool success = (ev.success != 0); + IntPtr tag = ev.tag; + try + { + var callback = cq.CompletionRegistry.Extract(tag); + queuedContinuationCounter.Increment(); + if (!inlineHandlers) + { + // Use cached delegates to avoid unnecessary allocations + ThreadPool.QueueUserWorkItem(success ? runCompletionQueueEventCallbackSuccess : runCompletionQueueEventCallbackFailure, callback); + } + else + { + RunCompletionQueueEventCallback(callback, success); + } + } + catch (Exception e) + { + Logger.Error(e, "Exception occurred while extracting event from completion registry."); + } + } + } + while (ev.type != CompletionQueueEvent.CompletionType.Shutdown); + + // Continuations are running on default threadpool that consists of background threads. + // GrpcThreadPool thread (a foreground thread) will not exit unless all queued work had + // been finished to prevent terminating the continuations queued prematurely. + int sleepIterations = 0; + while (queuedContinuationCounter.Count != 0) + { + // Only happens on shutdown and having pending continuations shouldn't very common, + // so sleeping here for a little bit is fine. + if (sleepIterations >= MaxFinishContinuationsSleepTotalMillis / FinishContinuationsSleepMillis) + { + Logger.Warning("Shutting down gRPC thread [{0}] with unfinished callbacks (Timed out waiting for callbacks to finish).", + Thread.CurrentThread.Name); + break; + } + Thread.Sleep(FinishContinuationsSleepMillis); + sleepIterations ++; + } + } + + private static IReadOnlyCollection CreateCompletionQueueList(GrpcEnvironment environment, int completionQueueCount) + { + var list = new List(); + for (int i = 0; i < completionQueueCount; i++) + { + var completionRegistry = new CompletionRegistry(environment, () => environment.BatchContextPool.Lease(), () => environment.RequestCallContextPool.Lease()); + list.Add(CompletionQueueSafeHandle.CreateAsync(completionRegistry)); + } + return list.AsReadOnly(); + } + + private void RunCompletionQueueEventCallback(IOpCompletionCallback callback, bool success) + { + try + { + callback.OnComplete(success); + } + catch (Exception e) + { + Logger.Error(e, "Exception occurred while invoking completion delegate"); + } + finally + { + queuedContinuationCounter.Decrement(); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/INativeCall.cs b/src/csharp/Grpc.Core/Internal/INativeCall.cs new file mode 100644 index 00000000..70e98bfc --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/INativeCall.cs @@ -0,0 +1,94 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.Core; + +namespace Grpc.Core.Internal +{ + internal interface IUnaryResponseClientCallback + { + void OnUnaryResponseClient(bool success, ClientSideStatus receivedStatus, IBufferReader receivedMessageReader, Metadata responseHeaders); + } + + // Received status for streaming response calls. + internal interface IReceivedStatusOnClientCallback + { + void OnReceivedStatusOnClient(bool success, ClientSideStatus receivedStatus); + } + + internal interface IReceivedMessageCallback + { + void OnReceivedMessage(bool success, IBufferReader receivedMessageReader); + } + + internal interface IReceivedResponseHeadersCallback + { + void OnReceivedResponseHeaders(bool success, Metadata responseHeaders); + } + + internal interface ISendCompletionCallback + { + void OnSendCompletion(bool success); + } + + internal interface ISendStatusFromServerCompletionCallback + { + void OnSendStatusFromServerCompletion(bool success); + } + + internal interface IReceivedCloseOnServerCallback + { + void OnReceivedCloseOnServer(bool success, bool cancelled); + } + + /// + /// Abstraction of a native call object. + /// + internal interface INativeCall : IDisposable + { + void Cancel(); + + void CancelWithStatus(Status status); + + string GetPeer(); + + void StartUnary(IUnaryResponseClientCallback callback, SliceBufferSafeHandle payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags); + + void StartUnary(BatchContextSafeHandle ctx, SliceBufferSafeHandle payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags); + + void StartClientStreaming(IUnaryResponseClientCallback callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags); + + void StartServerStreaming(IReceivedStatusOnClientCallback callback, SliceBufferSafeHandle payload, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags callFlags); + + void StartDuplexStreaming(IReceivedStatusOnClientCallback callback, MetadataArraySafeHandle metadataArray, CallFlags callFlags); + + void StartReceiveMessage(IReceivedMessageCallback callback); + + void StartReceiveInitialMetadata(IReceivedResponseHeadersCallback callback); + + void StartSendInitialMetadata(ISendCompletionCallback callback, MetadataArraySafeHandle metadataArray); + + void StartSendMessage(ISendCompletionCallback callback, SliceBufferSafeHandle payload, WriteFlags writeFlags, bool sendEmptyInitialMetadata); + + void StartSendCloseFromClient(ISendCompletionCallback callback); + + void StartSendStatusFromServer(ISendStatusFromServerCompletionCallback callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata, SliceBufferSafeHandle optionalPayload, WriteFlags writeFlags); + + void StartServerSide(IReceivedCloseOnServerCallback callback); + } +} diff --git a/src/csharp/Grpc.Core/Internal/IObjectPool.cs b/src/csharp/Grpc.Core/Internal/IObjectPool.cs new file mode 100644 index 00000000..f7d6e30a --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/IObjectPool.cs @@ -0,0 +1,35 @@ +#region Copyright notice and license + +// Copyright 2017 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading; +using System.Collections.Generic; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Pool of objects. + /// + internal interface IObjectPool : IDisposable + where T : class + { + T Lease(); + void Return(T item); + } +} diff --git a/src/csharp/Grpc.Core/Internal/IPooledObject.cs b/src/csharp/Grpc.Core/Internal/IPooledObject.cs new file mode 100644 index 00000000..e20bd51d --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/IPooledObject.cs @@ -0,0 +1,34 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System; + +namespace Grpc.Core.Internal +{ + /// + /// An object that can be pooled in IObjectPool. + /// + /// + internal interface IPooledObject : IDisposable + { + /// + /// Set the action that will be invoked to return a leased object to the pool. + /// + void SetReturnToPoolAction(Action returnAction); + } +} diff --git a/src/csharp/Grpc.Core/Internal/IServerResponseStream.cs b/src/csharp/Grpc.Core/Internal/IServerResponseStream.cs new file mode 100644 index 00000000..874aae70 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/IServerResponseStream.cs @@ -0,0 +1,38 @@ +#region Copyright notice and license +// Copyright 2019 The gRPC Authors +// +// 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. +#endregion + +using System; +using System.Threading.Tasks; +using Grpc.Core.Internal; + +namespace Grpc.Core.Internal +{ + /// + /// Exposes non-generic members of ServerReponseStream. + /// + internal interface IServerResponseStream + { + /// + /// Asynchronously sends response headers for the current call to the client. See ServerCallContext.WriteResponseHeadersAsync for exact semantics. + /// + Task WriteResponseHeadersAsync(Metadata responseHeaders); + + /// + /// Gets or sets the write options. + /// + WriteOptions WriteOptions { get; set; } + } +} diff --git a/src/csharp/Grpc.Core/Internal/MarshalUtils.cs b/src/csharp/Grpc.Core/Internal/MarshalUtils.cs new file mode 100644 index 00000000..313e2b5c --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/MarshalUtils.cs @@ -0,0 +1,73 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using System.Text; +using Grpc.Core.Api.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Useful methods for native/managed marshalling. + /// + internal static class MarshalUtils + { + static readonly Encoding EncodingUTF8 = System.Text.Encoding.UTF8; + + /// + /// Converts IntPtr pointing to a UTF-8 encoded byte array to string. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string PtrToStringUTF8(IntPtr ptr, int len) + { + return EncodingUTF8.GetString(ptr, len); + } + + /// + /// UTF-8 encodes the given string into a buffer of sufficient size + /// + public static unsafe int GetBytesUTF8(string str, byte* destination, int destinationLength) + { + int charCount = str.Length; + if (charCount == 0) return 0; + fixed (char* source = str) + { + return EncodingUTF8.GetBytes(source, charCount, destination, destinationLength); + } + } + + /// + /// Returns the maximum number of bytes required to encode a given string. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetMaxByteCountUTF8(string str) + { + return EncodingUTF8.GetMaxByteCount(str.Length); + } + + /// + /// Returns the actual number of bytes required to encode a given string. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetByteCountUTF8(string str) + { + return EncodingUTF8.GetByteCount(str); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs new file mode 100644 index 00000000..3edfbfa3 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs @@ -0,0 +1,93 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace Grpc.Core.Internal +{ + /// + /// grpc_metadata_array from grpc/grpc.h + /// + internal class MetadataArraySafeHandle : SafeHandleZeroIsInvalid + { + static readonly NativeMethods Native = NativeMethods.Get(); + + private MetadataArraySafeHandle() + { + } + + public static MetadataArraySafeHandle Create(Metadata metadata) + { + if (metadata.Count == 0) + { + return new MetadataArraySafeHandle(); + } + + // TODO(jtattermusch): we might wanna check that the metadata is readonly + var metadataArray = Native.grpcsharp_metadata_array_create(new UIntPtr((ulong)metadata.Count)); + for (int i = 0; i < metadata.Count; i++) + { + var valueBytes = metadata[i].GetSerializedValueUnsafe(); + Native.grpcsharp_metadata_array_add(metadataArray, metadata[i].Key, valueBytes, new UIntPtr((ulong)valueBytes.Length)); + } + return metadataArray; + } + + /// + /// Reads metadata from pointer to grpc_metadata_array + /// + public static Metadata ReadMetadataFromPtrUnsafe(IntPtr metadataArray) + { + if (metadataArray == IntPtr.Zero) + { + return null; + } + + ulong count = Native.grpcsharp_metadata_array_count(metadataArray).ToUInt64(); + + var metadata = new Metadata(); + for (ulong i = 0; i < count; i++) + { + var index = new UIntPtr(i); + UIntPtr keyLen; + IntPtr keyPtr = Native.grpcsharp_metadata_array_get_key(metadataArray, index, out keyLen); + int keyLen32 = checked((int)keyLen.ToUInt32()); + string key = WellKnownStrings.TryIdentify(keyPtr, keyLen32) + ?? Marshal.PtrToStringAnsi(keyPtr, keyLen32); + UIntPtr valueLen; + IntPtr valuePtr = Native.grpcsharp_metadata_array_get_value(metadataArray, index, out valueLen); + int len32 = checked((int)valueLen.ToUInt64()); + metadata.Add(Metadata.Entry.CreateUnsafe(key, valuePtr, len32)); + } + return metadata; + } + + internal IntPtr Handle + { + get + { + return handle; + } + } + + protected override bool ReleaseHandle() + { + Native.grpcsharp_metadata_array_destroy_full(handle); + return true; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/MonoPInvokeCallbackAttribute.cs b/src/csharp/Grpc.Core/Internal/MonoPInvokeCallbackAttribute.cs new file mode 100644 index 00000000..64eb386a --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/MonoPInvokeCallbackAttribute.cs @@ -0,0 +1,40 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; + +namespace Grpc.Core.Internal +{ + /// + /// Use this attribute to mark methods that will be called back from P/Invoke calls. + /// iOS (and probably other AOT platforms) needs to have delegates registered. + /// Instead of depending on Xamarin.iOS for this, we can just create our own, + /// the iOS runtime just checks for the type name. + /// See: https://docs.microsoft.com/en-gb/xamarin/ios/internals/limitations#reverse-callbacks + /// + [AttributeUsage(AttributeTargets.Method)] + internal sealed class MonoPInvokeCallbackAttribute : Attribute + { + public MonoPInvokeCallbackAttribute(Type type) + { + Type = type; + } + + public Type Type { get; private set; } + } +} diff --git a/src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs b/src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs new file mode 100644 index 00000000..0777d793 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs @@ -0,0 +1,91 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading; +using System.Collections.Generic; +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + internal delegate int UniversalNativeCallback(IntPtr arg0, IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5); + + internal delegate int NativeCallbackDispatcherCallback(IntPtr tag, IntPtr arg0, IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5); + + internal class NativeCallbackDispatcher + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + + static NativeCallbackDispatcherCallback dispatcherCallback; + + public static void Init(NativeMethods native) + { + GrpcPreconditions.CheckState(dispatcherCallback == null); + dispatcherCallback = new NativeCallbackDispatcherCallback(HandleDispatcherCallback); + native.grpcsharp_native_callback_dispatcher_init(dispatcherCallback); + } + + public static NativeCallbackRegistration RegisterCallback(UniversalNativeCallback callback) + { + var gcHandle = GCHandle.Alloc(callback); + return new NativeCallbackRegistration(gcHandle); + } + + [MonoPInvokeCallback(typeof(NativeCallbackDispatcherCallback))] + private static int HandleDispatcherCallback(IntPtr tag, IntPtr arg0, IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5) + { + try + { + var gcHandle = GCHandle.FromIntPtr(tag); + var callback = (UniversalNativeCallback) gcHandle.Target; + return callback(arg0, arg1, arg2, arg3, arg4, arg5); + } + catch (Exception e) + { + // eat the exception, we must not throw when inside callback from native code. + Logger.Error(e, "Caught exception inside callback from native code."); + return 0; + } + } + } + + internal class NativeCallbackRegistration : IDisposable + { + readonly GCHandle handle; + + public NativeCallbackRegistration(GCHandle handle) + { + this.handle = handle; + } + + public IntPtr Tag => GCHandle.ToIntPtr(handle); + + public void Dispose() + { + if (handle.IsAllocated) + { + handle.Free(); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/NativeExtension.cs b/src/csharp/Grpc.Core/Internal/NativeExtension.cs new file mode 100644 index 00000000..3073b814 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/NativeExtension.cs @@ -0,0 +1,330 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.IO; +using System.Reflection; + +using Grpc.Core.Logging; + +namespace Grpc.Core.Internal +{ + /// + /// Takes care of loading C# native extension and provides access to PInvoke calls the library exports. + /// + internal sealed class NativeExtension + { + // Enviroment variable can be used to force loading the native extension from given location. + private const string CsharpExtOverrideLocationEnvVarName = "GRPC_CSHARP_EXT_OVERRIDE_LOCATION"; + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + static readonly object staticLock = new object(); + static volatile NativeExtension instance; + + readonly NativeMethods nativeMethods; + + private NativeExtension() + { + this.nativeMethods = LoadNativeMethods(); + + // Redirect the native logs as the very first thing after loading the native extension + // to make sure we don't lose any logs. + NativeLogRedirector.Redirect(this.nativeMethods); + + // Initialize + NativeCallbackDispatcher.Init(this.nativeMethods); + + DefaultSslRootsOverride.Override(this.nativeMethods); + + Logger.Debug("gRPC native library loaded successfully."); + } + + /// + /// Gets singleton instance of this class. + /// The native extension is loaded when called for the first time. + /// + public static NativeExtension Get() + { + if (instance == null) + { + lock (staticLock) + { + if (instance == null) { + instance = new NativeExtension(); + } + } + } + return instance; + } + + /// + /// Provides access to the exported native methods. + /// + public NativeMethods NativeMethods + { + get { return this.nativeMethods; } + } + + /// + /// Detects which configuration of native extension to load and explicitly loads the dynamic library. + /// The explicit load makes sure that we can detect any loading problems early on. + /// + private static NativeMethods LoadNativeMethodsUsingExplicitLoad() + { + // NOTE: a side effect of searching the native extension's library file relatively to the assembly location is that when Grpc.Core assembly + // is loaded via reflection from a different app's context, the native extension is still loaded correctly + // (while if we used [DllImport], the native extension won't be on the other app's search path for shared libraries). + var assemblyDirectory = GetAssemblyDirectory(); + + // With "classic" VS projects, the native libraries get copied using a .targets rule to the build output folder + // alongside the compiled assembly. + // With dotnet SDK projects targeting net45 framework, the native libraries (just the required ones) + // are similarly copied to the built output folder, through the magic of Microsoft.NETCore.Platforms. + var classicPath = Path.Combine(assemblyDirectory, GetNativeLibraryFilename()); + + // With dotnet SDK project targeting netcoreappX.Y, projects will use Grpc.Core assembly directly in the location where it got restored + // by nuget. We locate the native libraries based on known structure of Grpc.Core nuget package. + // When "dotnet publish" is used, the runtimes directory is copied next to the published assemblies. + string runtimesDirectory = string.Format("runtimes/{0}/native", GetRuntimeIdString()); + var netCorePublishedAppStylePath = Path.Combine(assemblyDirectory, runtimesDirectory, GetNativeLibraryFilename()); + var netCoreAppStylePath = Path.Combine(assemblyDirectory, "../..", runtimesDirectory, GetNativeLibraryFilename()); + + // Look for the native library in all possible locations in given order. + string[] paths = new[] { classicPath, netCorePublishedAppStylePath, netCoreAppStylePath}; + + // The UnmanagedLibrary mechanism for loading the native extension while avoiding + // direct use of DllImport is quite complicated but it is currently needed to ensure: + // 1.) the native extension is loaded eagerly (needed to avoid startup issues) + // 2.) less common scenarios (such as loading Grpc.Core.dll by reflection) still work + // 3.) loading native extension from an arbitrary location when set by an enviroment variable + // TODO(jtattermusch): revisit the possibility of eliminating UnmanagedLibrary completely in the future. + return new NativeMethods(new UnmanagedLibrary(paths)); + } + + /// + /// Loads native methods using the [DllImport(LIBRARY_NAME)] attributes. + /// Note that this way of loading the native extension is "lazy" and doesn't + /// detect any "missing library" problems until we actually try to invoke the native methods + /// (which could be too late and could cause weird hangs at startup) + /// + private static NativeMethods LoadNativeMethodsUsingDllImports() + { + // While in theory, we could just use [DllImport("grpc_csharp_ext")] for all the platforms + // and operating systems, the native libraries in the nuget package + // need to be laid out in a way that still allows things to work well under + // the legacy .NET Framework (where native libraries are a concept unknown to the runtime). + // Therefore, we use several flavors of the DllImport attribute + // (e.g. the ".x86" vs ".x64" suffix) and we choose the one we want at runtime. + // The classes with the list of DllImport'd methods are code generated, + // so having more than just one doesn't really bother us. + + // on Windows, the DllImport("grpc_csharp_ext.x64") doesn't work + // but DllImport("grpc_csharp_ext.x64.dll") does, so we need a special case for that. + // See https://github.com/dotnet/coreclr/pull/17505 (fixed in .NET Core 3.1+) + bool useDllSuffix = PlatformApis.IsWindows; + if (PlatformApis.ProcessArchitecture == CommonPlatformDetection.CpuArchitecture.X64) + { + if (useDllSuffix) + { + return new NativeMethods(new NativeMethods.DllImportsFromSharedLib_x64_dll()); + } + return new NativeMethods(new NativeMethods.DllImportsFromSharedLib_x64()); + } + else if (PlatformApis.ProcessArchitecture == CommonPlatformDetection.CpuArchitecture.X86) + { + if (useDllSuffix) + { + return new NativeMethods(new NativeMethods.DllImportsFromSharedLib_x86_dll()); + } + return new NativeMethods(new NativeMethods.DllImportsFromSharedLib_x86()); + } + else if (PlatformApis.ProcessArchitecture == CommonPlatformDetection.CpuArchitecture.Arm64) + { + return new NativeMethods(new NativeMethods.DllImportsFromSharedLib_arm64()); + } + else + { + throw new InvalidOperationException($"Unsupported architecture \"{PlatformApis.ProcessArchitecture}\"."); + } + } + + /// + /// Loads native extension and return native methods delegates. + /// + private static NativeMethods LoadNativeMethods() + { + if (PlatformApis.IsUnity) + { + return LoadNativeMethodsUnity(); + } + if (PlatformApis.IsXamarin) + { + return LoadNativeMethodsXamarin(); + } + + // Override location of grpc_csharp_ext native library with an environment variable + // Use at your own risk! By doing this you take all the responsibility that the dynamic library + // is of the correct version (needs to match the Grpc.Core assembly exactly) and of the correct platform/architecture. + var nativeExtPathFromEnv = System.Environment.GetEnvironmentVariable(CsharpExtOverrideLocationEnvVarName); + if (!string.IsNullOrEmpty(nativeExtPathFromEnv)) + { + return new NativeMethods(new UnmanagedLibrary(new string[] { nativeExtPathFromEnv })); + } + + if (IsNet5SingleFileApp()) + { + // Ideally we'd want to always load the native extension explicitly + // (to detect any potential problems early on and to avoid hard-to-debug startup issues) + // but the mechanism we normally use doesn't work when running + // as a single file app (see https://github.com/grpc/grpc/pull/24744). + // Therefore in this case we simply rely + // on the automatic [DllImport] loading logic to do the right thing. + return LoadNativeMethodsUsingDllImports(); + } + return LoadNativeMethodsUsingExplicitLoad(); + } + + /// + /// Return native method delegates when running on Unity platform. + /// Unity does not use standard NuGet packages and the native library is treated + /// there as a "native plugin" which is (provided it has the right metadata) + /// automatically made available to [DllImport] loading logic. + /// WARNING: Unity support is experimental and work-in-progress. Don't expect it to work. + /// + private static NativeMethods LoadNativeMethodsUnity() + { + if (PlatformApis.IsUnityIOS) + { + return new NativeMethods(new NativeMethods.DllImportsFromStaticLib()); + } + // most other platforms load unity plugins as a shared library + return new NativeMethods(new NativeMethods.DllImportsFromSharedLib()); + } + + /// + /// Return native method delegates when running on the Xamarin platform. + /// On Xamarin, the standard [DllImport] loading logic just works + /// as the native library metadata is provided by the AndroidNativeLibrary or + /// NativeReference items in the Xamarin projects (injected automatically + /// by the Grpc.Core.Xamarin nuget). + /// WARNING: Xamarin support is experimental and work-in-progress. Don't expect it to work. + /// + private static NativeMethods LoadNativeMethodsXamarin() + { + if (PlatformApis.IsXamarinAndroid) + { + return new NativeMethods(new NativeMethods.DllImportsFromSharedLib()); + } + return new NativeMethods(new NativeMethods.DllImportsFromStaticLib()); + } + + private static string GetAssemblyDirectory() + { + var assembly = typeof(NativeExtension).GetTypeInfo().Assembly; +#if NETSTANDARD + // Assembly.EscapedCodeBase does not exist under CoreCLR, but assemblies imported from a nuget package + // don't seem to be shadowed by DNX-based projects at all. + var assemblyLocation = assembly.Location; + if (string.IsNullOrEmpty(assemblyLocation)) + { + // In .NET5 single-file deployments, assembly.Location won't be available + // and we can use it for detecting whether we are running as a single file app. + // Also see https://docs.microsoft.com/en-us/dotnet/core/deploying/single-file#other-considerations + return null; + } + return Path.GetDirectoryName(assemblyLocation); +#else + // If assembly is shadowed (e.g. in a webapp), EscapedCodeBase is pointing + // to the original location of the assembly, and Location is pointing + // to the shadow copy. We care about the original location because + // the native dlls don't get shadowed. + + var escapedCodeBase = assembly.EscapedCodeBase; + if (IsFileUri(escapedCodeBase)) + { + return Path.GetDirectoryName(new Uri(escapedCodeBase).LocalPath); + } + return Path.GetDirectoryName(assembly.Location); +#endif + } + + private static bool IsNet5SingleFileApp() + { + // Use a heuristic that GetAssemblyDirectory() will return null for single file apps. + return PlatformApis.IsNet5OrHigher && GetAssemblyDirectory() == null; + } + +#if !NETSTANDARD + private static bool IsFileUri(string uri) + { + return uri.ToLowerInvariant().StartsWith(Uri.UriSchemeFile); + } +#endif + + private static string GetRuntimeIdString() + { + string architecture = GetArchitectureString(); + if (PlatformApis.IsWindows) + { + return string.Format("win-{0}", architecture); + } + if (PlatformApis.IsLinux) + { + return string.Format("linux-{0}", architecture); + } + if (PlatformApis.IsMacOSX) + { + return string.Format("osx-{0}", architecture); + } + throw new InvalidOperationException("Unsupported platform."); + } + + private static string GetArchitectureString() + { + switch (PlatformApis.ProcessArchitecture) + { + case CommonPlatformDetection.CpuArchitecture.X86: + return "x86"; + case CommonPlatformDetection.CpuArchitecture.X64: + return "x64"; + case CommonPlatformDetection.CpuArchitecture.Arm64: + return "arm64"; + default: + throw new InvalidOperationException($"Unsupported architecture \"{PlatformApis.ProcessArchitecture}\"."); + } + } + + // platform specific file name of the extension library + private static string GetNativeLibraryFilename() + { + string architecture = GetArchitectureString(); + if (PlatformApis.IsWindows) + { + return string.Format("grpc_csharp_ext.{0}.dll", architecture); + } + if (PlatformApis.IsLinux) + { + return string.Format("libgrpc_csharp_ext.{0}.so", architecture); + } + if (PlatformApis.IsMacOSX) + { + return string.Format("libgrpc_csharp_ext.{0}.dylib", architecture); + } + throw new InvalidOperationException("Unsupported platform."); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/NativeLogRedirector.cs b/src/csharp/Grpc.Core/Internal/NativeLogRedirector.cs new file mode 100644 index 00000000..062c0101 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/NativeLogRedirector.cs @@ -0,0 +1,90 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading; + +namespace Grpc.Core.Internal +{ + internal delegate void GprLogDelegate(IntPtr fileStringPtr, int line, ulong threadId, IntPtr severityStringPtr, IntPtr msgPtr); + + /// + /// Logs from gRPC C core library can get lost if your application is not a console app. + /// This class allows redirection of logs to gRPC logger. + /// + internal static class NativeLogRedirector + { + static object staticLock = new object(); + static GprLogDelegate writeCallback; + + /// + /// Redirects logs from native gRPC C core library to a general logger. + /// + public static void Redirect(NativeMethods native) + { + lock (staticLock) + { + if (writeCallback == null) + { + writeCallback = new GprLogDelegate(HandleWrite); + native.grpcsharp_redirect_log(writeCallback); + } + } + } + + [MonoPInvokeCallback(typeof(GprLogDelegate))] + private static void HandleWrite(IntPtr fileStringPtr, int line, ulong threadId, IntPtr severityStringPtr, IntPtr msgPtr) + { + try + { + var logger = GrpcEnvironment.Logger; + string severityString = Marshal.PtrToStringAnsi(severityStringPtr); + string message = string.Format("{0} {1}:{2}: {3}", + threadId, + Marshal.PtrToStringAnsi(fileStringPtr), + line, + Marshal.PtrToStringAnsi(msgPtr)); + + switch (severityString) + { + case "D": + logger.Debug(message); + break; + case "I": + logger.Info(message); + break; + case "E": + logger.Error(message); + break; + default: + // severity not recognized, default to error. + logger.Error(message); + break; + } + } + catch (Exception e) + { + Console.WriteLine("Caught exception in native callback " + e); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs new file mode 100644 index 00000000..cdcd69ef --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs @@ -0,0 +1,100 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + internal class NativeMetadataCredentialsPlugin + { + const string GetMetadataExceptionStatusMsg = "Exception occurred in metadata credentials plugin."; + const string GetMetadataExceptionLogMsg = GetMetadataExceptionStatusMsg + " This is likely not a problem with gRPC itself. Please verify that the code supplying the metadata (usually an authentication token) works correctly."; + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + static readonly NativeMethods Native = NativeMethods.Get(); + + AsyncAuthInterceptor interceptor; + CallCredentialsSafeHandle credentials; + NativeCallbackRegistration callbackRegistration; + + public NativeMetadataCredentialsPlugin(AsyncAuthInterceptor interceptor) + { + this.interceptor = GrpcPreconditions.CheckNotNull(interceptor, "interceptor"); + this.callbackRegistration = NativeCallbackDispatcher.RegisterCallback(HandleUniversalCallback); + this.credentials = Native.grpcsharp_metadata_credentials_create_from_plugin(this.callbackRegistration.Tag); + } + + public CallCredentialsSafeHandle Credentials + { + get { return credentials; } + } + + private int HandleUniversalCallback(IntPtr arg0, IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5) + { + NativeMetadataInterceptorHandler(arg0, arg1, arg2, arg3, arg4 != IntPtr.Zero); + return 0; + } + + private void NativeMetadataInterceptorHandler(IntPtr serviceUrlPtr, IntPtr methodNamePtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy) + { + if (isDestroy) + { + this.callbackRegistration.Dispose(); + return; + } + + try + { + // NOTE: The serviceUrlPtr and methodNamePtr values come from the grpc_auth_metadata_context + // and are only guaranteed to be valid until synchronous return of this handler. + // We are effectively making a copy of these strings by creating C# string from the native char pointers, + // and passing the resulting C# strings to the context is therefore safe. + var context = new AuthInterceptorContext(Marshal.PtrToStringAnsi(serviceUrlPtr), Marshal.PtrToStringAnsi(methodNamePtr)); + // Make a guarantee that credentials_notify_from_plugin is invoked async to be compliant with c-core API. + ThreadPool.QueueUserWorkItem(async (stateInfo) => await GetMetadataAsync(context, callbackPtr, userDataPtr)); + } + catch (Exception e) + { + // eat the exception, we must not throw when inside callback from native code. + Logger.Error(e, "Exception occurred while invoking native metadata interceptor handler."); + } + } + + private async Task GetMetadataAsync(AuthInterceptorContext context, IntPtr callbackPtr, IntPtr userDataPtr) + { + try + { + var metadata = new Metadata(); + await interceptor(context, metadata).ConfigureAwait(false); + + using (var metadataArray = MetadataArraySafeHandle.Create(metadata)) + { + Native.grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, metadataArray, StatusCode.OK, null); + } + } + catch (Exception e) + { + string detail = GetMetadataExceptionStatusMsg + " " + e.ToString(); + Native.grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, MetadataArraySafeHandle.Create(Metadata.Empty), StatusCode.Unknown, detail); + Logger.Error(e, GetMetadataExceptionLogMsg); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs new file mode 100644 index 00000000..83d9ffaa --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs @@ -0,0 +1,3359 @@ + +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; + +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + internal partial class NativeMethods + { + #region Native methods + + public readonly Delegates.grpcsharp_init_delegate grpcsharp_init; + public readonly Delegates.grpcsharp_shutdown_delegate grpcsharp_shutdown; + public readonly Delegates.grpcsharp_version_string_delegate grpcsharp_version_string; + public readonly Delegates.grpcsharp_batch_context_create_delegate grpcsharp_batch_context_create; + public readonly Delegates.grpcsharp_batch_context_recv_initial_metadata_delegate grpcsharp_batch_context_recv_initial_metadata; + public readonly Delegates.grpcsharp_batch_context_recv_message_length_delegate grpcsharp_batch_context_recv_message_length; + public readonly Delegates.grpcsharp_batch_context_recv_message_next_slice_peek_delegate grpcsharp_batch_context_recv_message_next_slice_peek; + public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_status_delegate grpcsharp_batch_context_recv_status_on_client_status; + public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_details_delegate grpcsharp_batch_context_recv_status_on_client_details; + public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_error_string_delegate grpcsharp_batch_context_recv_status_on_client_error_string; + public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate grpcsharp_batch_context_recv_status_on_client_trailing_metadata; + public readonly Delegates.grpcsharp_batch_context_recv_close_on_server_cancelled_delegate grpcsharp_batch_context_recv_close_on_server_cancelled; + public readonly Delegates.grpcsharp_batch_context_reset_delegate grpcsharp_batch_context_reset; + public readonly Delegates.grpcsharp_batch_context_destroy_delegate grpcsharp_batch_context_destroy; + public readonly Delegates.grpcsharp_request_call_context_create_delegate grpcsharp_request_call_context_create; + public readonly Delegates.grpcsharp_request_call_context_call_delegate grpcsharp_request_call_context_call; + public readonly Delegates.grpcsharp_request_call_context_method_delegate grpcsharp_request_call_context_method; + public readonly Delegates.grpcsharp_request_call_context_host_delegate grpcsharp_request_call_context_host; + public readonly Delegates.grpcsharp_request_call_context_deadline_delegate grpcsharp_request_call_context_deadline; + public readonly Delegates.grpcsharp_request_call_context_request_metadata_delegate grpcsharp_request_call_context_request_metadata; + public readonly Delegates.grpcsharp_request_call_context_reset_delegate grpcsharp_request_call_context_reset; + public readonly Delegates.grpcsharp_request_call_context_destroy_delegate grpcsharp_request_call_context_destroy; + public readonly Delegates.grpcsharp_composite_call_credentials_create_delegate grpcsharp_composite_call_credentials_create; + public readonly Delegates.grpcsharp_call_credentials_release_delegate grpcsharp_call_credentials_release; + public readonly Delegates.grpcsharp_call_cancel_delegate grpcsharp_call_cancel; + public readonly Delegates.grpcsharp_call_cancel_with_status_delegate grpcsharp_call_cancel_with_status; + public readonly Delegates.grpcsharp_call_start_unary_delegate grpcsharp_call_start_unary; + public readonly Delegates.grpcsharp_call_start_client_streaming_delegate grpcsharp_call_start_client_streaming; + public readonly Delegates.grpcsharp_call_start_server_streaming_delegate grpcsharp_call_start_server_streaming; + public readonly Delegates.grpcsharp_call_start_duplex_streaming_delegate grpcsharp_call_start_duplex_streaming; + public readonly Delegates.grpcsharp_call_send_message_delegate grpcsharp_call_send_message; + public readonly Delegates.grpcsharp_call_send_close_from_client_delegate grpcsharp_call_send_close_from_client; + public readonly Delegates.grpcsharp_call_send_status_from_server_delegate grpcsharp_call_send_status_from_server; + public readonly Delegates.grpcsharp_call_recv_message_delegate grpcsharp_call_recv_message; + public readonly Delegates.grpcsharp_call_recv_initial_metadata_delegate grpcsharp_call_recv_initial_metadata; + public readonly Delegates.grpcsharp_call_start_serverside_delegate grpcsharp_call_start_serverside; + public readonly Delegates.grpcsharp_call_send_initial_metadata_delegate grpcsharp_call_send_initial_metadata; + public readonly Delegates.grpcsharp_call_set_credentials_delegate grpcsharp_call_set_credentials; + public readonly Delegates.grpcsharp_call_get_peer_delegate grpcsharp_call_get_peer; + public readonly Delegates.grpcsharp_call_destroy_delegate grpcsharp_call_destroy; + public readonly Delegates.grpcsharp_channel_args_create_delegate grpcsharp_channel_args_create; + public readonly Delegates.grpcsharp_channel_args_set_string_delegate grpcsharp_channel_args_set_string; + public readonly Delegates.grpcsharp_channel_args_set_integer_delegate grpcsharp_channel_args_set_integer; + public readonly Delegates.grpcsharp_channel_args_destroy_delegate grpcsharp_channel_args_destroy; + public readonly Delegates.grpcsharp_override_default_ssl_roots_delegate grpcsharp_override_default_ssl_roots; + public readonly Delegates.grpcsharp_ssl_credentials_create_delegate grpcsharp_ssl_credentials_create; + public readonly Delegates.grpcsharp_composite_channel_credentials_create_delegate grpcsharp_composite_channel_credentials_create; + public readonly Delegates.grpcsharp_channel_credentials_release_delegate grpcsharp_channel_credentials_release; + public readonly Delegates.grpcsharp_insecure_channel_create_delegate grpcsharp_insecure_channel_create; + public readonly Delegates.grpcsharp_secure_channel_create_delegate grpcsharp_secure_channel_create; + public readonly Delegates.grpcsharp_channel_create_call_delegate grpcsharp_channel_create_call; + public readonly Delegates.grpcsharp_channel_check_connectivity_state_delegate grpcsharp_channel_check_connectivity_state; + public readonly Delegates.grpcsharp_channel_watch_connectivity_state_delegate grpcsharp_channel_watch_connectivity_state; + public readonly Delegates.grpcsharp_channel_get_target_delegate grpcsharp_channel_get_target; + public readonly Delegates.grpcsharp_channel_destroy_delegate grpcsharp_channel_destroy; + public readonly Delegates.grpcsharp_sizeof_grpc_event_delegate grpcsharp_sizeof_grpc_event; + public readonly Delegates.grpcsharp_completion_queue_create_async_delegate grpcsharp_completion_queue_create_async; + public readonly Delegates.grpcsharp_completion_queue_create_sync_delegate grpcsharp_completion_queue_create_sync; + public readonly Delegates.grpcsharp_completion_queue_shutdown_delegate grpcsharp_completion_queue_shutdown; + public readonly Delegates.grpcsharp_completion_queue_next_delegate grpcsharp_completion_queue_next; + public readonly Delegates.grpcsharp_completion_queue_pluck_delegate grpcsharp_completion_queue_pluck; + public readonly Delegates.grpcsharp_completion_queue_destroy_delegate grpcsharp_completion_queue_destroy; + public readonly Delegates.gprsharp_free_delegate gprsharp_free; + public readonly Delegates.grpcsharp_metadata_array_create_delegate grpcsharp_metadata_array_create; + public readonly Delegates.grpcsharp_metadata_array_add_delegate grpcsharp_metadata_array_add; + public readonly Delegates.grpcsharp_metadata_array_count_delegate grpcsharp_metadata_array_count; + public readonly Delegates.grpcsharp_metadata_array_get_key_delegate grpcsharp_metadata_array_get_key; + public readonly Delegates.grpcsharp_metadata_array_get_value_delegate grpcsharp_metadata_array_get_value; + public readonly Delegates.grpcsharp_metadata_array_destroy_full_delegate grpcsharp_metadata_array_destroy_full; + public readonly Delegates.grpcsharp_redirect_log_delegate grpcsharp_redirect_log; + public readonly Delegates.grpcsharp_native_callback_dispatcher_init_delegate grpcsharp_native_callback_dispatcher_init; + public readonly Delegates.grpcsharp_metadata_credentials_create_from_plugin_delegate grpcsharp_metadata_credentials_create_from_plugin; + public readonly Delegates.grpcsharp_metadata_credentials_notify_from_plugin_delegate grpcsharp_metadata_credentials_notify_from_plugin; + public readonly Delegates.grpcsharp_ssl_server_credentials_create_delegate grpcsharp_ssl_server_credentials_create; + public readonly Delegates.grpcsharp_server_credentials_release_delegate grpcsharp_server_credentials_release; + public readonly Delegates.grpcsharp_server_create_delegate grpcsharp_server_create; + public readonly Delegates.grpcsharp_server_register_completion_queue_delegate grpcsharp_server_register_completion_queue; + public readonly Delegates.grpcsharp_server_add_insecure_http2_port_delegate grpcsharp_server_add_insecure_http2_port; + public readonly Delegates.grpcsharp_server_add_secure_http2_port_delegate grpcsharp_server_add_secure_http2_port; + public readonly Delegates.grpcsharp_server_start_delegate grpcsharp_server_start; + public readonly Delegates.grpcsharp_server_request_call_delegate grpcsharp_server_request_call; + public readonly Delegates.grpcsharp_server_cancel_all_calls_delegate grpcsharp_server_cancel_all_calls; + public readonly Delegates.grpcsharp_server_shutdown_and_notify_callback_delegate grpcsharp_server_shutdown_and_notify_callback; + public readonly Delegates.grpcsharp_server_destroy_delegate grpcsharp_server_destroy; + public readonly Delegates.grpcsharp_call_auth_context_delegate grpcsharp_call_auth_context; + public readonly Delegates.grpcsharp_auth_context_peer_identity_property_name_delegate grpcsharp_auth_context_peer_identity_property_name; + public readonly Delegates.grpcsharp_auth_context_property_iterator_delegate grpcsharp_auth_context_property_iterator; + public readonly Delegates.grpcsharp_auth_property_iterator_next_delegate grpcsharp_auth_property_iterator_next; + public readonly Delegates.grpcsharp_auth_context_release_delegate grpcsharp_auth_context_release; + public readonly Delegates.grpcsharp_slice_buffer_create_delegate grpcsharp_slice_buffer_create; + public readonly Delegates.grpcsharp_slice_buffer_adjust_tail_space_delegate grpcsharp_slice_buffer_adjust_tail_space; + public readonly Delegates.grpcsharp_slice_buffer_slice_count_delegate grpcsharp_slice_buffer_slice_count; + public readonly Delegates.grpcsharp_slice_buffer_slice_peek_delegate grpcsharp_slice_buffer_slice_peek; + public readonly Delegates.grpcsharp_slice_buffer_reset_and_unref_delegate grpcsharp_slice_buffer_reset_and_unref; + public readonly Delegates.grpcsharp_slice_buffer_destroy_delegate grpcsharp_slice_buffer_destroy; + public readonly Delegates.gprsharp_now_delegate gprsharp_now; + public readonly Delegates.gprsharp_inf_future_delegate gprsharp_inf_future; + public readonly Delegates.gprsharp_inf_past_delegate gprsharp_inf_past; + public readonly Delegates.gprsharp_convert_clock_type_delegate gprsharp_convert_clock_type; + public readonly Delegates.gprsharp_sizeof_timespec_delegate gprsharp_sizeof_timespec; + public readonly Delegates.grpcsharp_test_callback_delegate grpcsharp_test_callback; + public readonly Delegates.grpcsharp_test_nop_delegate grpcsharp_test_nop; + public readonly Delegates.grpcsharp_test_override_method_delegate grpcsharp_test_override_method; + public readonly Delegates.grpcsharp_test_call_start_unary_echo_delegate grpcsharp_test_call_start_unary_echo; + + #endregion + + public NativeMethods(UnmanagedLibrary library) + { + this.grpcsharp_init = GetMethodDelegate(library); + this.grpcsharp_shutdown = GetMethodDelegate(library); + this.grpcsharp_version_string = GetMethodDelegate(library); + this.grpcsharp_batch_context_create = GetMethodDelegate(library); + this.grpcsharp_batch_context_recv_initial_metadata = GetMethodDelegate(library); + this.grpcsharp_batch_context_recv_message_length = GetMethodDelegate(library); + this.grpcsharp_batch_context_recv_message_next_slice_peek = GetMethodDelegate(library); + this.grpcsharp_batch_context_recv_status_on_client_status = GetMethodDelegate(library); + this.grpcsharp_batch_context_recv_status_on_client_details = GetMethodDelegate(library); + this.grpcsharp_batch_context_recv_status_on_client_error_string = GetMethodDelegate(library); + this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = GetMethodDelegate(library); + this.grpcsharp_batch_context_recv_close_on_server_cancelled = GetMethodDelegate(library); + this.grpcsharp_batch_context_reset = GetMethodDelegate(library); + this.grpcsharp_batch_context_destroy = GetMethodDelegate(library); + this.grpcsharp_request_call_context_create = GetMethodDelegate(library); + this.grpcsharp_request_call_context_call = GetMethodDelegate(library); + this.grpcsharp_request_call_context_method = GetMethodDelegate(library); + this.grpcsharp_request_call_context_host = GetMethodDelegate(library); + this.grpcsharp_request_call_context_deadline = GetMethodDelegate(library); + this.grpcsharp_request_call_context_request_metadata = GetMethodDelegate(library); + this.grpcsharp_request_call_context_reset = GetMethodDelegate(library); + this.grpcsharp_request_call_context_destroy = GetMethodDelegate(library); + this.grpcsharp_composite_call_credentials_create = GetMethodDelegate(library); + this.grpcsharp_call_credentials_release = GetMethodDelegate(library); + this.grpcsharp_call_cancel = GetMethodDelegate(library); + this.grpcsharp_call_cancel_with_status = GetMethodDelegate(library); + this.grpcsharp_call_start_unary = GetMethodDelegate(library); + this.grpcsharp_call_start_client_streaming = GetMethodDelegate(library); + this.grpcsharp_call_start_server_streaming = GetMethodDelegate(library); + this.grpcsharp_call_start_duplex_streaming = GetMethodDelegate(library); + this.grpcsharp_call_send_message = GetMethodDelegate(library); + this.grpcsharp_call_send_close_from_client = GetMethodDelegate(library); + this.grpcsharp_call_send_status_from_server = GetMethodDelegate(library); + this.grpcsharp_call_recv_message = GetMethodDelegate(library); + this.grpcsharp_call_recv_initial_metadata = GetMethodDelegate(library); + this.grpcsharp_call_start_serverside = GetMethodDelegate(library); + this.grpcsharp_call_send_initial_metadata = GetMethodDelegate(library); + this.grpcsharp_call_set_credentials = GetMethodDelegate(library); + this.grpcsharp_call_get_peer = GetMethodDelegate(library); + this.grpcsharp_call_destroy = GetMethodDelegate(library); + this.grpcsharp_channel_args_create = GetMethodDelegate(library); + this.grpcsharp_channel_args_set_string = GetMethodDelegate(library); + this.grpcsharp_channel_args_set_integer = GetMethodDelegate(library); + this.grpcsharp_channel_args_destroy = GetMethodDelegate(library); + this.grpcsharp_override_default_ssl_roots = GetMethodDelegate(library); + this.grpcsharp_ssl_credentials_create = GetMethodDelegate(library); + this.grpcsharp_composite_channel_credentials_create = GetMethodDelegate(library); + this.grpcsharp_channel_credentials_release = GetMethodDelegate(library); + this.grpcsharp_insecure_channel_create = GetMethodDelegate(library); + this.grpcsharp_secure_channel_create = GetMethodDelegate(library); + this.grpcsharp_channel_create_call = GetMethodDelegate(library); + this.grpcsharp_channel_check_connectivity_state = GetMethodDelegate(library); + this.grpcsharp_channel_watch_connectivity_state = GetMethodDelegate(library); + this.grpcsharp_channel_get_target = GetMethodDelegate(library); + this.grpcsharp_channel_destroy = GetMethodDelegate(library); + this.grpcsharp_sizeof_grpc_event = GetMethodDelegate(library); + this.grpcsharp_completion_queue_create_async = GetMethodDelegate(library); + this.grpcsharp_completion_queue_create_sync = GetMethodDelegate(library); + this.grpcsharp_completion_queue_shutdown = GetMethodDelegate(library); + this.grpcsharp_completion_queue_next = GetMethodDelegate(library); + this.grpcsharp_completion_queue_pluck = GetMethodDelegate(library); + this.grpcsharp_completion_queue_destroy = GetMethodDelegate(library); + this.gprsharp_free = GetMethodDelegate(library); + this.grpcsharp_metadata_array_create = GetMethodDelegate(library); + this.grpcsharp_metadata_array_add = GetMethodDelegate(library); + this.grpcsharp_metadata_array_count = GetMethodDelegate(library); + this.grpcsharp_metadata_array_get_key = GetMethodDelegate(library); + this.grpcsharp_metadata_array_get_value = GetMethodDelegate(library); + this.grpcsharp_metadata_array_destroy_full = GetMethodDelegate(library); + this.grpcsharp_redirect_log = GetMethodDelegate(library); + this.grpcsharp_native_callback_dispatcher_init = GetMethodDelegate(library); + this.grpcsharp_metadata_credentials_create_from_plugin = GetMethodDelegate(library); + this.grpcsharp_metadata_credentials_notify_from_plugin = GetMethodDelegate(library); + this.grpcsharp_ssl_server_credentials_create = GetMethodDelegate(library); + this.grpcsharp_server_credentials_release = GetMethodDelegate(library); + this.grpcsharp_server_create = GetMethodDelegate(library); + this.grpcsharp_server_register_completion_queue = GetMethodDelegate(library); + this.grpcsharp_server_add_insecure_http2_port = GetMethodDelegate(library); + this.grpcsharp_server_add_secure_http2_port = GetMethodDelegate(library); + this.grpcsharp_server_start = GetMethodDelegate(library); + this.grpcsharp_server_request_call = GetMethodDelegate(library); + this.grpcsharp_server_cancel_all_calls = GetMethodDelegate(library); + this.grpcsharp_server_shutdown_and_notify_callback = GetMethodDelegate(library); + this.grpcsharp_server_destroy = GetMethodDelegate(library); + this.grpcsharp_call_auth_context = GetMethodDelegate(library); + this.grpcsharp_auth_context_peer_identity_property_name = GetMethodDelegate(library); + this.grpcsharp_auth_context_property_iterator = GetMethodDelegate(library); + this.grpcsharp_auth_property_iterator_next = GetMethodDelegate(library); + this.grpcsharp_auth_context_release = GetMethodDelegate(library); + this.grpcsharp_slice_buffer_create = GetMethodDelegate(library); + this.grpcsharp_slice_buffer_adjust_tail_space = GetMethodDelegate(library); + this.grpcsharp_slice_buffer_slice_count = GetMethodDelegate(library); + this.grpcsharp_slice_buffer_slice_peek = GetMethodDelegate(library); + this.grpcsharp_slice_buffer_reset_and_unref = GetMethodDelegate(library); + this.grpcsharp_slice_buffer_destroy = GetMethodDelegate(library); + this.gprsharp_now = GetMethodDelegate(library); + this.gprsharp_inf_future = GetMethodDelegate(library); + this.gprsharp_inf_past = GetMethodDelegate(library); + this.gprsharp_convert_clock_type = GetMethodDelegate(library); + this.gprsharp_sizeof_timespec = GetMethodDelegate(library); + this.grpcsharp_test_callback = GetMethodDelegate(library); + this.grpcsharp_test_nop = GetMethodDelegate(library); + this.grpcsharp_test_override_method = GetMethodDelegate(library); + this.grpcsharp_test_call_start_unary_echo = GetMethodDelegate(library); + } + + public NativeMethods(DllImportsFromStaticLib unusedInstance) + { + this.grpcsharp_init = DllImportsFromStaticLib.grpcsharp_init; + this.grpcsharp_shutdown = DllImportsFromStaticLib.grpcsharp_shutdown; + this.grpcsharp_version_string = DllImportsFromStaticLib.grpcsharp_version_string; + this.grpcsharp_batch_context_create = DllImportsFromStaticLib.grpcsharp_batch_context_create; + this.grpcsharp_batch_context_recv_initial_metadata = DllImportsFromStaticLib.grpcsharp_batch_context_recv_initial_metadata; + this.grpcsharp_batch_context_recv_message_length = DllImportsFromStaticLib.grpcsharp_batch_context_recv_message_length; + this.grpcsharp_batch_context_recv_message_next_slice_peek = DllImportsFromStaticLib.grpcsharp_batch_context_recv_message_next_slice_peek; + this.grpcsharp_batch_context_recv_status_on_client_status = DllImportsFromStaticLib.grpcsharp_batch_context_recv_status_on_client_status; + this.grpcsharp_batch_context_recv_status_on_client_details = DllImportsFromStaticLib.grpcsharp_batch_context_recv_status_on_client_details; + this.grpcsharp_batch_context_recv_status_on_client_error_string = DllImportsFromStaticLib.grpcsharp_batch_context_recv_status_on_client_error_string; + this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = DllImportsFromStaticLib.grpcsharp_batch_context_recv_status_on_client_trailing_metadata; + this.grpcsharp_batch_context_recv_close_on_server_cancelled = DllImportsFromStaticLib.grpcsharp_batch_context_recv_close_on_server_cancelled; + this.grpcsharp_batch_context_reset = DllImportsFromStaticLib.grpcsharp_batch_context_reset; + this.grpcsharp_batch_context_destroy = DllImportsFromStaticLib.grpcsharp_batch_context_destroy; + this.grpcsharp_request_call_context_create = DllImportsFromStaticLib.grpcsharp_request_call_context_create; + this.grpcsharp_request_call_context_call = DllImportsFromStaticLib.grpcsharp_request_call_context_call; + this.grpcsharp_request_call_context_method = DllImportsFromStaticLib.grpcsharp_request_call_context_method; + this.grpcsharp_request_call_context_host = DllImportsFromStaticLib.grpcsharp_request_call_context_host; + this.grpcsharp_request_call_context_deadline = DllImportsFromStaticLib.grpcsharp_request_call_context_deadline; + this.grpcsharp_request_call_context_request_metadata = DllImportsFromStaticLib.grpcsharp_request_call_context_request_metadata; + this.grpcsharp_request_call_context_reset = DllImportsFromStaticLib.grpcsharp_request_call_context_reset; + this.grpcsharp_request_call_context_destroy = DllImportsFromStaticLib.grpcsharp_request_call_context_destroy; + this.grpcsharp_composite_call_credentials_create = DllImportsFromStaticLib.grpcsharp_composite_call_credentials_create; + this.grpcsharp_call_credentials_release = DllImportsFromStaticLib.grpcsharp_call_credentials_release; + this.grpcsharp_call_cancel = DllImportsFromStaticLib.grpcsharp_call_cancel; + this.grpcsharp_call_cancel_with_status = DllImportsFromStaticLib.grpcsharp_call_cancel_with_status; + this.grpcsharp_call_start_unary = DllImportsFromStaticLib.grpcsharp_call_start_unary; + this.grpcsharp_call_start_client_streaming = DllImportsFromStaticLib.grpcsharp_call_start_client_streaming; + this.grpcsharp_call_start_server_streaming = DllImportsFromStaticLib.grpcsharp_call_start_server_streaming; + this.grpcsharp_call_start_duplex_streaming = DllImportsFromStaticLib.grpcsharp_call_start_duplex_streaming; + this.grpcsharp_call_send_message = DllImportsFromStaticLib.grpcsharp_call_send_message; + this.grpcsharp_call_send_close_from_client = DllImportsFromStaticLib.grpcsharp_call_send_close_from_client; + this.grpcsharp_call_send_status_from_server = DllImportsFromStaticLib.grpcsharp_call_send_status_from_server; + this.grpcsharp_call_recv_message = DllImportsFromStaticLib.grpcsharp_call_recv_message; + this.grpcsharp_call_recv_initial_metadata = DllImportsFromStaticLib.grpcsharp_call_recv_initial_metadata; + this.grpcsharp_call_start_serverside = DllImportsFromStaticLib.grpcsharp_call_start_serverside; + this.grpcsharp_call_send_initial_metadata = DllImportsFromStaticLib.grpcsharp_call_send_initial_metadata; + this.grpcsharp_call_set_credentials = DllImportsFromStaticLib.grpcsharp_call_set_credentials; + this.grpcsharp_call_get_peer = DllImportsFromStaticLib.grpcsharp_call_get_peer; + this.grpcsharp_call_destroy = DllImportsFromStaticLib.grpcsharp_call_destroy; + this.grpcsharp_channel_args_create = DllImportsFromStaticLib.grpcsharp_channel_args_create; + this.grpcsharp_channel_args_set_string = DllImportsFromStaticLib.grpcsharp_channel_args_set_string; + this.grpcsharp_channel_args_set_integer = DllImportsFromStaticLib.grpcsharp_channel_args_set_integer; + this.grpcsharp_channel_args_destroy = DllImportsFromStaticLib.grpcsharp_channel_args_destroy; + this.grpcsharp_override_default_ssl_roots = DllImportsFromStaticLib.grpcsharp_override_default_ssl_roots; + this.grpcsharp_ssl_credentials_create = DllImportsFromStaticLib.grpcsharp_ssl_credentials_create; + this.grpcsharp_composite_channel_credentials_create = DllImportsFromStaticLib.grpcsharp_composite_channel_credentials_create; + this.grpcsharp_channel_credentials_release = DllImportsFromStaticLib.grpcsharp_channel_credentials_release; + this.grpcsharp_insecure_channel_create = DllImportsFromStaticLib.grpcsharp_insecure_channel_create; + this.grpcsharp_secure_channel_create = DllImportsFromStaticLib.grpcsharp_secure_channel_create; + this.grpcsharp_channel_create_call = DllImportsFromStaticLib.grpcsharp_channel_create_call; + this.grpcsharp_channel_check_connectivity_state = DllImportsFromStaticLib.grpcsharp_channel_check_connectivity_state; + this.grpcsharp_channel_watch_connectivity_state = DllImportsFromStaticLib.grpcsharp_channel_watch_connectivity_state; + this.grpcsharp_channel_get_target = DllImportsFromStaticLib.grpcsharp_channel_get_target; + this.grpcsharp_channel_destroy = DllImportsFromStaticLib.grpcsharp_channel_destroy; + this.grpcsharp_sizeof_grpc_event = DllImportsFromStaticLib.grpcsharp_sizeof_grpc_event; + this.grpcsharp_completion_queue_create_async = DllImportsFromStaticLib.grpcsharp_completion_queue_create_async; + this.grpcsharp_completion_queue_create_sync = DllImportsFromStaticLib.grpcsharp_completion_queue_create_sync; + this.grpcsharp_completion_queue_shutdown = DllImportsFromStaticLib.grpcsharp_completion_queue_shutdown; + this.grpcsharp_completion_queue_next = DllImportsFromStaticLib.grpcsharp_completion_queue_next; + this.grpcsharp_completion_queue_pluck = DllImportsFromStaticLib.grpcsharp_completion_queue_pluck; + this.grpcsharp_completion_queue_destroy = DllImportsFromStaticLib.grpcsharp_completion_queue_destroy; + this.gprsharp_free = DllImportsFromStaticLib.gprsharp_free; + this.grpcsharp_metadata_array_create = DllImportsFromStaticLib.grpcsharp_metadata_array_create; + this.grpcsharp_metadata_array_add = DllImportsFromStaticLib.grpcsharp_metadata_array_add; + this.grpcsharp_metadata_array_count = DllImportsFromStaticLib.grpcsharp_metadata_array_count; + this.grpcsharp_metadata_array_get_key = DllImportsFromStaticLib.grpcsharp_metadata_array_get_key; + this.grpcsharp_metadata_array_get_value = DllImportsFromStaticLib.grpcsharp_metadata_array_get_value; + this.grpcsharp_metadata_array_destroy_full = DllImportsFromStaticLib.grpcsharp_metadata_array_destroy_full; + this.grpcsharp_redirect_log = DllImportsFromStaticLib.grpcsharp_redirect_log; + this.grpcsharp_native_callback_dispatcher_init = DllImportsFromStaticLib.grpcsharp_native_callback_dispatcher_init; + this.grpcsharp_metadata_credentials_create_from_plugin = DllImportsFromStaticLib.grpcsharp_metadata_credentials_create_from_plugin; + this.grpcsharp_metadata_credentials_notify_from_plugin = DllImportsFromStaticLib.grpcsharp_metadata_credentials_notify_from_plugin; + this.grpcsharp_ssl_server_credentials_create = DllImportsFromStaticLib.grpcsharp_ssl_server_credentials_create; + this.grpcsharp_server_credentials_release = DllImportsFromStaticLib.grpcsharp_server_credentials_release; + this.grpcsharp_server_create = DllImportsFromStaticLib.grpcsharp_server_create; + this.grpcsharp_server_register_completion_queue = DllImportsFromStaticLib.grpcsharp_server_register_completion_queue; + this.grpcsharp_server_add_insecure_http2_port = DllImportsFromStaticLib.grpcsharp_server_add_insecure_http2_port; + this.grpcsharp_server_add_secure_http2_port = DllImportsFromStaticLib.grpcsharp_server_add_secure_http2_port; + this.grpcsharp_server_start = DllImportsFromStaticLib.grpcsharp_server_start; + this.grpcsharp_server_request_call = DllImportsFromStaticLib.grpcsharp_server_request_call; + this.grpcsharp_server_cancel_all_calls = DllImportsFromStaticLib.grpcsharp_server_cancel_all_calls; + this.grpcsharp_server_shutdown_and_notify_callback = DllImportsFromStaticLib.grpcsharp_server_shutdown_and_notify_callback; + this.grpcsharp_server_destroy = DllImportsFromStaticLib.grpcsharp_server_destroy; + this.grpcsharp_call_auth_context = DllImportsFromStaticLib.grpcsharp_call_auth_context; + this.grpcsharp_auth_context_peer_identity_property_name = DllImportsFromStaticLib.grpcsharp_auth_context_peer_identity_property_name; + this.grpcsharp_auth_context_property_iterator = DllImportsFromStaticLib.grpcsharp_auth_context_property_iterator; + this.grpcsharp_auth_property_iterator_next = DllImportsFromStaticLib.grpcsharp_auth_property_iterator_next; + this.grpcsharp_auth_context_release = DllImportsFromStaticLib.grpcsharp_auth_context_release; + this.grpcsharp_slice_buffer_create = DllImportsFromStaticLib.grpcsharp_slice_buffer_create; + this.grpcsharp_slice_buffer_adjust_tail_space = DllImportsFromStaticLib.grpcsharp_slice_buffer_adjust_tail_space; + this.grpcsharp_slice_buffer_slice_count = DllImportsFromStaticLib.grpcsharp_slice_buffer_slice_count; + this.grpcsharp_slice_buffer_slice_peek = DllImportsFromStaticLib.grpcsharp_slice_buffer_slice_peek; + this.grpcsharp_slice_buffer_reset_and_unref = DllImportsFromStaticLib.grpcsharp_slice_buffer_reset_and_unref; + this.grpcsharp_slice_buffer_destroy = DllImportsFromStaticLib.grpcsharp_slice_buffer_destroy; + this.gprsharp_now = DllImportsFromStaticLib.gprsharp_now; + this.gprsharp_inf_future = DllImportsFromStaticLib.gprsharp_inf_future; + this.gprsharp_inf_past = DllImportsFromStaticLib.gprsharp_inf_past; + this.gprsharp_convert_clock_type = DllImportsFromStaticLib.gprsharp_convert_clock_type; + this.gprsharp_sizeof_timespec = DllImportsFromStaticLib.gprsharp_sizeof_timespec; + this.grpcsharp_test_callback = DllImportsFromStaticLib.grpcsharp_test_callback; + this.grpcsharp_test_nop = DllImportsFromStaticLib.grpcsharp_test_nop; + this.grpcsharp_test_override_method = DllImportsFromStaticLib.grpcsharp_test_override_method; + this.grpcsharp_test_call_start_unary_echo = DllImportsFromStaticLib.grpcsharp_test_call_start_unary_echo; + } + + public NativeMethods(DllImportsFromSharedLib unusedInstance) + { + this.grpcsharp_init = DllImportsFromSharedLib.grpcsharp_init; + this.grpcsharp_shutdown = DllImportsFromSharedLib.grpcsharp_shutdown; + this.grpcsharp_version_string = DllImportsFromSharedLib.grpcsharp_version_string; + this.grpcsharp_batch_context_create = DllImportsFromSharedLib.grpcsharp_batch_context_create; + this.grpcsharp_batch_context_recv_initial_metadata = DllImportsFromSharedLib.grpcsharp_batch_context_recv_initial_metadata; + this.grpcsharp_batch_context_recv_message_length = DllImportsFromSharedLib.grpcsharp_batch_context_recv_message_length; + this.grpcsharp_batch_context_recv_message_next_slice_peek = DllImportsFromSharedLib.grpcsharp_batch_context_recv_message_next_slice_peek; + this.grpcsharp_batch_context_recv_status_on_client_status = DllImportsFromSharedLib.grpcsharp_batch_context_recv_status_on_client_status; + this.grpcsharp_batch_context_recv_status_on_client_details = DllImportsFromSharedLib.grpcsharp_batch_context_recv_status_on_client_details; + this.grpcsharp_batch_context_recv_status_on_client_error_string = DllImportsFromSharedLib.grpcsharp_batch_context_recv_status_on_client_error_string; + this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = DllImportsFromSharedLib.grpcsharp_batch_context_recv_status_on_client_trailing_metadata; + this.grpcsharp_batch_context_recv_close_on_server_cancelled = DllImportsFromSharedLib.grpcsharp_batch_context_recv_close_on_server_cancelled; + this.grpcsharp_batch_context_reset = DllImportsFromSharedLib.grpcsharp_batch_context_reset; + this.grpcsharp_batch_context_destroy = DllImportsFromSharedLib.grpcsharp_batch_context_destroy; + this.grpcsharp_request_call_context_create = DllImportsFromSharedLib.grpcsharp_request_call_context_create; + this.grpcsharp_request_call_context_call = DllImportsFromSharedLib.grpcsharp_request_call_context_call; + this.grpcsharp_request_call_context_method = DllImportsFromSharedLib.grpcsharp_request_call_context_method; + this.grpcsharp_request_call_context_host = DllImportsFromSharedLib.grpcsharp_request_call_context_host; + this.grpcsharp_request_call_context_deadline = DllImportsFromSharedLib.grpcsharp_request_call_context_deadline; + this.grpcsharp_request_call_context_request_metadata = DllImportsFromSharedLib.grpcsharp_request_call_context_request_metadata; + this.grpcsharp_request_call_context_reset = DllImportsFromSharedLib.grpcsharp_request_call_context_reset; + this.grpcsharp_request_call_context_destroy = DllImportsFromSharedLib.grpcsharp_request_call_context_destroy; + this.grpcsharp_composite_call_credentials_create = DllImportsFromSharedLib.grpcsharp_composite_call_credentials_create; + this.grpcsharp_call_credentials_release = DllImportsFromSharedLib.grpcsharp_call_credentials_release; + this.grpcsharp_call_cancel = DllImportsFromSharedLib.grpcsharp_call_cancel; + this.grpcsharp_call_cancel_with_status = DllImportsFromSharedLib.grpcsharp_call_cancel_with_status; + this.grpcsharp_call_start_unary = DllImportsFromSharedLib.grpcsharp_call_start_unary; + this.grpcsharp_call_start_client_streaming = DllImportsFromSharedLib.grpcsharp_call_start_client_streaming; + this.grpcsharp_call_start_server_streaming = DllImportsFromSharedLib.grpcsharp_call_start_server_streaming; + this.grpcsharp_call_start_duplex_streaming = DllImportsFromSharedLib.grpcsharp_call_start_duplex_streaming; + this.grpcsharp_call_send_message = DllImportsFromSharedLib.grpcsharp_call_send_message; + this.grpcsharp_call_send_close_from_client = DllImportsFromSharedLib.grpcsharp_call_send_close_from_client; + this.grpcsharp_call_send_status_from_server = DllImportsFromSharedLib.grpcsharp_call_send_status_from_server; + this.grpcsharp_call_recv_message = DllImportsFromSharedLib.grpcsharp_call_recv_message; + this.grpcsharp_call_recv_initial_metadata = DllImportsFromSharedLib.grpcsharp_call_recv_initial_metadata; + this.grpcsharp_call_start_serverside = DllImportsFromSharedLib.grpcsharp_call_start_serverside; + this.grpcsharp_call_send_initial_metadata = DllImportsFromSharedLib.grpcsharp_call_send_initial_metadata; + this.grpcsharp_call_set_credentials = DllImportsFromSharedLib.grpcsharp_call_set_credentials; + this.grpcsharp_call_get_peer = DllImportsFromSharedLib.grpcsharp_call_get_peer; + this.grpcsharp_call_destroy = DllImportsFromSharedLib.grpcsharp_call_destroy; + this.grpcsharp_channel_args_create = DllImportsFromSharedLib.grpcsharp_channel_args_create; + this.grpcsharp_channel_args_set_string = DllImportsFromSharedLib.grpcsharp_channel_args_set_string; + this.grpcsharp_channel_args_set_integer = DllImportsFromSharedLib.grpcsharp_channel_args_set_integer; + this.grpcsharp_channel_args_destroy = DllImportsFromSharedLib.grpcsharp_channel_args_destroy; + this.grpcsharp_override_default_ssl_roots = DllImportsFromSharedLib.grpcsharp_override_default_ssl_roots; + this.grpcsharp_ssl_credentials_create = DllImportsFromSharedLib.grpcsharp_ssl_credentials_create; + this.grpcsharp_composite_channel_credentials_create = DllImportsFromSharedLib.grpcsharp_composite_channel_credentials_create; + this.grpcsharp_channel_credentials_release = DllImportsFromSharedLib.grpcsharp_channel_credentials_release; + this.grpcsharp_insecure_channel_create = DllImportsFromSharedLib.grpcsharp_insecure_channel_create; + this.grpcsharp_secure_channel_create = DllImportsFromSharedLib.grpcsharp_secure_channel_create; + this.grpcsharp_channel_create_call = DllImportsFromSharedLib.grpcsharp_channel_create_call; + this.grpcsharp_channel_check_connectivity_state = DllImportsFromSharedLib.grpcsharp_channel_check_connectivity_state; + this.grpcsharp_channel_watch_connectivity_state = DllImportsFromSharedLib.grpcsharp_channel_watch_connectivity_state; + this.grpcsharp_channel_get_target = DllImportsFromSharedLib.grpcsharp_channel_get_target; + this.grpcsharp_channel_destroy = DllImportsFromSharedLib.grpcsharp_channel_destroy; + this.grpcsharp_sizeof_grpc_event = DllImportsFromSharedLib.grpcsharp_sizeof_grpc_event; + this.grpcsharp_completion_queue_create_async = DllImportsFromSharedLib.grpcsharp_completion_queue_create_async; + this.grpcsharp_completion_queue_create_sync = DllImportsFromSharedLib.grpcsharp_completion_queue_create_sync; + this.grpcsharp_completion_queue_shutdown = DllImportsFromSharedLib.grpcsharp_completion_queue_shutdown; + this.grpcsharp_completion_queue_next = DllImportsFromSharedLib.grpcsharp_completion_queue_next; + this.grpcsharp_completion_queue_pluck = DllImportsFromSharedLib.grpcsharp_completion_queue_pluck; + this.grpcsharp_completion_queue_destroy = DllImportsFromSharedLib.grpcsharp_completion_queue_destroy; + this.gprsharp_free = DllImportsFromSharedLib.gprsharp_free; + this.grpcsharp_metadata_array_create = DllImportsFromSharedLib.grpcsharp_metadata_array_create; + this.grpcsharp_metadata_array_add = DllImportsFromSharedLib.grpcsharp_metadata_array_add; + this.grpcsharp_metadata_array_count = DllImportsFromSharedLib.grpcsharp_metadata_array_count; + this.grpcsharp_metadata_array_get_key = DllImportsFromSharedLib.grpcsharp_metadata_array_get_key; + this.grpcsharp_metadata_array_get_value = DllImportsFromSharedLib.grpcsharp_metadata_array_get_value; + this.grpcsharp_metadata_array_destroy_full = DllImportsFromSharedLib.grpcsharp_metadata_array_destroy_full; + this.grpcsharp_redirect_log = DllImportsFromSharedLib.grpcsharp_redirect_log; + this.grpcsharp_native_callback_dispatcher_init = DllImportsFromSharedLib.grpcsharp_native_callback_dispatcher_init; + this.grpcsharp_metadata_credentials_create_from_plugin = DllImportsFromSharedLib.grpcsharp_metadata_credentials_create_from_plugin; + this.grpcsharp_metadata_credentials_notify_from_plugin = DllImportsFromSharedLib.grpcsharp_metadata_credentials_notify_from_plugin; + this.grpcsharp_ssl_server_credentials_create = DllImportsFromSharedLib.grpcsharp_ssl_server_credentials_create; + this.grpcsharp_server_credentials_release = DllImportsFromSharedLib.grpcsharp_server_credentials_release; + this.grpcsharp_server_create = DllImportsFromSharedLib.grpcsharp_server_create; + this.grpcsharp_server_register_completion_queue = DllImportsFromSharedLib.grpcsharp_server_register_completion_queue; + this.grpcsharp_server_add_insecure_http2_port = DllImportsFromSharedLib.grpcsharp_server_add_insecure_http2_port; + this.grpcsharp_server_add_secure_http2_port = DllImportsFromSharedLib.grpcsharp_server_add_secure_http2_port; + this.grpcsharp_server_start = DllImportsFromSharedLib.grpcsharp_server_start; + this.grpcsharp_server_request_call = DllImportsFromSharedLib.grpcsharp_server_request_call; + this.grpcsharp_server_cancel_all_calls = DllImportsFromSharedLib.grpcsharp_server_cancel_all_calls; + this.grpcsharp_server_shutdown_and_notify_callback = DllImportsFromSharedLib.grpcsharp_server_shutdown_and_notify_callback; + this.grpcsharp_server_destroy = DllImportsFromSharedLib.grpcsharp_server_destroy; + this.grpcsharp_call_auth_context = DllImportsFromSharedLib.grpcsharp_call_auth_context; + this.grpcsharp_auth_context_peer_identity_property_name = DllImportsFromSharedLib.grpcsharp_auth_context_peer_identity_property_name; + this.grpcsharp_auth_context_property_iterator = DllImportsFromSharedLib.grpcsharp_auth_context_property_iterator; + this.grpcsharp_auth_property_iterator_next = DllImportsFromSharedLib.grpcsharp_auth_property_iterator_next; + this.grpcsharp_auth_context_release = DllImportsFromSharedLib.grpcsharp_auth_context_release; + this.grpcsharp_slice_buffer_create = DllImportsFromSharedLib.grpcsharp_slice_buffer_create; + this.grpcsharp_slice_buffer_adjust_tail_space = DllImportsFromSharedLib.grpcsharp_slice_buffer_adjust_tail_space; + this.grpcsharp_slice_buffer_slice_count = DllImportsFromSharedLib.grpcsharp_slice_buffer_slice_count; + this.grpcsharp_slice_buffer_slice_peek = DllImportsFromSharedLib.grpcsharp_slice_buffer_slice_peek; + this.grpcsharp_slice_buffer_reset_and_unref = DllImportsFromSharedLib.grpcsharp_slice_buffer_reset_and_unref; + this.grpcsharp_slice_buffer_destroy = DllImportsFromSharedLib.grpcsharp_slice_buffer_destroy; + this.gprsharp_now = DllImportsFromSharedLib.gprsharp_now; + this.gprsharp_inf_future = DllImportsFromSharedLib.gprsharp_inf_future; + this.gprsharp_inf_past = DllImportsFromSharedLib.gprsharp_inf_past; + this.gprsharp_convert_clock_type = DllImportsFromSharedLib.gprsharp_convert_clock_type; + this.gprsharp_sizeof_timespec = DllImportsFromSharedLib.gprsharp_sizeof_timespec; + this.grpcsharp_test_callback = DllImportsFromSharedLib.grpcsharp_test_callback; + this.grpcsharp_test_nop = DllImportsFromSharedLib.grpcsharp_test_nop; + this.grpcsharp_test_override_method = DllImportsFromSharedLib.grpcsharp_test_override_method; + this.grpcsharp_test_call_start_unary_echo = DllImportsFromSharedLib.grpcsharp_test_call_start_unary_echo; + } + + public NativeMethods(DllImportsFromSharedLib_x86 unusedInstance) + { + this.grpcsharp_init = DllImportsFromSharedLib_x86.grpcsharp_init; + this.grpcsharp_shutdown = DllImportsFromSharedLib_x86.grpcsharp_shutdown; + this.grpcsharp_version_string = DllImportsFromSharedLib_x86.grpcsharp_version_string; + this.grpcsharp_batch_context_create = DllImportsFromSharedLib_x86.grpcsharp_batch_context_create; + this.grpcsharp_batch_context_recv_initial_metadata = DllImportsFromSharedLib_x86.grpcsharp_batch_context_recv_initial_metadata; + this.grpcsharp_batch_context_recv_message_length = DllImportsFromSharedLib_x86.grpcsharp_batch_context_recv_message_length; + this.grpcsharp_batch_context_recv_message_next_slice_peek = DllImportsFromSharedLib_x86.grpcsharp_batch_context_recv_message_next_slice_peek; + this.grpcsharp_batch_context_recv_status_on_client_status = DllImportsFromSharedLib_x86.grpcsharp_batch_context_recv_status_on_client_status; + this.grpcsharp_batch_context_recv_status_on_client_details = DllImportsFromSharedLib_x86.grpcsharp_batch_context_recv_status_on_client_details; + this.grpcsharp_batch_context_recv_status_on_client_error_string = DllImportsFromSharedLib_x86.grpcsharp_batch_context_recv_status_on_client_error_string; + this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = DllImportsFromSharedLib_x86.grpcsharp_batch_context_recv_status_on_client_trailing_metadata; + this.grpcsharp_batch_context_recv_close_on_server_cancelled = DllImportsFromSharedLib_x86.grpcsharp_batch_context_recv_close_on_server_cancelled; + this.grpcsharp_batch_context_reset = DllImportsFromSharedLib_x86.grpcsharp_batch_context_reset; + this.grpcsharp_batch_context_destroy = DllImportsFromSharedLib_x86.grpcsharp_batch_context_destroy; + this.grpcsharp_request_call_context_create = DllImportsFromSharedLib_x86.grpcsharp_request_call_context_create; + this.grpcsharp_request_call_context_call = DllImportsFromSharedLib_x86.grpcsharp_request_call_context_call; + this.grpcsharp_request_call_context_method = DllImportsFromSharedLib_x86.grpcsharp_request_call_context_method; + this.grpcsharp_request_call_context_host = DllImportsFromSharedLib_x86.grpcsharp_request_call_context_host; + this.grpcsharp_request_call_context_deadline = DllImportsFromSharedLib_x86.grpcsharp_request_call_context_deadline; + this.grpcsharp_request_call_context_request_metadata = DllImportsFromSharedLib_x86.grpcsharp_request_call_context_request_metadata; + this.grpcsharp_request_call_context_reset = DllImportsFromSharedLib_x86.grpcsharp_request_call_context_reset; + this.grpcsharp_request_call_context_destroy = DllImportsFromSharedLib_x86.grpcsharp_request_call_context_destroy; + this.grpcsharp_composite_call_credentials_create = DllImportsFromSharedLib_x86.grpcsharp_composite_call_credentials_create; + this.grpcsharp_call_credentials_release = DllImportsFromSharedLib_x86.grpcsharp_call_credentials_release; + this.grpcsharp_call_cancel = DllImportsFromSharedLib_x86.grpcsharp_call_cancel; + this.grpcsharp_call_cancel_with_status = DllImportsFromSharedLib_x86.grpcsharp_call_cancel_with_status; + this.grpcsharp_call_start_unary = DllImportsFromSharedLib_x86.grpcsharp_call_start_unary; + this.grpcsharp_call_start_client_streaming = DllImportsFromSharedLib_x86.grpcsharp_call_start_client_streaming; + this.grpcsharp_call_start_server_streaming = DllImportsFromSharedLib_x86.grpcsharp_call_start_server_streaming; + this.grpcsharp_call_start_duplex_streaming = DllImportsFromSharedLib_x86.grpcsharp_call_start_duplex_streaming; + this.grpcsharp_call_send_message = DllImportsFromSharedLib_x86.grpcsharp_call_send_message; + this.grpcsharp_call_send_close_from_client = DllImportsFromSharedLib_x86.grpcsharp_call_send_close_from_client; + this.grpcsharp_call_send_status_from_server = DllImportsFromSharedLib_x86.grpcsharp_call_send_status_from_server; + this.grpcsharp_call_recv_message = DllImportsFromSharedLib_x86.grpcsharp_call_recv_message; + this.grpcsharp_call_recv_initial_metadata = DllImportsFromSharedLib_x86.grpcsharp_call_recv_initial_metadata; + this.grpcsharp_call_start_serverside = DllImportsFromSharedLib_x86.grpcsharp_call_start_serverside; + this.grpcsharp_call_send_initial_metadata = DllImportsFromSharedLib_x86.grpcsharp_call_send_initial_metadata; + this.grpcsharp_call_set_credentials = DllImportsFromSharedLib_x86.grpcsharp_call_set_credentials; + this.grpcsharp_call_get_peer = DllImportsFromSharedLib_x86.grpcsharp_call_get_peer; + this.grpcsharp_call_destroy = DllImportsFromSharedLib_x86.grpcsharp_call_destroy; + this.grpcsharp_channel_args_create = DllImportsFromSharedLib_x86.grpcsharp_channel_args_create; + this.grpcsharp_channel_args_set_string = DllImportsFromSharedLib_x86.grpcsharp_channel_args_set_string; + this.grpcsharp_channel_args_set_integer = DllImportsFromSharedLib_x86.grpcsharp_channel_args_set_integer; + this.grpcsharp_channel_args_destroy = DllImportsFromSharedLib_x86.grpcsharp_channel_args_destroy; + this.grpcsharp_override_default_ssl_roots = DllImportsFromSharedLib_x86.grpcsharp_override_default_ssl_roots; + this.grpcsharp_ssl_credentials_create = DllImportsFromSharedLib_x86.grpcsharp_ssl_credentials_create; + this.grpcsharp_composite_channel_credentials_create = DllImportsFromSharedLib_x86.grpcsharp_composite_channel_credentials_create; + this.grpcsharp_channel_credentials_release = DllImportsFromSharedLib_x86.grpcsharp_channel_credentials_release; + this.grpcsharp_insecure_channel_create = DllImportsFromSharedLib_x86.grpcsharp_insecure_channel_create; + this.grpcsharp_secure_channel_create = DllImportsFromSharedLib_x86.grpcsharp_secure_channel_create; + this.grpcsharp_channel_create_call = DllImportsFromSharedLib_x86.grpcsharp_channel_create_call; + this.grpcsharp_channel_check_connectivity_state = DllImportsFromSharedLib_x86.grpcsharp_channel_check_connectivity_state; + this.grpcsharp_channel_watch_connectivity_state = DllImportsFromSharedLib_x86.grpcsharp_channel_watch_connectivity_state; + this.grpcsharp_channel_get_target = DllImportsFromSharedLib_x86.grpcsharp_channel_get_target; + this.grpcsharp_channel_destroy = DllImportsFromSharedLib_x86.grpcsharp_channel_destroy; + this.grpcsharp_sizeof_grpc_event = DllImportsFromSharedLib_x86.grpcsharp_sizeof_grpc_event; + this.grpcsharp_completion_queue_create_async = DllImportsFromSharedLib_x86.grpcsharp_completion_queue_create_async; + this.grpcsharp_completion_queue_create_sync = DllImportsFromSharedLib_x86.grpcsharp_completion_queue_create_sync; + this.grpcsharp_completion_queue_shutdown = DllImportsFromSharedLib_x86.grpcsharp_completion_queue_shutdown; + this.grpcsharp_completion_queue_next = DllImportsFromSharedLib_x86.grpcsharp_completion_queue_next; + this.grpcsharp_completion_queue_pluck = DllImportsFromSharedLib_x86.grpcsharp_completion_queue_pluck; + this.grpcsharp_completion_queue_destroy = DllImportsFromSharedLib_x86.grpcsharp_completion_queue_destroy; + this.gprsharp_free = DllImportsFromSharedLib_x86.gprsharp_free; + this.grpcsharp_metadata_array_create = DllImportsFromSharedLib_x86.grpcsharp_metadata_array_create; + this.grpcsharp_metadata_array_add = DllImportsFromSharedLib_x86.grpcsharp_metadata_array_add; + this.grpcsharp_metadata_array_count = DllImportsFromSharedLib_x86.grpcsharp_metadata_array_count; + this.grpcsharp_metadata_array_get_key = DllImportsFromSharedLib_x86.grpcsharp_metadata_array_get_key; + this.grpcsharp_metadata_array_get_value = DllImportsFromSharedLib_x86.grpcsharp_metadata_array_get_value; + this.grpcsharp_metadata_array_destroy_full = DllImportsFromSharedLib_x86.grpcsharp_metadata_array_destroy_full; + this.grpcsharp_redirect_log = DllImportsFromSharedLib_x86.grpcsharp_redirect_log; + this.grpcsharp_native_callback_dispatcher_init = DllImportsFromSharedLib_x86.grpcsharp_native_callback_dispatcher_init; + this.grpcsharp_metadata_credentials_create_from_plugin = DllImportsFromSharedLib_x86.grpcsharp_metadata_credentials_create_from_plugin; + this.grpcsharp_metadata_credentials_notify_from_plugin = DllImportsFromSharedLib_x86.grpcsharp_metadata_credentials_notify_from_plugin; + this.grpcsharp_ssl_server_credentials_create = DllImportsFromSharedLib_x86.grpcsharp_ssl_server_credentials_create; + this.grpcsharp_server_credentials_release = DllImportsFromSharedLib_x86.grpcsharp_server_credentials_release; + this.grpcsharp_server_create = DllImportsFromSharedLib_x86.grpcsharp_server_create; + this.grpcsharp_server_register_completion_queue = DllImportsFromSharedLib_x86.grpcsharp_server_register_completion_queue; + this.grpcsharp_server_add_insecure_http2_port = DllImportsFromSharedLib_x86.grpcsharp_server_add_insecure_http2_port; + this.grpcsharp_server_add_secure_http2_port = DllImportsFromSharedLib_x86.grpcsharp_server_add_secure_http2_port; + this.grpcsharp_server_start = DllImportsFromSharedLib_x86.grpcsharp_server_start; + this.grpcsharp_server_request_call = DllImportsFromSharedLib_x86.grpcsharp_server_request_call; + this.grpcsharp_server_cancel_all_calls = DllImportsFromSharedLib_x86.grpcsharp_server_cancel_all_calls; + this.grpcsharp_server_shutdown_and_notify_callback = DllImportsFromSharedLib_x86.grpcsharp_server_shutdown_and_notify_callback; + this.grpcsharp_server_destroy = DllImportsFromSharedLib_x86.grpcsharp_server_destroy; + this.grpcsharp_call_auth_context = DllImportsFromSharedLib_x86.grpcsharp_call_auth_context; + this.grpcsharp_auth_context_peer_identity_property_name = DllImportsFromSharedLib_x86.grpcsharp_auth_context_peer_identity_property_name; + this.grpcsharp_auth_context_property_iterator = DllImportsFromSharedLib_x86.grpcsharp_auth_context_property_iterator; + this.grpcsharp_auth_property_iterator_next = DllImportsFromSharedLib_x86.grpcsharp_auth_property_iterator_next; + this.grpcsharp_auth_context_release = DllImportsFromSharedLib_x86.grpcsharp_auth_context_release; + this.grpcsharp_slice_buffer_create = DllImportsFromSharedLib_x86.grpcsharp_slice_buffer_create; + this.grpcsharp_slice_buffer_adjust_tail_space = DllImportsFromSharedLib_x86.grpcsharp_slice_buffer_adjust_tail_space; + this.grpcsharp_slice_buffer_slice_count = DllImportsFromSharedLib_x86.grpcsharp_slice_buffer_slice_count; + this.grpcsharp_slice_buffer_slice_peek = DllImportsFromSharedLib_x86.grpcsharp_slice_buffer_slice_peek; + this.grpcsharp_slice_buffer_reset_and_unref = DllImportsFromSharedLib_x86.grpcsharp_slice_buffer_reset_and_unref; + this.grpcsharp_slice_buffer_destroy = DllImportsFromSharedLib_x86.grpcsharp_slice_buffer_destroy; + this.gprsharp_now = DllImportsFromSharedLib_x86.gprsharp_now; + this.gprsharp_inf_future = DllImportsFromSharedLib_x86.gprsharp_inf_future; + this.gprsharp_inf_past = DllImportsFromSharedLib_x86.gprsharp_inf_past; + this.gprsharp_convert_clock_type = DllImportsFromSharedLib_x86.gprsharp_convert_clock_type; + this.gprsharp_sizeof_timespec = DllImportsFromSharedLib_x86.gprsharp_sizeof_timespec; + this.grpcsharp_test_callback = DllImportsFromSharedLib_x86.grpcsharp_test_callback; + this.grpcsharp_test_nop = DllImportsFromSharedLib_x86.grpcsharp_test_nop; + this.grpcsharp_test_override_method = DllImportsFromSharedLib_x86.grpcsharp_test_override_method; + this.grpcsharp_test_call_start_unary_echo = DllImportsFromSharedLib_x86.grpcsharp_test_call_start_unary_echo; + } + + public NativeMethods(DllImportsFromSharedLib_x64 unusedInstance) + { + this.grpcsharp_init = DllImportsFromSharedLib_x64.grpcsharp_init; + this.grpcsharp_shutdown = DllImportsFromSharedLib_x64.grpcsharp_shutdown; + this.grpcsharp_version_string = DllImportsFromSharedLib_x64.grpcsharp_version_string; + this.grpcsharp_batch_context_create = DllImportsFromSharedLib_x64.grpcsharp_batch_context_create; + this.grpcsharp_batch_context_recv_initial_metadata = DllImportsFromSharedLib_x64.grpcsharp_batch_context_recv_initial_metadata; + this.grpcsharp_batch_context_recv_message_length = DllImportsFromSharedLib_x64.grpcsharp_batch_context_recv_message_length; + this.grpcsharp_batch_context_recv_message_next_slice_peek = DllImportsFromSharedLib_x64.grpcsharp_batch_context_recv_message_next_slice_peek; + this.grpcsharp_batch_context_recv_status_on_client_status = DllImportsFromSharedLib_x64.grpcsharp_batch_context_recv_status_on_client_status; + this.grpcsharp_batch_context_recv_status_on_client_details = DllImportsFromSharedLib_x64.grpcsharp_batch_context_recv_status_on_client_details; + this.grpcsharp_batch_context_recv_status_on_client_error_string = DllImportsFromSharedLib_x64.grpcsharp_batch_context_recv_status_on_client_error_string; + this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = DllImportsFromSharedLib_x64.grpcsharp_batch_context_recv_status_on_client_trailing_metadata; + this.grpcsharp_batch_context_recv_close_on_server_cancelled = DllImportsFromSharedLib_x64.grpcsharp_batch_context_recv_close_on_server_cancelled; + this.grpcsharp_batch_context_reset = DllImportsFromSharedLib_x64.grpcsharp_batch_context_reset; + this.grpcsharp_batch_context_destroy = DllImportsFromSharedLib_x64.grpcsharp_batch_context_destroy; + this.grpcsharp_request_call_context_create = DllImportsFromSharedLib_x64.grpcsharp_request_call_context_create; + this.grpcsharp_request_call_context_call = DllImportsFromSharedLib_x64.grpcsharp_request_call_context_call; + this.grpcsharp_request_call_context_method = DllImportsFromSharedLib_x64.grpcsharp_request_call_context_method; + this.grpcsharp_request_call_context_host = DllImportsFromSharedLib_x64.grpcsharp_request_call_context_host; + this.grpcsharp_request_call_context_deadline = DllImportsFromSharedLib_x64.grpcsharp_request_call_context_deadline; + this.grpcsharp_request_call_context_request_metadata = DllImportsFromSharedLib_x64.grpcsharp_request_call_context_request_metadata; + this.grpcsharp_request_call_context_reset = DllImportsFromSharedLib_x64.grpcsharp_request_call_context_reset; + this.grpcsharp_request_call_context_destroy = DllImportsFromSharedLib_x64.grpcsharp_request_call_context_destroy; + this.grpcsharp_composite_call_credentials_create = DllImportsFromSharedLib_x64.grpcsharp_composite_call_credentials_create; + this.grpcsharp_call_credentials_release = DllImportsFromSharedLib_x64.grpcsharp_call_credentials_release; + this.grpcsharp_call_cancel = DllImportsFromSharedLib_x64.grpcsharp_call_cancel; + this.grpcsharp_call_cancel_with_status = DllImportsFromSharedLib_x64.grpcsharp_call_cancel_with_status; + this.grpcsharp_call_start_unary = DllImportsFromSharedLib_x64.grpcsharp_call_start_unary; + this.grpcsharp_call_start_client_streaming = DllImportsFromSharedLib_x64.grpcsharp_call_start_client_streaming; + this.grpcsharp_call_start_server_streaming = DllImportsFromSharedLib_x64.grpcsharp_call_start_server_streaming; + this.grpcsharp_call_start_duplex_streaming = DllImportsFromSharedLib_x64.grpcsharp_call_start_duplex_streaming; + this.grpcsharp_call_send_message = DllImportsFromSharedLib_x64.grpcsharp_call_send_message; + this.grpcsharp_call_send_close_from_client = DllImportsFromSharedLib_x64.grpcsharp_call_send_close_from_client; + this.grpcsharp_call_send_status_from_server = DllImportsFromSharedLib_x64.grpcsharp_call_send_status_from_server; + this.grpcsharp_call_recv_message = DllImportsFromSharedLib_x64.grpcsharp_call_recv_message; + this.grpcsharp_call_recv_initial_metadata = DllImportsFromSharedLib_x64.grpcsharp_call_recv_initial_metadata; + this.grpcsharp_call_start_serverside = DllImportsFromSharedLib_x64.grpcsharp_call_start_serverside; + this.grpcsharp_call_send_initial_metadata = DllImportsFromSharedLib_x64.grpcsharp_call_send_initial_metadata; + this.grpcsharp_call_set_credentials = DllImportsFromSharedLib_x64.grpcsharp_call_set_credentials; + this.grpcsharp_call_get_peer = DllImportsFromSharedLib_x64.grpcsharp_call_get_peer; + this.grpcsharp_call_destroy = DllImportsFromSharedLib_x64.grpcsharp_call_destroy; + this.grpcsharp_channel_args_create = DllImportsFromSharedLib_x64.grpcsharp_channel_args_create; + this.grpcsharp_channel_args_set_string = DllImportsFromSharedLib_x64.grpcsharp_channel_args_set_string; + this.grpcsharp_channel_args_set_integer = DllImportsFromSharedLib_x64.grpcsharp_channel_args_set_integer; + this.grpcsharp_channel_args_destroy = DllImportsFromSharedLib_x64.grpcsharp_channel_args_destroy; + this.grpcsharp_override_default_ssl_roots = DllImportsFromSharedLib_x64.grpcsharp_override_default_ssl_roots; + this.grpcsharp_ssl_credentials_create = DllImportsFromSharedLib_x64.grpcsharp_ssl_credentials_create; + this.grpcsharp_composite_channel_credentials_create = DllImportsFromSharedLib_x64.grpcsharp_composite_channel_credentials_create; + this.grpcsharp_channel_credentials_release = DllImportsFromSharedLib_x64.grpcsharp_channel_credentials_release; + this.grpcsharp_insecure_channel_create = DllImportsFromSharedLib_x64.grpcsharp_insecure_channel_create; + this.grpcsharp_secure_channel_create = DllImportsFromSharedLib_x64.grpcsharp_secure_channel_create; + this.grpcsharp_channel_create_call = DllImportsFromSharedLib_x64.grpcsharp_channel_create_call; + this.grpcsharp_channel_check_connectivity_state = DllImportsFromSharedLib_x64.grpcsharp_channel_check_connectivity_state; + this.grpcsharp_channel_watch_connectivity_state = DllImportsFromSharedLib_x64.grpcsharp_channel_watch_connectivity_state; + this.grpcsharp_channel_get_target = DllImportsFromSharedLib_x64.grpcsharp_channel_get_target; + this.grpcsharp_channel_destroy = DllImportsFromSharedLib_x64.grpcsharp_channel_destroy; + this.grpcsharp_sizeof_grpc_event = DllImportsFromSharedLib_x64.grpcsharp_sizeof_grpc_event; + this.grpcsharp_completion_queue_create_async = DllImportsFromSharedLib_x64.grpcsharp_completion_queue_create_async; + this.grpcsharp_completion_queue_create_sync = DllImportsFromSharedLib_x64.grpcsharp_completion_queue_create_sync; + this.grpcsharp_completion_queue_shutdown = DllImportsFromSharedLib_x64.grpcsharp_completion_queue_shutdown; + this.grpcsharp_completion_queue_next = DllImportsFromSharedLib_x64.grpcsharp_completion_queue_next; + this.grpcsharp_completion_queue_pluck = DllImportsFromSharedLib_x64.grpcsharp_completion_queue_pluck; + this.grpcsharp_completion_queue_destroy = DllImportsFromSharedLib_x64.grpcsharp_completion_queue_destroy; + this.gprsharp_free = DllImportsFromSharedLib_x64.gprsharp_free; + this.grpcsharp_metadata_array_create = DllImportsFromSharedLib_x64.grpcsharp_metadata_array_create; + this.grpcsharp_metadata_array_add = DllImportsFromSharedLib_x64.grpcsharp_metadata_array_add; + this.grpcsharp_metadata_array_count = DllImportsFromSharedLib_x64.grpcsharp_metadata_array_count; + this.grpcsharp_metadata_array_get_key = DllImportsFromSharedLib_x64.grpcsharp_metadata_array_get_key; + this.grpcsharp_metadata_array_get_value = DllImportsFromSharedLib_x64.grpcsharp_metadata_array_get_value; + this.grpcsharp_metadata_array_destroy_full = DllImportsFromSharedLib_x64.grpcsharp_metadata_array_destroy_full; + this.grpcsharp_redirect_log = DllImportsFromSharedLib_x64.grpcsharp_redirect_log; + this.grpcsharp_native_callback_dispatcher_init = DllImportsFromSharedLib_x64.grpcsharp_native_callback_dispatcher_init; + this.grpcsharp_metadata_credentials_create_from_plugin = DllImportsFromSharedLib_x64.grpcsharp_metadata_credentials_create_from_plugin; + this.grpcsharp_metadata_credentials_notify_from_plugin = DllImportsFromSharedLib_x64.grpcsharp_metadata_credentials_notify_from_plugin; + this.grpcsharp_ssl_server_credentials_create = DllImportsFromSharedLib_x64.grpcsharp_ssl_server_credentials_create; + this.grpcsharp_server_credentials_release = DllImportsFromSharedLib_x64.grpcsharp_server_credentials_release; + this.grpcsharp_server_create = DllImportsFromSharedLib_x64.grpcsharp_server_create; + this.grpcsharp_server_register_completion_queue = DllImportsFromSharedLib_x64.grpcsharp_server_register_completion_queue; + this.grpcsharp_server_add_insecure_http2_port = DllImportsFromSharedLib_x64.grpcsharp_server_add_insecure_http2_port; + this.grpcsharp_server_add_secure_http2_port = DllImportsFromSharedLib_x64.grpcsharp_server_add_secure_http2_port; + this.grpcsharp_server_start = DllImportsFromSharedLib_x64.grpcsharp_server_start; + this.grpcsharp_server_request_call = DllImportsFromSharedLib_x64.grpcsharp_server_request_call; + this.grpcsharp_server_cancel_all_calls = DllImportsFromSharedLib_x64.grpcsharp_server_cancel_all_calls; + this.grpcsharp_server_shutdown_and_notify_callback = DllImportsFromSharedLib_x64.grpcsharp_server_shutdown_and_notify_callback; + this.grpcsharp_server_destroy = DllImportsFromSharedLib_x64.grpcsharp_server_destroy; + this.grpcsharp_call_auth_context = DllImportsFromSharedLib_x64.grpcsharp_call_auth_context; + this.grpcsharp_auth_context_peer_identity_property_name = DllImportsFromSharedLib_x64.grpcsharp_auth_context_peer_identity_property_name; + this.grpcsharp_auth_context_property_iterator = DllImportsFromSharedLib_x64.grpcsharp_auth_context_property_iterator; + this.grpcsharp_auth_property_iterator_next = DllImportsFromSharedLib_x64.grpcsharp_auth_property_iterator_next; + this.grpcsharp_auth_context_release = DllImportsFromSharedLib_x64.grpcsharp_auth_context_release; + this.grpcsharp_slice_buffer_create = DllImportsFromSharedLib_x64.grpcsharp_slice_buffer_create; + this.grpcsharp_slice_buffer_adjust_tail_space = DllImportsFromSharedLib_x64.grpcsharp_slice_buffer_adjust_tail_space; + this.grpcsharp_slice_buffer_slice_count = DllImportsFromSharedLib_x64.grpcsharp_slice_buffer_slice_count; + this.grpcsharp_slice_buffer_slice_peek = DllImportsFromSharedLib_x64.grpcsharp_slice_buffer_slice_peek; + this.grpcsharp_slice_buffer_reset_and_unref = DllImportsFromSharedLib_x64.grpcsharp_slice_buffer_reset_and_unref; + this.grpcsharp_slice_buffer_destroy = DllImportsFromSharedLib_x64.grpcsharp_slice_buffer_destroy; + this.gprsharp_now = DllImportsFromSharedLib_x64.gprsharp_now; + this.gprsharp_inf_future = DllImportsFromSharedLib_x64.gprsharp_inf_future; + this.gprsharp_inf_past = DllImportsFromSharedLib_x64.gprsharp_inf_past; + this.gprsharp_convert_clock_type = DllImportsFromSharedLib_x64.gprsharp_convert_clock_type; + this.gprsharp_sizeof_timespec = DllImportsFromSharedLib_x64.gprsharp_sizeof_timespec; + this.grpcsharp_test_callback = DllImportsFromSharedLib_x64.grpcsharp_test_callback; + this.grpcsharp_test_nop = DllImportsFromSharedLib_x64.grpcsharp_test_nop; + this.grpcsharp_test_override_method = DllImportsFromSharedLib_x64.grpcsharp_test_override_method; + this.grpcsharp_test_call_start_unary_echo = DllImportsFromSharedLib_x64.grpcsharp_test_call_start_unary_echo; + } + + public NativeMethods(DllImportsFromSharedLib_arm64 unusedInstance) + { + this.grpcsharp_init = DllImportsFromSharedLib_arm64.grpcsharp_init; + this.grpcsharp_shutdown = DllImportsFromSharedLib_arm64.grpcsharp_shutdown; + this.grpcsharp_version_string = DllImportsFromSharedLib_arm64.grpcsharp_version_string; + this.grpcsharp_batch_context_create = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_create; + this.grpcsharp_batch_context_recv_initial_metadata = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_initial_metadata; + this.grpcsharp_batch_context_recv_message_length = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_message_length; + this.grpcsharp_batch_context_recv_message_next_slice_peek = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_message_next_slice_peek; + this.grpcsharp_batch_context_recv_status_on_client_status = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_status_on_client_status; + this.grpcsharp_batch_context_recv_status_on_client_details = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_status_on_client_details; + this.grpcsharp_batch_context_recv_status_on_client_error_string = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_status_on_client_error_string; + this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_status_on_client_trailing_metadata; + this.grpcsharp_batch_context_recv_close_on_server_cancelled = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_close_on_server_cancelled; + this.grpcsharp_batch_context_reset = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_reset; + this.grpcsharp_batch_context_destroy = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_destroy; + this.grpcsharp_request_call_context_create = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_create; + this.grpcsharp_request_call_context_call = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_call; + this.grpcsharp_request_call_context_method = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_method; + this.grpcsharp_request_call_context_host = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_host; + this.grpcsharp_request_call_context_deadline = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_deadline; + this.grpcsharp_request_call_context_request_metadata = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_request_metadata; + this.grpcsharp_request_call_context_reset = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_reset; + this.grpcsharp_request_call_context_destroy = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_destroy; + this.grpcsharp_composite_call_credentials_create = DllImportsFromSharedLib_arm64.grpcsharp_composite_call_credentials_create; + this.grpcsharp_call_credentials_release = DllImportsFromSharedLib_arm64.grpcsharp_call_credentials_release; + this.grpcsharp_call_cancel = DllImportsFromSharedLib_arm64.grpcsharp_call_cancel; + this.grpcsharp_call_cancel_with_status = DllImportsFromSharedLib_arm64.grpcsharp_call_cancel_with_status; + this.grpcsharp_call_start_unary = DllImportsFromSharedLib_arm64.grpcsharp_call_start_unary; + this.grpcsharp_call_start_client_streaming = DllImportsFromSharedLib_arm64.grpcsharp_call_start_client_streaming; + this.grpcsharp_call_start_server_streaming = DllImportsFromSharedLib_arm64.grpcsharp_call_start_server_streaming; + this.grpcsharp_call_start_duplex_streaming = DllImportsFromSharedLib_arm64.grpcsharp_call_start_duplex_streaming; + this.grpcsharp_call_send_message = DllImportsFromSharedLib_arm64.grpcsharp_call_send_message; + this.grpcsharp_call_send_close_from_client = DllImportsFromSharedLib_arm64.grpcsharp_call_send_close_from_client; + this.grpcsharp_call_send_status_from_server = DllImportsFromSharedLib_arm64.grpcsharp_call_send_status_from_server; + this.grpcsharp_call_recv_message = DllImportsFromSharedLib_arm64.grpcsharp_call_recv_message; + this.grpcsharp_call_recv_initial_metadata = DllImportsFromSharedLib_arm64.grpcsharp_call_recv_initial_metadata; + this.grpcsharp_call_start_serverside = DllImportsFromSharedLib_arm64.grpcsharp_call_start_serverside; + this.grpcsharp_call_send_initial_metadata = DllImportsFromSharedLib_arm64.grpcsharp_call_send_initial_metadata; + this.grpcsharp_call_set_credentials = DllImportsFromSharedLib_arm64.grpcsharp_call_set_credentials; + this.grpcsharp_call_get_peer = DllImportsFromSharedLib_arm64.grpcsharp_call_get_peer; + this.grpcsharp_call_destroy = DllImportsFromSharedLib_arm64.grpcsharp_call_destroy; + this.grpcsharp_channel_args_create = DllImportsFromSharedLib_arm64.grpcsharp_channel_args_create; + this.grpcsharp_channel_args_set_string = DllImportsFromSharedLib_arm64.grpcsharp_channel_args_set_string; + this.grpcsharp_channel_args_set_integer = DllImportsFromSharedLib_arm64.grpcsharp_channel_args_set_integer; + this.grpcsharp_channel_args_destroy = DllImportsFromSharedLib_arm64.grpcsharp_channel_args_destroy; + this.grpcsharp_override_default_ssl_roots = DllImportsFromSharedLib_arm64.grpcsharp_override_default_ssl_roots; + this.grpcsharp_ssl_credentials_create = DllImportsFromSharedLib_arm64.grpcsharp_ssl_credentials_create; + this.grpcsharp_composite_channel_credentials_create = DllImportsFromSharedLib_arm64.grpcsharp_composite_channel_credentials_create; + this.grpcsharp_channel_credentials_release = DllImportsFromSharedLib_arm64.grpcsharp_channel_credentials_release; + this.grpcsharp_insecure_channel_create = DllImportsFromSharedLib_arm64.grpcsharp_insecure_channel_create; + this.grpcsharp_secure_channel_create = DllImportsFromSharedLib_arm64.grpcsharp_secure_channel_create; + this.grpcsharp_channel_create_call = DllImportsFromSharedLib_arm64.grpcsharp_channel_create_call; + this.grpcsharp_channel_check_connectivity_state = DllImportsFromSharedLib_arm64.grpcsharp_channel_check_connectivity_state; + this.grpcsharp_channel_watch_connectivity_state = DllImportsFromSharedLib_arm64.grpcsharp_channel_watch_connectivity_state; + this.grpcsharp_channel_get_target = DllImportsFromSharedLib_arm64.grpcsharp_channel_get_target; + this.grpcsharp_channel_destroy = DllImportsFromSharedLib_arm64.grpcsharp_channel_destroy; + this.grpcsharp_sizeof_grpc_event = DllImportsFromSharedLib_arm64.grpcsharp_sizeof_grpc_event; + this.grpcsharp_completion_queue_create_async = DllImportsFromSharedLib_arm64.grpcsharp_completion_queue_create_async; + this.grpcsharp_completion_queue_create_sync = DllImportsFromSharedLib_arm64.grpcsharp_completion_queue_create_sync; + this.grpcsharp_completion_queue_shutdown = DllImportsFromSharedLib_arm64.grpcsharp_completion_queue_shutdown; + this.grpcsharp_completion_queue_next = DllImportsFromSharedLib_arm64.grpcsharp_completion_queue_next; + this.grpcsharp_completion_queue_pluck = DllImportsFromSharedLib_arm64.grpcsharp_completion_queue_pluck; + this.grpcsharp_completion_queue_destroy = DllImportsFromSharedLib_arm64.grpcsharp_completion_queue_destroy; + this.gprsharp_free = DllImportsFromSharedLib_arm64.gprsharp_free; + this.grpcsharp_metadata_array_create = DllImportsFromSharedLib_arm64.grpcsharp_metadata_array_create; + this.grpcsharp_metadata_array_add = DllImportsFromSharedLib_arm64.grpcsharp_metadata_array_add; + this.grpcsharp_metadata_array_count = DllImportsFromSharedLib_arm64.grpcsharp_metadata_array_count; + this.grpcsharp_metadata_array_get_key = DllImportsFromSharedLib_arm64.grpcsharp_metadata_array_get_key; + this.grpcsharp_metadata_array_get_value = DllImportsFromSharedLib_arm64.grpcsharp_metadata_array_get_value; + this.grpcsharp_metadata_array_destroy_full = DllImportsFromSharedLib_arm64.grpcsharp_metadata_array_destroy_full; + this.grpcsharp_redirect_log = DllImportsFromSharedLib_arm64.grpcsharp_redirect_log; + this.grpcsharp_native_callback_dispatcher_init = DllImportsFromSharedLib_arm64.grpcsharp_native_callback_dispatcher_init; + this.grpcsharp_metadata_credentials_create_from_plugin = DllImportsFromSharedLib_arm64.grpcsharp_metadata_credentials_create_from_plugin; + this.grpcsharp_metadata_credentials_notify_from_plugin = DllImportsFromSharedLib_arm64.grpcsharp_metadata_credentials_notify_from_plugin; + this.grpcsharp_ssl_server_credentials_create = DllImportsFromSharedLib_arm64.grpcsharp_ssl_server_credentials_create; + this.grpcsharp_server_credentials_release = DllImportsFromSharedLib_arm64.grpcsharp_server_credentials_release; + this.grpcsharp_server_create = DllImportsFromSharedLib_arm64.grpcsharp_server_create; + this.grpcsharp_server_register_completion_queue = DllImportsFromSharedLib_arm64.grpcsharp_server_register_completion_queue; + this.grpcsharp_server_add_insecure_http2_port = DllImportsFromSharedLib_arm64.grpcsharp_server_add_insecure_http2_port; + this.grpcsharp_server_add_secure_http2_port = DllImportsFromSharedLib_arm64.grpcsharp_server_add_secure_http2_port; + this.grpcsharp_server_start = DllImportsFromSharedLib_arm64.grpcsharp_server_start; + this.grpcsharp_server_request_call = DllImportsFromSharedLib_arm64.grpcsharp_server_request_call; + this.grpcsharp_server_cancel_all_calls = DllImportsFromSharedLib_arm64.grpcsharp_server_cancel_all_calls; + this.grpcsharp_server_shutdown_and_notify_callback = DllImportsFromSharedLib_arm64.grpcsharp_server_shutdown_and_notify_callback; + this.grpcsharp_server_destroy = DllImportsFromSharedLib_arm64.grpcsharp_server_destroy; + this.grpcsharp_call_auth_context = DllImportsFromSharedLib_arm64.grpcsharp_call_auth_context; + this.grpcsharp_auth_context_peer_identity_property_name = DllImportsFromSharedLib_arm64.grpcsharp_auth_context_peer_identity_property_name; + this.grpcsharp_auth_context_property_iterator = DllImportsFromSharedLib_arm64.grpcsharp_auth_context_property_iterator; + this.grpcsharp_auth_property_iterator_next = DllImportsFromSharedLib_arm64.grpcsharp_auth_property_iterator_next; + this.grpcsharp_auth_context_release = DllImportsFromSharedLib_arm64.grpcsharp_auth_context_release; + this.grpcsharp_slice_buffer_create = DllImportsFromSharedLib_arm64.grpcsharp_slice_buffer_create; + this.grpcsharp_slice_buffer_adjust_tail_space = DllImportsFromSharedLib_arm64.grpcsharp_slice_buffer_adjust_tail_space; + this.grpcsharp_slice_buffer_slice_count = DllImportsFromSharedLib_arm64.grpcsharp_slice_buffer_slice_count; + this.grpcsharp_slice_buffer_slice_peek = DllImportsFromSharedLib_arm64.grpcsharp_slice_buffer_slice_peek; + this.grpcsharp_slice_buffer_reset_and_unref = DllImportsFromSharedLib_arm64.grpcsharp_slice_buffer_reset_and_unref; + this.grpcsharp_slice_buffer_destroy = DllImportsFromSharedLib_arm64.grpcsharp_slice_buffer_destroy; + this.gprsharp_now = DllImportsFromSharedLib_arm64.gprsharp_now; + this.gprsharp_inf_future = DllImportsFromSharedLib_arm64.gprsharp_inf_future; + this.gprsharp_inf_past = DllImportsFromSharedLib_arm64.gprsharp_inf_past; + this.gprsharp_convert_clock_type = DllImportsFromSharedLib_arm64.gprsharp_convert_clock_type; + this.gprsharp_sizeof_timespec = DllImportsFromSharedLib_arm64.gprsharp_sizeof_timespec; + this.grpcsharp_test_callback = DllImportsFromSharedLib_arm64.grpcsharp_test_callback; + this.grpcsharp_test_nop = DllImportsFromSharedLib_arm64.grpcsharp_test_nop; + this.grpcsharp_test_override_method = DllImportsFromSharedLib_arm64.grpcsharp_test_override_method; + this.grpcsharp_test_call_start_unary_echo = DllImportsFromSharedLib_arm64.grpcsharp_test_call_start_unary_echo; + } + + public NativeMethods(DllImportsFromSharedLib_x86_dll unusedInstance) + { + this.grpcsharp_init = DllImportsFromSharedLib_x86_dll.grpcsharp_init; + this.grpcsharp_shutdown = DllImportsFromSharedLib_x86_dll.grpcsharp_shutdown; + this.grpcsharp_version_string = DllImportsFromSharedLib_x86_dll.grpcsharp_version_string; + this.grpcsharp_batch_context_create = DllImportsFromSharedLib_x86_dll.grpcsharp_batch_context_create; + this.grpcsharp_batch_context_recv_initial_metadata = DllImportsFromSharedLib_x86_dll.grpcsharp_batch_context_recv_initial_metadata; + this.grpcsharp_batch_context_recv_message_length = DllImportsFromSharedLib_x86_dll.grpcsharp_batch_context_recv_message_length; + this.grpcsharp_batch_context_recv_message_next_slice_peek = DllImportsFromSharedLib_x86_dll.grpcsharp_batch_context_recv_message_next_slice_peek; + this.grpcsharp_batch_context_recv_status_on_client_status = DllImportsFromSharedLib_x86_dll.grpcsharp_batch_context_recv_status_on_client_status; + this.grpcsharp_batch_context_recv_status_on_client_details = DllImportsFromSharedLib_x86_dll.grpcsharp_batch_context_recv_status_on_client_details; + this.grpcsharp_batch_context_recv_status_on_client_error_string = DllImportsFromSharedLib_x86_dll.grpcsharp_batch_context_recv_status_on_client_error_string; + this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = DllImportsFromSharedLib_x86_dll.grpcsharp_batch_context_recv_status_on_client_trailing_metadata; + this.grpcsharp_batch_context_recv_close_on_server_cancelled = DllImportsFromSharedLib_x86_dll.grpcsharp_batch_context_recv_close_on_server_cancelled; + this.grpcsharp_batch_context_reset = DllImportsFromSharedLib_x86_dll.grpcsharp_batch_context_reset; + this.grpcsharp_batch_context_destroy = DllImportsFromSharedLib_x86_dll.grpcsharp_batch_context_destroy; + this.grpcsharp_request_call_context_create = DllImportsFromSharedLib_x86_dll.grpcsharp_request_call_context_create; + this.grpcsharp_request_call_context_call = DllImportsFromSharedLib_x86_dll.grpcsharp_request_call_context_call; + this.grpcsharp_request_call_context_method = DllImportsFromSharedLib_x86_dll.grpcsharp_request_call_context_method; + this.grpcsharp_request_call_context_host = DllImportsFromSharedLib_x86_dll.grpcsharp_request_call_context_host; + this.grpcsharp_request_call_context_deadline = DllImportsFromSharedLib_x86_dll.grpcsharp_request_call_context_deadline; + this.grpcsharp_request_call_context_request_metadata = DllImportsFromSharedLib_x86_dll.grpcsharp_request_call_context_request_metadata; + this.grpcsharp_request_call_context_reset = DllImportsFromSharedLib_x86_dll.grpcsharp_request_call_context_reset; + this.grpcsharp_request_call_context_destroy = DllImportsFromSharedLib_x86_dll.grpcsharp_request_call_context_destroy; + this.grpcsharp_composite_call_credentials_create = DllImportsFromSharedLib_x86_dll.grpcsharp_composite_call_credentials_create; + this.grpcsharp_call_credentials_release = DllImportsFromSharedLib_x86_dll.grpcsharp_call_credentials_release; + this.grpcsharp_call_cancel = DllImportsFromSharedLib_x86_dll.grpcsharp_call_cancel; + this.grpcsharp_call_cancel_with_status = DllImportsFromSharedLib_x86_dll.grpcsharp_call_cancel_with_status; + this.grpcsharp_call_start_unary = DllImportsFromSharedLib_x86_dll.grpcsharp_call_start_unary; + this.grpcsharp_call_start_client_streaming = DllImportsFromSharedLib_x86_dll.grpcsharp_call_start_client_streaming; + this.grpcsharp_call_start_server_streaming = DllImportsFromSharedLib_x86_dll.grpcsharp_call_start_server_streaming; + this.grpcsharp_call_start_duplex_streaming = DllImportsFromSharedLib_x86_dll.grpcsharp_call_start_duplex_streaming; + this.grpcsharp_call_send_message = DllImportsFromSharedLib_x86_dll.grpcsharp_call_send_message; + this.grpcsharp_call_send_close_from_client = DllImportsFromSharedLib_x86_dll.grpcsharp_call_send_close_from_client; + this.grpcsharp_call_send_status_from_server = DllImportsFromSharedLib_x86_dll.grpcsharp_call_send_status_from_server; + this.grpcsharp_call_recv_message = DllImportsFromSharedLib_x86_dll.grpcsharp_call_recv_message; + this.grpcsharp_call_recv_initial_metadata = DllImportsFromSharedLib_x86_dll.grpcsharp_call_recv_initial_metadata; + this.grpcsharp_call_start_serverside = DllImportsFromSharedLib_x86_dll.grpcsharp_call_start_serverside; + this.grpcsharp_call_send_initial_metadata = DllImportsFromSharedLib_x86_dll.grpcsharp_call_send_initial_metadata; + this.grpcsharp_call_set_credentials = DllImportsFromSharedLib_x86_dll.grpcsharp_call_set_credentials; + this.grpcsharp_call_get_peer = DllImportsFromSharedLib_x86_dll.grpcsharp_call_get_peer; + this.grpcsharp_call_destroy = DllImportsFromSharedLib_x86_dll.grpcsharp_call_destroy; + this.grpcsharp_channel_args_create = DllImportsFromSharedLib_x86_dll.grpcsharp_channel_args_create; + this.grpcsharp_channel_args_set_string = DllImportsFromSharedLib_x86_dll.grpcsharp_channel_args_set_string; + this.grpcsharp_channel_args_set_integer = DllImportsFromSharedLib_x86_dll.grpcsharp_channel_args_set_integer; + this.grpcsharp_channel_args_destroy = DllImportsFromSharedLib_x86_dll.grpcsharp_channel_args_destroy; + this.grpcsharp_override_default_ssl_roots = DllImportsFromSharedLib_x86_dll.grpcsharp_override_default_ssl_roots; + this.grpcsharp_ssl_credentials_create = DllImportsFromSharedLib_x86_dll.grpcsharp_ssl_credentials_create; + this.grpcsharp_composite_channel_credentials_create = DllImportsFromSharedLib_x86_dll.grpcsharp_composite_channel_credentials_create; + this.grpcsharp_channel_credentials_release = DllImportsFromSharedLib_x86_dll.grpcsharp_channel_credentials_release; + this.grpcsharp_insecure_channel_create = DllImportsFromSharedLib_x86_dll.grpcsharp_insecure_channel_create; + this.grpcsharp_secure_channel_create = DllImportsFromSharedLib_x86_dll.grpcsharp_secure_channel_create; + this.grpcsharp_channel_create_call = DllImportsFromSharedLib_x86_dll.grpcsharp_channel_create_call; + this.grpcsharp_channel_check_connectivity_state = DllImportsFromSharedLib_x86_dll.grpcsharp_channel_check_connectivity_state; + this.grpcsharp_channel_watch_connectivity_state = DllImportsFromSharedLib_x86_dll.grpcsharp_channel_watch_connectivity_state; + this.grpcsharp_channel_get_target = DllImportsFromSharedLib_x86_dll.grpcsharp_channel_get_target; + this.grpcsharp_channel_destroy = DllImportsFromSharedLib_x86_dll.grpcsharp_channel_destroy; + this.grpcsharp_sizeof_grpc_event = DllImportsFromSharedLib_x86_dll.grpcsharp_sizeof_grpc_event; + this.grpcsharp_completion_queue_create_async = DllImportsFromSharedLib_x86_dll.grpcsharp_completion_queue_create_async; + this.grpcsharp_completion_queue_create_sync = DllImportsFromSharedLib_x86_dll.grpcsharp_completion_queue_create_sync; + this.grpcsharp_completion_queue_shutdown = DllImportsFromSharedLib_x86_dll.grpcsharp_completion_queue_shutdown; + this.grpcsharp_completion_queue_next = DllImportsFromSharedLib_x86_dll.grpcsharp_completion_queue_next; + this.grpcsharp_completion_queue_pluck = DllImportsFromSharedLib_x86_dll.grpcsharp_completion_queue_pluck; + this.grpcsharp_completion_queue_destroy = DllImportsFromSharedLib_x86_dll.grpcsharp_completion_queue_destroy; + this.gprsharp_free = DllImportsFromSharedLib_x86_dll.gprsharp_free; + this.grpcsharp_metadata_array_create = DllImportsFromSharedLib_x86_dll.grpcsharp_metadata_array_create; + this.grpcsharp_metadata_array_add = DllImportsFromSharedLib_x86_dll.grpcsharp_metadata_array_add; + this.grpcsharp_metadata_array_count = DllImportsFromSharedLib_x86_dll.grpcsharp_metadata_array_count; + this.grpcsharp_metadata_array_get_key = DllImportsFromSharedLib_x86_dll.grpcsharp_metadata_array_get_key; + this.grpcsharp_metadata_array_get_value = DllImportsFromSharedLib_x86_dll.grpcsharp_metadata_array_get_value; + this.grpcsharp_metadata_array_destroy_full = DllImportsFromSharedLib_x86_dll.grpcsharp_metadata_array_destroy_full; + this.grpcsharp_redirect_log = DllImportsFromSharedLib_x86_dll.grpcsharp_redirect_log; + this.grpcsharp_native_callback_dispatcher_init = DllImportsFromSharedLib_x86_dll.grpcsharp_native_callback_dispatcher_init; + this.grpcsharp_metadata_credentials_create_from_plugin = DllImportsFromSharedLib_x86_dll.grpcsharp_metadata_credentials_create_from_plugin; + this.grpcsharp_metadata_credentials_notify_from_plugin = DllImportsFromSharedLib_x86_dll.grpcsharp_metadata_credentials_notify_from_plugin; + this.grpcsharp_ssl_server_credentials_create = DllImportsFromSharedLib_x86_dll.grpcsharp_ssl_server_credentials_create; + this.grpcsharp_server_credentials_release = DllImportsFromSharedLib_x86_dll.grpcsharp_server_credentials_release; + this.grpcsharp_server_create = DllImportsFromSharedLib_x86_dll.grpcsharp_server_create; + this.grpcsharp_server_register_completion_queue = DllImportsFromSharedLib_x86_dll.grpcsharp_server_register_completion_queue; + this.grpcsharp_server_add_insecure_http2_port = DllImportsFromSharedLib_x86_dll.grpcsharp_server_add_insecure_http2_port; + this.grpcsharp_server_add_secure_http2_port = DllImportsFromSharedLib_x86_dll.grpcsharp_server_add_secure_http2_port; + this.grpcsharp_server_start = DllImportsFromSharedLib_x86_dll.grpcsharp_server_start; + this.grpcsharp_server_request_call = DllImportsFromSharedLib_x86_dll.grpcsharp_server_request_call; + this.grpcsharp_server_cancel_all_calls = DllImportsFromSharedLib_x86_dll.grpcsharp_server_cancel_all_calls; + this.grpcsharp_server_shutdown_and_notify_callback = DllImportsFromSharedLib_x86_dll.grpcsharp_server_shutdown_and_notify_callback; + this.grpcsharp_server_destroy = DllImportsFromSharedLib_x86_dll.grpcsharp_server_destroy; + this.grpcsharp_call_auth_context = DllImportsFromSharedLib_x86_dll.grpcsharp_call_auth_context; + this.grpcsharp_auth_context_peer_identity_property_name = DllImportsFromSharedLib_x86_dll.grpcsharp_auth_context_peer_identity_property_name; + this.grpcsharp_auth_context_property_iterator = DllImportsFromSharedLib_x86_dll.grpcsharp_auth_context_property_iterator; + this.grpcsharp_auth_property_iterator_next = DllImportsFromSharedLib_x86_dll.grpcsharp_auth_property_iterator_next; + this.grpcsharp_auth_context_release = DllImportsFromSharedLib_x86_dll.grpcsharp_auth_context_release; + this.grpcsharp_slice_buffer_create = DllImportsFromSharedLib_x86_dll.grpcsharp_slice_buffer_create; + this.grpcsharp_slice_buffer_adjust_tail_space = DllImportsFromSharedLib_x86_dll.grpcsharp_slice_buffer_adjust_tail_space; + this.grpcsharp_slice_buffer_slice_count = DllImportsFromSharedLib_x86_dll.grpcsharp_slice_buffer_slice_count; + this.grpcsharp_slice_buffer_slice_peek = DllImportsFromSharedLib_x86_dll.grpcsharp_slice_buffer_slice_peek; + this.grpcsharp_slice_buffer_reset_and_unref = DllImportsFromSharedLib_x86_dll.grpcsharp_slice_buffer_reset_and_unref; + this.grpcsharp_slice_buffer_destroy = DllImportsFromSharedLib_x86_dll.grpcsharp_slice_buffer_destroy; + this.gprsharp_now = DllImportsFromSharedLib_x86_dll.gprsharp_now; + this.gprsharp_inf_future = DllImportsFromSharedLib_x86_dll.gprsharp_inf_future; + this.gprsharp_inf_past = DllImportsFromSharedLib_x86_dll.gprsharp_inf_past; + this.gprsharp_convert_clock_type = DllImportsFromSharedLib_x86_dll.gprsharp_convert_clock_type; + this.gprsharp_sizeof_timespec = DllImportsFromSharedLib_x86_dll.gprsharp_sizeof_timespec; + this.grpcsharp_test_callback = DllImportsFromSharedLib_x86_dll.grpcsharp_test_callback; + this.grpcsharp_test_nop = DllImportsFromSharedLib_x86_dll.grpcsharp_test_nop; + this.grpcsharp_test_override_method = DllImportsFromSharedLib_x86_dll.grpcsharp_test_override_method; + this.grpcsharp_test_call_start_unary_echo = DllImportsFromSharedLib_x86_dll.grpcsharp_test_call_start_unary_echo; + } + + public NativeMethods(DllImportsFromSharedLib_x64_dll unusedInstance) + { + this.grpcsharp_init = DllImportsFromSharedLib_x64_dll.grpcsharp_init; + this.grpcsharp_shutdown = DllImportsFromSharedLib_x64_dll.grpcsharp_shutdown; + this.grpcsharp_version_string = DllImportsFromSharedLib_x64_dll.grpcsharp_version_string; + this.grpcsharp_batch_context_create = DllImportsFromSharedLib_x64_dll.grpcsharp_batch_context_create; + this.grpcsharp_batch_context_recv_initial_metadata = DllImportsFromSharedLib_x64_dll.grpcsharp_batch_context_recv_initial_metadata; + this.grpcsharp_batch_context_recv_message_length = DllImportsFromSharedLib_x64_dll.grpcsharp_batch_context_recv_message_length; + this.grpcsharp_batch_context_recv_message_next_slice_peek = DllImportsFromSharedLib_x64_dll.grpcsharp_batch_context_recv_message_next_slice_peek; + this.grpcsharp_batch_context_recv_status_on_client_status = DllImportsFromSharedLib_x64_dll.grpcsharp_batch_context_recv_status_on_client_status; + this.grpcsharp_batch_context_recv_status_on_client_details = DllImportsFromSharedLib_x64_dll.grpcsharp_batch_context_recv_status_on_client_details; + this.grpcsharp_batch_context_recv_status_on_client_error_string = DllImportsFromSharedLib_x64_dll.grpcsharp_batch_context_recv_status_on_client_error_string; + this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = DllImportsFromSharedLib_x64_dll.grpcsharp_batch_context_recv_status_on_client_trailing_metadata; + this.grpcsharp_batch_context_recv_close_on_server_cancelled = DllImportsFromSharedLib_x64_dll.grpcsharp_batch_context_recv_close_on_server_cancelled; + this.grpcsharp_batch_context_reset = DllImportsFromSharedLib_x64_dll.grpcsharp_batch_context_reset; + this.grpcsharp_batch_context_destroy = DllImportsFromSharedLib_x64_dll.grpcsharp_batch_context_destroy; + this.grpcsharp_request_call_context_create = DllImportsFromSharedLib_x64_dll.grpcsharp_request_call_context_create; + this.grpcsharp_request_call_context_call = DllImportsFromSharedLib_x64_dll.grpcsharp_request_call_context_call; + this.grpcsharp_request_call_context_method = DllImportsFromSharedLib_x64_dll.grpcsharp_request_call_context_method; + this.grpcsharp_request_call_context_host = DllImportsFromSharedLib_x64_dll.grpcsharp_request_call_context_host; + this.grpcsharp_request_call_context_deadline = DllImportsFromSharedLib_x64_dll.grpcsharp_request_call_context_deadline; + this.grpcsharp_request_call_context_request_metadata = DllImportsFromSharedLib_x64_dll.grpcsharp_request_call_context_request_metadata; + this.grpcsharp_request_call_context_reset = DllImportsFromSharedLib_x64_dll.grpcsharp_request_call_context_reset; + this.grpcsharp_request_call_context_destroy = DllImportsFromSharedLib_x64_dll.grpcsharp_request_call_context_destroy; + this.grpcsharp_composite_call_credentials_create = DllImportsFromSharedLib_x64_dll.grpcsharp_composite_call_credentials_create; + this.grpcsharp_call_credentials_release = DllImportsFromSharedLib_x64_dll.grpcsharp_call_credentials_release; + this.grpcsharp_call_cancel = DllImportsFromSharedLib_x64_dll.grpcsharp_call_cancel; + this.grpcsharp_call_cancel_with_status = DllImportsFromSharedLib_x64_dll.grpcsharp_call_cancel_with_status; + this.grpcsharp_call_start_unary = DllImportsFromSharedLib_x64_dll.grpcsharp_call_start_unary; + this.grpcsharp_call_start_client_streaming = DllImportsFromSharedLib_x64_dll.grpcsharp_call_start_client_streaming; + this.grpcsharp_call_start_server_streaming = DllImportsFromSharedLib_x64_dll.grpcsharp_call_start_server_streaming; + this.grpcsharp_call_start_duplex_streaming = DllImportsFromSharedLib_x64_dll.grpcsharp_call_start_duplex_streaming; + this.grpcsharp_call_send_message = DllImportsFromSharedLib_x64_dll.grpcsharp_call_send_message; + this.grpcsharp_call_send_close_from_client = DllImportsFromSharedLib_x64_dll.grpcsharp_call_send_close_from_client; + this.grpcsharp_call_send_status_from_server = DllImportsFromSharedLib_x64_dll.grpcsharp_call_send_status_from_server; + this.grpcsharp_call_recv_message = DllImportsFromSharedLib_x64_dll.grpcsharp_call_recv_message; + this.grpcsharp_call_recv_initial_metadata = DllImportsFromSharedLib_x64_dll.grpcsharp_call_recv_initial_metadata; + this.grpcsharp_call_start_serverside = DllImportsFromSharedLib_x64_dll.grpcsharp_call_start_serverside; + this.grpcsharp_call_send_initial_metadata = DllImportsFromSharedLib_x64_dll.grpcsharp_call_send_initial_metadata; + this.grpcsharp_call_set_credentials = DllImportsFromSharedLib_x64_dll.grpcsharp_call_set_credentials; + this.grpcsharp_call_get_peer = DllImportsFromSharedLib_x64_dll.grpcsharp_call_get_peer; + this.grpcsharp_call_destroy = DllImportsFromSharedLib_x64_dll.grpcsharp_call_destroy; + this.grpcsharp_channel_args_create = DllImportsFromSharedLib_x64_dll.grpcsharp_channel_args_create; + this.grpcsharp_channel_args_set_string = DllImportsFromSharedLib_x64_dll.grpcsharp_channel_args_set_string; + this.grpcsharp_channel_args_set_integer = DllImportsFromSharedLib_x64_dll.grpcsharp_channel_args_set_integer; + this.grpcsharp_channel_args_destroy = DllImportsFromSharedLib_x64_dll.grpcsharp_channel_args_destroy; + this.grpcsharp_override_default_ssl_roots = DllImportsFromSharedLib_x64_dll.grpcsharp_override_default_ssl_roots; + this.grpcsharp_ssl_credentials_create = DllImportsFromSharedLib_x64_dll.grpcsharp_ssl_credentials_create; + this.grpcsharp_composite_channel_credentials_create = DllImportsFromSharedLib_x64_dll.grpcsharp_composite_channel_credentials_create; + this.grpcsharp_channel_credentials_release = DllImportsFromSharedLib_x64_dll.grpcsharp_channel_credentials_release; + this.grpcsharp_insecure_channel_create = DllImportsFromSharedLib_x64_dll.grpcsharp_insecure_channel_create; + this.grpcsharp_secure_channel_create = DllImportsFromSharedLib_x64_dll.grpcsharp_secure_channel_create; + this.grpcsharp_channel_create_call = DllImportsFromSharedLib_x64_dll.grpcsharp_channel_create_call; + this.grpcsharp_channel_check_connectivity_state = DllImportsFromSharedLib_x64_dll.grpcsharp_channel_check_connectivity_state; + this.grpcsharp_channel_watch_connectivity_state = DllImportsFromSharedLib_x64_dll.grpcsharp_channel_watch_connectivity_state; + this.grpcsharp_channel_get_target = DllImportsFromSharedLib_x64_dll.grpcsharp_channel_get_target; + this.grpcsharp_channel_destroy = DllImportsFromSharedLib_x64_dll.grpcsharp_channel_destroy; + this.grpcsharp_sizeof_grpc_event = DllImportsFromSharedLib_x64_dll.grpcsharp_sizeof_grpc_event; + this.grpcsharp_completion_queue_create_async = DllImportsFromSharedLib_x64_dll.grpcsharp_completion_queue_create_async; + this.grpcsharp_completion_queue_create_sync = DllImportsFromSharedLib_x64_dll.grpcsharp_completion_queue_create_sync; + this.grpcsharp_completion_queue_shutdown = DllImportsFromSharedLib_x64_dll.grpcsharp_completion_queue_shutdown; + this.grpcsharp_completion_queue_next = DllImportsFromSharedLib_x64_dll.grpcsharp_completion_queue_next; + this.grpcsharp_completion_queue_pluck = DllImportsFromSharedLib_x64_dll.grpcsharp_completion_queue_pluck; + this.grpcsharp_completion_queue_destroy = DllImportsFromSharedLib_x64_dll.grpcsharp_completion_queue_destroy; + this.gprsharp_free = DllImportsFromSharedLib_x64_dll.gprsharp_free; + this.grpcsharp_metadata_array_create = DllImportsFromSharedLib_x64_dll.grpcsharp_metadata_array_create; + this.grpcsharp_metadata_array_add = DllImportsFromSharedLib_x64_dll.grpcsharp_metadata_array_add; + this.grpcsharp_metadata_array_count = DllImportsFromSharedLib_x64_dll.grpcsharp_metadata_array_count; + this.grpcsharp_metadata_array_get_key = DllImportsFromSharedLib_x64_dll.grpcsharp_metadata_array_get_key; + this.grpcsharp_metadata_array_get_value = DllImportsFromSharedLib_x64_dll.grpcsharp_metadata_array_get_value; + this.grpcsharp_metadata_array_destroy_full = DllImportsFromSharedLib_x64_dll.grpcsharp_metadata_array_destroy_full; + this.grpcsharp_redirect_log = DllImportsFromSharedLib_x64_dll.grpcsharp_redirect_log; + this.grpcsharp_native_callback_dispatcher_init = DllImportsFromSharedLib_x64_dll.grpcsharp_native_callback_dispatcher_init; + this.grpcsharp_metadata_credentials_create_from_plugin = DllImportsFromSharedLib_x64_dll.grpcsharp_metadata_credentials_create_from_plugin; + this.grpcsharp_metadata_credentials_notify_from_plugin = DllImportsFromSharedLib_x64_dll.grpcsharp_metadata_credentials_notify_from_plugin; + this.grpcsharp_ssl_server_credentials_create = DllImportsFromSharedLib_x64_dll.grpcsharp_ssl_server_credentials_create; + this.grpcsharp_server_credentials_release = DllImportsFromSharedLib_x64_dll.grpcsharp_server_credentials_release; + this.grpcsharp_server_create = DllImportsFromSharedLib_x64_dll.grpcsharp_server_create; + this.grpcsharp_server_register_completion_queue = DllImportsFromSharedLib_x64_dll.grpcsharp_server_register_completion_queue; + this.grpcsharp_server_add_insecure_http2_port = DllImportsFromSharedLib_x64_dll.grpcsharp_server_add_insecure_http2_port; + this.grpcsharp_server_add_secure_http2_port = DllImportsFromSharedLib_x64_dll.grpcsharp_server_add_secure_http2_port; + this.grpcsharp_server_start = DllImportsFromSharedLib_x64_dll.grpcsharp_server_start; + this.grpcsharp_server_request_call = DllImportsFromSharedLib_x64_dll.grpcsharp_server_request_call; + this.grpcsharp_server_cancel_all_calls = DllImportsFromSharedLib_x64_dll.grpcsharp_server_cancel_all_calls; + this.grpcsharp_server_shutdown_and_notify_callback = DllImportsFromSharedLib_x64_dll.grpcsharp_server_shutdown_and_notify_callback; + this.grpcsharp_server_destroy = DllImportsFromSharedLib_x64_dll.grpcsharp_server_destroy; + this.grpcsharp_call_auth_context = DllImportsFromSharedLib_x64_dll.grpcsharp_call_auth_context; + this.grpcsharp_auth_context_peer_identity_property_name = DllImportsFromSharedLib_x64_dll.grpcsharp_auth_context_peer_identity_property_name; + this.grpcsharp_auth_context_property_iterator = DllImportsFromSharedLib_x64_dll.grpcsharp_auth_context_property_iterator; + this.grpcsharp_auth_property_iterator_next = DllImportsFromSharedLib_x64_dll.grpcsharp_auth_property_iterator_next; + this.grpcsharp_auth_context_release = DllImportsFromSharedLib_x64_dll.grpcsharp_auth_context_release; + this.grpcsharp_slice_buffer_create = DllImportsFromSharedLib_x64_dll.grpcsharp_slice_buffer_create; + this.grpcsharp_slice_buffer_adjust_tail_space = DllImportsFromSharedLib_x64_dll.grpcsharp_slice_buffer_adjust_tail_space; + this.grpcsharp_slice_buffer_slice_count = DllImportsFromSharedLib_x64_dll.grpcsharp_slice_buffer_slice_count; + this.grpcsharp_slice_buffer_slice_peek = DllImportsFromSharedLib_x64_dll.grpcsharp_slice_buffer_slice_peek; + this.grpcsharp_slice_buffer_reset_and_unref = DllImportsFromSharedLib_x64_dll.grpcsharp_slice_buffer_reset_and_unref; + this.grpcsharp_slice_buffer_destroy = DllImportsFromSharedLib_x64_dll.grpcsharp_slice_buffer_destroy; + this.gprsharp_now = DllImportsFromSharedLib_x64_dll.gprsharp_now; + this.gprsharp_inf_future = DllImportsFromSharedLib_x64_dll.gprsharp_inf_future; + this.gprsharp_inf_past = DllImportsFromSharedLib_x64_dll.gprsharp_inf_past; + this.gprsharp_convert_clock_type = DllImportsFromSharedLib_x64_dll.gprsharp_convert_clock_type; + this.gprsharp_sizeof_timespec = DllImportsFromSharedLib_x64_dll.gprsharp_sizeof_timespec; + this.grpcsharp_test_callback = DllImportsFromSharedLib_x64_dll.grpcsharp_test_callback; + this.grpcsharp_test_nop = DllImportsFromSharedLib_x64_dll.grpcsharp_test_nop; + this.grpcsharp_test_override_method = DllImportsFromSharedLib_x64_dll.grpcsharp_test_override_method; + this.grpcsharp_test_call_start_unary_echo = DllImportsFromSharedLib_x64_dll.grpcsharp_test_call_start_unary_echo; + } + + /// + /// Delegate types for all published native methods. Declared under inner class to prevent scope pollution. + /// + public class Delegates + { + public delegate void grpcsharp_init_delegate(); + public delegate void grpcsharp_shutdown_delegate(); + public delegate IntPtr grpcsharp_version_string_delegate(); // returns not-owned const char* + public delegate BatchContextSafeHandle grpcsharp_batch_context_create_delegate(); + public delegate IntPtr grpcsharp_batch_context_recv_initial_metadata_delegate(BatchContextSafeHandle ctx); + public delegate IntPtr grpcsharp_batch_context_recv_message_length_delegate(BatchContextSafeHandle ctx); + public delegate int grpcsharp_batch_context_recv_message_next_slice_peek_delegate(BatchContextSafeHandle ctx, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + public delegate StatusCode grpcsharp_batch_context_recv_status_on_client_status_delegate(BatchContextSafeHandle ctx); + public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_details_delegate(BatchContextSafeHandle ctx, out UIntPtr detailsLength); + public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_error_string_delegate(BatchContextSafeHandle ctx); + public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate(BatchContextSafeHandle ctx); + public delegate int grpcsharp_batch_context_recv_close_on_server_cancelled_delegate(BatchContextSafeHandle ctx); + public delegate void grpcsharp_batch_context_reset_delegate(BatchContextSafeHandle ctx); + public delegate void grpcsharp_batch_context_destroy_delegate(IntPtr ctx); + public delegate RequestCallContextSafeHandle grpcsharp_request_call_context_create_delegate(); + public delegate CallSafeHandle grpcsharp_request_call_context_call_delegate(RequestCallContextSafeHandle ctx); + public delegate IntPtr grpcsharp_request_call_context_method_delegate(RequestCallContextSafeHandle ctx, out UIntPtr methodLength); + public delegate IntPtr grpcsharp_request_call_context_host_delegate(RequestCallContextSafeHandle ctx, out UIntPtr hostLength); + public delegate Timespec grpcsharp_request_call_context_deadline_delegate(RequestCallContextSafeHandle ctx); + public delegate IntPtr grpcsharp_request_call_context_request_metadata_delegate(RequestCallContextSafeHandle ctx); + public delegate void grpcsharp_request_call_context_reset_delegate(RequestCallContextSafeHandle ctx); + public delegate void grpcsharp_request_call_context_destroy_delegate(IntPtr ctx); + public delegate CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create_delegate(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); + public delegate void grpcsharp_call_credentials_release_delegate(IntPtr credentials); + public delegate CallError grpcsharp_call_cancel_delegate(CallSafeHandle call); + public delegate CallError grpcsharp_call_cancel_with_status_delegate(CallSafeHandle call, StatusCode status, string description); + public delegate CallError grpcsharp_call_start_unary_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + public delegate CallError grpcsharp_call_start_client_streaming_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + public delegate CallError grpcsharp_call_start_server_streaming_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + public delegate CallError grpcsharp_call_start_duplex_streaming_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + public delegate CallError grpcsharp_call_send_message_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, int sendEmptyInitialMetadata); + public delegate CallError grpcsharp_call_send_close_from_client_delegate(CallSafeHandle call, BatchContextSafeHandle ctx); + public delegate CallError grpcsharp_call_send_status_from_server_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, SliceBufferSafeHandle optionalSendBuffer, WriteFlags writeFlags); + public delegate CallError grpcsharp_call_recv_message_delegate(CallSafeHandle call, BatchContextSafeHandle ctx); + public delegate CallError grpcsharp_call_recv_initial_metadata_delegate(CallSafeHandle call, BatchContextSafeHandle ctx); + public delegate CallError grpcsharp_call_start_serverside_delegate(CallSafeHandle call, BatchContextSafeHandle ctx); + public delegate CallError grpcsharp_call_send_initial_metadata_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + public delegate CallError grpcsharp_call_set_credentials_delegate(CallSafeHandle call, CallCredentialsSafeHandle credentials); + public delegate CStringSafeHandle grpcsharp_call_get_peer_delegate(CallSafeHandle call); + public delegate void grpcsharp_call_destroy_delegate(IntPtr call); + public delegate ChannelArgsSafeHandle grpcsharp_channel_args_create_delegate(UIntPtr numArgs); + public delegate void grpcsharp_channel_args_set_string_delegate(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); + public delegate void grpcsharp_channel_args_set_integer_delegate(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); + public delegate void grpcsharp_channel_args_destroy_delegate(IntPtr args); + public delegate void grpcsharp_override_default_ssl_roots_delegate(string pemRootCerts); + public delegate ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create_delegate(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); + public delegate ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create_delegate(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); + public delegate void grpcsharp_channel_credentials_release_delegate(IntPtr credentials); + public delegate ChannelSafeHandle grpcsharp_insecure_channel_create_delegate(string target, ChannelArgsSafeHandle channelArgs); + public delegate ChannelSafeHandle grpcsharp_secure_channel_create_delegate(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); + public delegate CallSafeHandle grpcsharp_channel_create_call_delegate(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); + public delegate ChannelState grpcsharp_channel_check_connectivity_state_delegate(ChannelSafeHandle channel, int tryToConnect); + public delegate void grpcsharp_channel_watch_connectivity_state_delegate(ChannelSafeHandle channel, ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + public delegate CStringSafeHandle grpcsharp_channel_get_target_delegate(ChannelSafeHandle call); + public delegate void grpcsharp_channel_destroy_delegate(IntPtr channel); + public delegate int grpcsharp_sizeof_grpc_event_delegate(); + public delegate CompletionQueueSafeHandle grpcsharp_completion_queue_create_async_delegate(); + public delegate CompletionQueueSafeHandle grpcsharp_completion_queue_create_sync_delegate(); + public delegate void grpcsharp_completion_queue_shutdown_delegate(CompletionQueueSafeHandle cq); + public delegate CompletionQueueEvent grpcsharp_completion_queue_next_delegate(CompletionQueueSafeHandle cq); + public delegate CompletionQueueEvent grpcsharp_completion_queue_pluck_delegate(CompletionQueueSafeHandle cq, IntPtr tag); + public delegate void grpcsharp_completion_queue_destroy_delegate(IntPtr cq); + public delegate void gprsharp_free_delegate(IntPtr ptr); + public delegate MetadataArraySafeHandle grpcsharp_metadata_array_create_delegate(UIntPtr capacity); + public delegate void grpcsharp_metadata_array_add_delegate(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); + public delegate UIntPtr grpcsharp_metadata_array_count_delegate(IntPtr metadataArray); + public delegate IntPtr grpcsharp_metadata_array_get_key_delegate(IntPtr metadataArray, UIntPtr index, out UIntPtr keyLength); + public delegate IntPtr grpcsharp_metadata_array_get_value_delegate(IntPtr metadataArray, UIntPtr index, out UIntPtr valueLength); + public delegate void grpcsharp_metadata_array_destroy_full_delegate(IntPtr array); + public delegate void grpcsharp_redirect_log_delegate(GprLogDelegate callback); + public delegate void grpcsharp_native_callback_dispatcher_init_delegate(NativeCallbackDispatcherCallback dispatcher); + public delegate CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin_delegate(IntPtr nativeCallbackTag); + public delegate void grpcsharp_metadata_credentials_notify_from_plugin_delegate(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); + public delegate ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create_delegate(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, SslClientCertificateRequestType clientCertificateRequest); + public delegate void grpcsharp_server_credentials_release_delegate(IntPtr credentials); + public delegate ServerSafeHandle grpcsharp_server_create_delegate(ChannelArgsSafeHandle args); + public delegate void grpcsharp_server_register_completion_queue_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq); + public delegate int grpcsharp_server_add_insecure_http2_port_delegate(ServerSafeHandle server, string addr); + public delegate int grpcsharp_server_add_secure_http2_port_delegate(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); + public delegate void grpcsharp_server_start_delegate(ServerSafeHandle server); + public delegate CallError grpcsharp_server_request_call_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq, RequestCallContextSafeHandle ctx); + public delegate void grpcsharp_server_cancel_all_calls_delegate(ServerSafeHandle server); + public delegate void grpcsharp_server_shutdown_and_notify_callback_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + public delegate void grpcsharp_server_destroy_delegate(IntPtr server); + public delegate AuthContextSafeHandle grpcsharp_call_auth_context_delegate(CallSafeHandle call); + public delegate IntPtr grpcsharp_auth_context_peer_identity_property_name_delegate(AuthContextSafeHandle authContext); // returns const char* + public delegate AuthContextSafeHandle.NativeAuthPropertyIterator grpcsharp_auth_context_property_iterator_delegate(AuthContextSafeHandle authContext); + public delegate IntPtr grpcsharp_auth_property_iterator_next_delegate(ref AuthContextSafeHandle.NativeAuthPropertyIterator iterator); // returns const auth_property* + public delegate void grpcsharp_auth_context_release_delegate(IntPtr authContext); + public delegate SliceBufferSafeHandle grpcsharp_slice_buffer_create_delegate(); + public delegate IntPtr grpcsharp_slice_buffer_adjust_tail_space_delegate(SliceBufferSafeHandle sliceBuffer, UIntPtr availableTailSpace, UIntPtr requestedTailSpace); + public delegate UIntPtr grpcsharp_slice_buffer_slice_count_delegate(SliceBufferSafeHandle sliceBuffer); + public delegate void grpcsharp_slice_buffer_slice_peek_delegate(SliceBufferSafeHandle sliceBuffer, UIntPtr index, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + public delegate void grpcsharp_slice_buffer_reset_and_unref_delegate(SliceBufferSafeHandle sliceBuffer); + public delegate void grpcsharp_slice_buffer_destroy_delegate(IntPtr sliceBuffer); + public delegate Timespec gprsharp_now_delegate(ClockType clockType); + public delegate Timespec gprsharp_inf_future_delegate(ClockType clockType); + public delegate Timespec gprsharp_inf_past_delegate(ClockType clockType); + public delegate Timespec gprsharp_convert_clock_type_delegate(Timespec t, ClockType targetClock); + public delegate int gprsharp_sizeof_timespec_delegate(); + public delegate CallError grpcsharp_test_callback_delegate([MarshalAs(UnmanagedType.FunctionPtr)] NativeCallbackTestDelegate callback); + public delegate IntPtr grpcsharp_test_nop_delegate(IntPtr ptr); + public delegate void grpcsharp_test_override_method_delegate(string methodName, string variant); + public delegate CallError grpcsharp_test_call_start_unary_echo_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + } + + /// + /// grpc_csharp_ext used as a static library (e.g Unity iOS). + /// + internal class DllImportsFromStaticLib + { + private const string ImportName = "__Internal"; + + [DllImport(ImportName)] + public static extern void grpcsharp_init(); + + [DllImport(ImportName)] + public static extern void grpcsharp_shutdown(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_version_string(); + + [DllImport(ImportName)] + public static extern BatchContextSafeHandle grpcsharp_batch_context_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_initial_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_message_length(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_message_next_slice_peek(BatchContextSafeHandle ctx, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern StatusCode grpcsharp_batch_context_recv_status_on_client_status(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx, out UIntPtr detailsLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_error_string(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_close_on_server_cancelled(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_reset(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern RequestCallContextSafeHandle grpcsharp_request_call_context_create(); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_request_call_context_call(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_method(RequestCallContextSafeHandle ctx, out UIntPtr methodLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_host(RequestCallContextSafeHandle ctx, out UIntPtr hostLength); + + [DllImport(ImportName)] + public static extern Timespec grpcsharp_request_call_context_deadline(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_request_metadata(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_reset(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_unary(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_client_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_server_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_message(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, int sendEmptyInitialMetadata); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_close_from_client(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, SliceBufferSafeHandle optionalSendBuffer, WriteFlags writeFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_message(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_serverside(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_destroy(IntPtr call); + + [DllImport(ImportName)] + public static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_destroy(IntPtr args); + + [DllImport(ImportName)] + public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); + + [DllImport(ImportName)] + public static extern ChannelState grpcsharp_channel_check_connectivity_state(ChannelSafeHandle channel, int tryToConnect); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_watch_connectivity_state(ChannelSafeHandle channel, ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_channel_get_target(ChannelSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_destroy(IntPtr channel); + + [DllImport(ImportName)] + public static extern int grpcsharp_sizeof_grpc_event(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_async(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_sync(); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_shutdown(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_next(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_pluck(CompletionQueueSafeHandle cq, IntPtr tag); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_destroy(IntPtr cq); + + [DllImport(ImportName)] + public static extern void gprsharp_free(IntPtr ptr); + + [DllImport(ImportName)] + public static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_metadata_array_count(IntPtr metadataArray); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_key(IntPtr metadataArray, UIntPtr index, out UIntPtr keyLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_value(IntPtr metadataArray, UIntPtr index, out UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_destroy_full(IntPtr array); + + [DllImport(ImportName)] + public static extern void grpcsharp_redirect_log(GprLogDelegate callback); + + [DllImport(ImportName)] + public static extern void grpcsharp_native_callback_dispatcher_init(NativeCallbackDispatcherCallback dispatcher); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(IntPtr nativeCallbackTag); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); + + [DllImport(ImportName)] + public static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, SslClientCertificateRequestType clientCertificateRequest); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ServerSafeHandle grpcsharp_server_create(ChannelArgsSafeHandle args); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_register_completion_queue(ServerSafeHandle server, CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_insecure_http2_port(ServerSafeHandle server, string addr); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_start(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_cancel_all_calls(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_shutdown_and_notify_callback(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_destroy(IntPtr server); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle grpcsharp_call_auth_context(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_context_peer_identity_property_name(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle.NativeAuthPropertyIterator grpcsharp_auth_context_property_iterator(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_property_iterator_next(ref AuthContextSafeHandle.NativeAuthPropertyIterator iterator); + + [DllImport(ImportName)] + public static extern void grpcsharp_auth_context_release(IntPtr authContext); + + [DllImport(ImportName)] + public static extern SliceBufferSafeHandle grpcsharp_slice_buffer_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_slice_buffer_adjust_tail_space(SliceBufferSafeHandle sliceBuffer, UIntPtr availableTailSpace, UIntPtr requestedTailSpace); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_slice_buffer_slice_count(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_slice_peek(SliceBufferSafeHandle sliceBuffer, UIntPtr index, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_reset_and_unref(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_destroy(IntPtr sliceBuffer); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_now(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_future(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_past(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_convert_clock_type(Timespec t, ClockType targetClock); + + [DllImport(ImportName)] + public static extern int gprsharp_sizeof_timespec(); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] NativeCallbackTestDelegate callback); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_test_nop(IntPtr ptr); + + [DllImport(ImportName)] + public static extern void grpcsharp_test_override_method(string methodName, string variant); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_call_start_unary_echo(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + } + + /// + /// grpc_csharp_ext used as a shared library (e.g on Unity Standalone and Android). + /// + internal class DllImportsFromSharedLib + { + private const string ImportName = "grpc_csharp_ext"; + + [DllImport(ImportName)] + public static extern void grpcsharp_init(); + + [DllImport(ImportName)] + public static extern void grpcsharp_shutdown(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_version_string(); + + [DllImport(ImportName)] + public static extern BatchContextSafeHandle grpcsharp_batch_context_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_initial_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_message_length(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_message_next_slice_peek(BatchContextSafeHandle ctx, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern StatusCode grpcsharp_batch_context_recv_status_on_client_status(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx, out UIntPtr detailsLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_error_string(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_close_on_server_cancelled(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_reset(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern RequestCallContextSafeHandle grpcsharp_request_call_context_create(); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_request_call_context_call(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_method(RequestCallContextSafeHandle ctx, out UIntPtr methodLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_host(RequestCallContextSafeHandle ctx, out UIntPtr hostLength); + + [DllImport(ImportName)] + public static extern Timespec grpcsharp_request_call_context_deadline(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_request_metadata(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_reset(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_unary(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_client_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_server_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_message(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, int sendEmptyInitialMetadata); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_close_from_client(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, SliceBufferSafeHandle optionalSendBuffer, WriteFlags writeFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_message(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_serverside(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_destroy(IntPtr call); + + [DllImport(ImportName)] + public static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_destroy(IntPtr args); + + [DllImport(ImportName)] + public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); + + [DllImport(ImportName)] + public static extern ChannelState grpcsharp_channel_check_connectivity_state(ChannelSafeHandle channel, int tryToConnect); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_watch_connectivity_state(ChannelSafeHandle channel, ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_channel_get_target(ChannelSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_destroy(IntPtr channel); + + [DllImport(ImportName)] + public static extern int grpcsharp_sizeof_grpc_event(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_async(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_sync(); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_shutdown(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_next(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_pluck(CompletionQueueSafeHandle cq, IntPtr tag); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_destroy(IntPtr cq); + + [DllImport(ImportName)] + public static extern void gprsharp_free(IntPtr ptr); + + [DllImport(ImportName)] + public static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_metadata_array_count(IntPtr metadataArray); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_key(IntPtr metadataArray, UIntPtr index, out UIntPtr keyLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_value(IntPtr metadataArray, UIntPtr index, out UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_destroy_full(IntPtr array); + + [DllImport(ImportName)] + public static extern void grpcsharp_redirect_log(GprLogDelegate callback); + + [DllImport(ImportName)] + public static extern void grpcsharp_native_callback_dispatcher_init(NativeCallbackDispatcherCallback dispatcher); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(IntPtr nativeCallbackTag); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); + + [DllImport(ImportName)] + public static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, SslClientCertificateRequestType clientCertificateRequest); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ServerSafeHandle grpcsharp_server_create(ChannelArgsSafeHandle args); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_register_completion_queue(ServerSafeHandle server, CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_insecure_http2_port(ServerSafeHandle server, string addr); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_start(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_cancel_all_calls(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_shutdown_and_notify_callback(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_destroy(IntPtr server); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle grpcsharp_call_auth_context(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_context_peer_identity_property_name(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle.NativeAuthPropertyIterator grpcsharp_auth_context_property_iterator(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_property_iterator_next(ref AuthContextSafeHandle.NativeAuthPropertyIterator iterator); + + [DllImport(ImportName)] + public static extern void grpcsharp_auth_context_release(IntPtr authContext); + + [DllImport(ImportName)] + public static extern SliceBufferSafeHandle grpcsharp_slice_buffer_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_slice_buffer_adjust_tail_space(SliceBufferSafeHandle sliceBuffer, UIntPtr availableTailSpace, UIntPtr requestedTailSpace); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_slice_buffer_slice_count(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_slice_peek(SliceBufferSafeHandle sliceBuffer, UIntPtr index, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_reset_and_unref(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_destroy(IntPtr sliceBuffer); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_now(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_future(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_past(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_convert_clock_type(Timespec t, ClockType targetClock); + + [DllImport(ImportName)] + public static extern int gprsharp_sizeof_timespec(); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] NativeCallbackTestDelegate callback); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_test_nop(IntPtr ptr); + + [DllImport(ImportName)] + public static extern void grpcsharp_test_override_method(string methodName, string variant); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_call_start_unary_echo(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + } + + /// + /// grpc_csharp_ext used as a shared library (with x86 suffix) + /// + internal class DllImportsFromSharedLib_x86 + { + private const string ImportName = "grpc_csharp_ext.x86"; + + [DllImport(ImportName)] + public static extern void grpcsharp_init(); + + [DllImport(ImportName)] + public static extern void grpcsharp_shutdown(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_version_string(); + + [DllImport(ImportName)] + public static extern BatchContextSafeHandle grpcsharp_batch_context_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_initial_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_message_length(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_message_next_slice_peek(BatchContextSafeHandle ctx, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern StatusCode grpcsharp_batch_context_recv_status_on_client_status(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx, out UIntPtr detailsLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_error_string(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_close_on_server_cancelled(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_reset(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern RequestCallContextSafeHandle grpcsharp_request_call_context_create(); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_request_call_context_call(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_method(RequestCallContextSafeHandle ctx, out UIntPtr methodLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_host(RequestCallContextSafeHandle ctx, out UIntPtr hostLength); + + [DllImport(ImportName)] + public static extern Timespec grpcsharp_request_call_context_deadline(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_request_metadata(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_reset(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_unary(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_client_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_server_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_message(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, int sendEmptyInitialMetadata); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_close_from_client(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, SliceBufferSafeHandle optionalSendBuffer, WriteFlags writeFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_message(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_serverside(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_destroy(IntPtr call); + + [DllImport(ImportName)] + public static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_destroy(IntPtr args); + + [DllImport(ImportName)] + public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); + + [DllImport(ImportName)] + public static extern ChannelState grpcsharp_channel_check_connectivity_state(ChannelSafeHandle channel, int tryToConnect); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_watch_connectivity_state(ChannelSafeHandle channel, ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_channel_get_target(ChannelSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_destroy(IntPtr channel); + + [DllImport(ImportName)] + public static extern int grpcsharp_sizeof_grpc_event(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_async(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_sync(); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_shutdown(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_next(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_pluck(CompletionQueueSafeHandle cq, IntPtr tag); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_destroy(IntPtr cq); + + [DllImport(ImportName)] + public static extern void gprsharp_free(IntPtr ptr); + + [DllImport(ImportName)] + public static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_metadata_array_count(IntPtr metadataArray); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_key(IntPtr metadataArray, UIntPtr index, out UIntPtr keyLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_value(IntPtr metadataArray, UIntPtr index, out UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_destroy_full(IntPtr array); + + [DllImport(ImportName)] + public static extern void grpcsharp_redirect_log(GprLogDelegate callback); + + [DllImport(ImportName)] + public static extern void grpcsharp_native_callback_dispatcher_init(NativeCallbackDispatcherCallback dispatcher); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(IntPtr nativeCallbackTag); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); + + [DllImport(ImportName)] + public static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, SslClientCertificateRequestType clientCertificateRequest); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ServerSafeHandle grpcsharp_server_create(ChannelArgsSafeHandle args); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_register_completion_queue(ServerSafeHandle server, CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_insecure_http2_port(ServerSafeHandle server, string addr); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_start(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_cancel_all_calls(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_shutdown_and_notify_callback(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_destroy(IntPtr server); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle grpcsharp_call_auth_context(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_context_peer_identity_property_name(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle.NativeAuthPropertyIterator grpcsharp_auth_context_property_iterator(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_property_iterator_next(ref AuthContextSafeHandle.NativeAuthPropertyIterator iterator); + + [DllImport(ImportName)] + public static extern void grpcsharp_auth_context_release(IntPtr authContext); + + [DllImport(ImportName)] + public static extern SliceBufferSafeHandle grpcsharp_slice_buffer_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_slice_buffer_adjust_tail_space(SliceBufferSafeHandle sliceBuffer, UIntPtr availableTailSpace, UIntPtr requestedTailSpace); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_slice_buffer_slice_count(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_slice_peek(SliceBufferSafeHandle sliceBuffer, UIntPtr index, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_reset_and_unref(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_destroy(IntPtr sliceBuffer); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_now(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_future(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_past(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_convert_clock_type(Timespec t, ClockType targetClock); + + [DllImport(ImportName)] + public static extern int gprsharp_sizeof_timespec(); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] NativeCallbackTestDelegate callback); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_test_nop(IntPtr ptr); + + [DllImport(ImportName)] + public static extern void grpcsharp_test_override_method(string methodName, string variant); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_call_start_unary_echo(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + } + + /// + /// grpc_csharp_ext used as a shared library (with x64 suffix) + /// + internal class DllImportsFromSharedLib_x64 + { + private const string ImportName = "grpc_csharp_ext.x64"; + + [DllImport(ImportName)] + public static extern void grpcsharp_init(); + + [DllImport(ImportName)] + public static extern void grpcsharp_shutdown(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_version_string(); + + [DllImport(ImportName)] + public static extern BatchContextSafeHandle grpcsharp_batch_context_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_initial_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_message_length(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_message_next_slice_peek(BatchContextSafeHandle ctx, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern StatusCode grpcsharp_batch_context_recv_status_on_client_status(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx, out UIntPtr detailsLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_error_string(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_close_on_server_cancelled(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_reset(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern RequestCallContextSafeHandle grpcsharp_request_call_context_create(); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_request_call_context_call(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_method(RequestCallContextSafeHandle ctx, out UIntPtr methodLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_host(RequestCallContextSafeHandle ctx, out UIntPtr hostLength); + + [DllImport(ImportName)] + public static extern Timespec grpcsharp_request_call_context_deadline(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_request_metadata(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_reset(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_unary(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_client_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_server_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_message(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, int sendEmptyInitialMetadata); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_close_from_client(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, SliceBufferSafeHandle optionalSendBuffer, WriteFlags writeFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_message(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_serverside(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_destroy(IntPtr call); + + [DllImport(ImportName)] + public static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_destroy(IntPtr args); + + [DllImport(ImportName)] + public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); + + [DllImport(ImportName)] + public static extern ChannelState grpcsharp_channel_check_connectivity_state(ChannelSafeHandle channel, int tryToConnect); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_watch_connectivity_state(ChannelSafeHandle channel, ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_channel_get_target(ChannelSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_destroy(IntPtr channel); + + [DllImport(ImportName)] + public static extern int grpcsharp_sizeof_grpc_event(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_async(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_sync(); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_shutdown(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_next(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_pluck(CompletionQueueSafeHandle cq, IntPtr tag); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_destroy(IntPtr cq); + + [DllImport(ImportName)] + public static extern void gprsharp_free(IntPtr ptr); + + [DllImport(ImportName)] + public static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_metadata_array_count(IntPtr metadataArray); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_key(IntPtr metadataArray, UIntPtr index, out UIntPtr keyLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_value(IntPtr metadataArray, UIntPtr index, out UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_destroy_full(IntPtr array); + + [DllImport(ImportName)] + public static extern void grpcsharp_redirect_log(GprLogDelegate callback); + + [DllImport(ImportName)] + public static extern void grpcsharp_native_callback_dispatcher_init(NativeCallbackDispatcherCallback dispatcher); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(IntPtr nativeCallbackTag); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); + + [DllImport(ImportName)] + public static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, SslClientCertificateRequestType clientCertificateRequest); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ServerSafeHandle grpcsharp_server_create(ChannelArgsSafeHandle args); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_register_completion_queue(ServerSafeHandle server, CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_insecure_http2_port(ServerSafeHandle server, string addr); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_start(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_cancel_all_calls(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_shutdown_and_notify_callback(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_destroy(IntPtr server); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle grpcsharp_call_auth_context(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_context_peer_identity_property_name(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle.NativeAuthPropertyIterator grpcsharp_auth_context_property_iterator(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_property_iterator_next(ref AuthContextSafeHandle.NativeAuthPropertyIterator iterator); + + [DllImport(ImportName)] + public static extern void grpcsharp_auth_context_release(IntPtr authContext); + + [DllImport(ImportName)] + public static extern SliceBufferSafeHandle grpcsharp_slice_buffer_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_slice_buffer_adjust_tail_space(SliceBufferSafeHandle sliceBuffer, UIntPtr availableTailSpace, UIntPtr requestedTailSpace); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_slice_buffer_slice_count(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_slice_peek(SliceBufferSafeHandle sliceBuffer, UIntPtr index, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_reset_and_unref(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_destroy(IntPtr sliceBuffer); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_now(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_future(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_past(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_convert_clock_type(Timespec t, ClockType targetClock); + + [DllImport(ImportName)] + public static extern int gprsharp_sizeof_timespec(); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] NativeCallbackTestDelegate callback); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_test_nop(IntPtr ptr); + + [DllImport(ImportName)] + public static extern void grpcsharp_test_override_method(string methodName, string variant); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_call_start_unary_echo(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + } + + /// + /// grpc_csharp_ext used as a shared library (with arm64 suffix) + /// + internal class DllImportsFromSharedLib_arm64 + { + private const string ImportName = "grpc_csharp_ext.arm64"; + + [DllImport(ImportName)] + public static extern void grpcsharp_init(); + + [DllImport(ImportName)] + public static extern void grpcsharp_shutdown(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_version_string(); + + [DllImport(ImportName)] + public static extern BatchContextSafeHandle grpcsharp_batch_context_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_initial_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_message_length(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_message_next_slice_peek(BatchContextSafeHandle ctx, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern StatusCode grpcsharp_batch_context_recv_status_on_client_status(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx, out UIntPtr detailsLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_error_string(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_close_on_server_cancelled(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_reset(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern RequestCallContextSafeHandle grpcsharp_request_call_context_create(); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_request_call_context_call(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_method(RequestCallContextSafeHandle ctx, out UIntPtr methodLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_host(RequestCallContextSafeHandle ctx, out UIntPtr hostLength); + + [DllImport(ImportName)] + public static extern Timespec grpcsharp_request_call_context_deadline(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_request_metadata(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_reset(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_unary(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_client_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_server_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_message(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, int sendEmptyInitialMetadata); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_close_from_client(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, SliceBufferSafeHandle optionalSendBuffer, WriteFlags writeFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_message(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_serverside(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_destroy(IntPtr call); + + [DllImport(ImportName)] + public static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_destroy(IntPtr args); + + [DllImport(ImportName)] + public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); + + [DllImport(ImportName)] + public static extern ChannelState grpcsharp_channel_check_connectivity_state(ChannelSafeHandle channel, int tryToConnect); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_watch_connectivity_state(ChannelSafeHandle channel, ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_channel_get_target(ChannelSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_destroy(IntPtr channel); + + [DllImport(ImportName)] + public static extern int grpcsharp_sizeof_grpc_event(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_async(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_sync(); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_shutdown(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_next(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_pluck(CompletionQueueSafeHandle cq, IntPtr tag); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_destroy(IntPtr cq); + + [DllImport(ImportName)] + public static extern void gprsharp_free(IntPtr ptr); + + [DllImport(ImportName)] + public static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_metadata_array_count(IntPtr metadataArray); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_key(IntPtr metadataArray, UIntPtr index, out UIntPtr keyLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_value(IntPtr metadataArray, UIntPtr index, out UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_destroy_full(IntPtr array); + + [DllImport(ImportName)] + public static extern void grpcsharp_redirect_log(GprLogDelegate callback); + + [DllImport(ImportName)] + public static extern void grpcsharp_native_callback_dispatcher_init(NativeCallbackDispatcherCallback dispatcher); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(IntPtr nativeCallbackTag); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); + + [DllImport(ImportName)] + public static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, SslClientCertificateRequestType clientCertificateRequest); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ServerSafeHandle grpcsharp_server_create(ChannelArgsSafeHandle args); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_register_completion_queue(ServerSafeHandle server, CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_insecure_http2_port(ServerSafeHandle server, string addr); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_start(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_cancel_all_calls(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_shutdown_and_notify_callback(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_destroy(IntPtr server); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle grpcsharp_call_auth_context(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_context_peer_identity_property_name(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle.NativeAuthPropertyIterator grpcsharp_auth_context_property_iterator(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_property_iterator_next(ref AuthContextSafeHandle.NativeAuthPropertyIterator iterator); + + [DllImport(ImportName)] + public static extern void grpcsharp_auth_context_release(IntPtr authContext); + + [DllImport(ImportName)] + public static extern SliceBufferSafeHandle grpcsharp_slice_buffer_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_slice_buffer_adjust_tail_space(SliceBufferSafeHandle sliceBuffer, UIntPtr availableTailSpace, UIntPtr requestedTailSpace); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_slice_buffer_slice_count(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_slice_peek(SliceBufferSafeHandle sliceBuffer, UIntPtr index, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_reset_and_unref(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_destroy(IntPtr sliceBuffer); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_now(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_future(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_past(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_convert_clock_type(Timespec t, ClockType targetClock); + + [DllImport(ImportName)] + public static extern int gprsharp_sizeof_timespec(); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] NativeCallbackTestDelegate callback); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_test_nop(IntPtr ptr); + + [DllImport(ImportName)] + public static extern void grpcsharp_test_override_method(string methodName, string variant); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_call_start_unary_echo(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + } + + /// + /// grpc_csharp_ext used as a shared library (with x86.dll suffix) + /// + internal class DllImportsFromSharedLib_x86_dll + { + private const string ImportName = "grpc_csharp_ext.x86.dll"; + + [DllImport(ImportName)] + public static extern void grpcsharp_init(); + + [DllImport(ImportName)] + public static extern void grpcsharp_shutdown(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_version_string(); + + [DllImport(ImportName)] + public static extern BatchContextSafeHandle grpcsharp_batch_context_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_initial_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_message_length(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_message_next_slice_peek(BatchContextSafeHandle ctx, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern StatusCode grpcsharp_batch_context_recv_status_on_client_status(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx, out UIntPtr detailsLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_error_string(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_close_on_server_cancelled(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_reset(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern RequestCallContextSafeHandle grpcsharp_request_call_context_create(); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_request_call_context_call(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_method(RequestCallContextSafeHandle ctx, out UIntPtr methodLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_host(RequestCallContextSafeHandle ctx, out UIntPtr hostLength); + + [DllImport(ImportName)] + public static extern Timespec grpcsharp_request_call_context_deadline(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_request_metadata(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_reset(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_unary(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_client_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_server_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_message(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, int sendEmptyInitialMetadata); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_close_from_client(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, SliceBufferSafeHandle optionalSendBuffer, WriteFlags writeFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_message(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_serverside(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_destroy(IntPtr call); + + [DllImport(ImportName)] + public static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_destroy(IntPtr args); + + [DllImport(ImportName)] + public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); + + [DllImport(ImportName)] + public static extern ChannelState grpcsharp_channel_check_connectivity_state(ChannelSafeHandle channel, int tryToConnect); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_watch_connectivity_state(ChannelSafeHandle channel, ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_channel_get_target(ChannelSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_destroy(IntPtr channel); + + [DllImport(ImportName)] + public static extern int grpcsharp_sizeof_grpc_event(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_async(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_sync(); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_shutdown(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_next(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_pluck(CompletionQueueSafeHandle cq, IntPtr tag); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_destroy(IntPtr cq); + + [DllImport(ImportName)] + public static extern void gprsharp_free(IntPtr ptr); + + [DllImport(ImportName)] + public static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_metadata_array_count(IntPtr metadataArray); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_key(IntPtr metadataArray, UIntPtr index, out UIntPtr keyLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_value(IntPtr metadataArray, UIntPtr index, out UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_destroy_full(IntPtr array); + + [DllImport(ImportName)] + public static extern void grpcsharp_redirect_log(GprLogDelegate callback); + + [DllImport(ImportName)] + public static extern void grpcsharp_native_callback_dispatcher_init(NativeCallbackDispatcherCallback dispatcher); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(IntPtr nativeCallbackTag); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); + + [DllImport(ImportName)] + public static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, SslClientCertificateRequestType clientCertificateRequest); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ServerSafeHandle grpcsharp_server_create(ChannelArgsSafeHandle args); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_register_completion_queue(ServerSafeHandle server, CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_insecure_http2_port(ServerSafeHandle server, string addr); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_start(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_cancel_all_calls(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_shutdown_and_notify_callback(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_destroy(IntPtr server); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle grpcsharp_call_auth_context(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_context_peer_identity_property_name(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle.NativeAuthPropertyIterator grpcsharp_auth_context_property_iterator(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_property_iterator_next(ref AuthContextSafeHandle.NativeAuthPropertyIterator iterator); + + [DllImport(ImportName)] + public static extern void grpcsharp_auth_context_release(IntPtr authContext); + + [DllImport(ImportName)] + public static extern SliceBufferSafeHandle grpcsharp_slice_buffer_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_slice_buffer_adjust_tail_space(SliceBufferSafeHandle sliceBuffer, UIntPtr availableTailSpace, UIntPtr requestedTailSpace); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_slice_buffer_slice_count(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_slice_peek(SliceBufferSafeHandle sliceBuffer, UIntPtr index, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_reset_and_unref(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_destroy(IntPtr sliceBuffer); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_now(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_future(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_past(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_convert_clock_type(Timespec t, ClockType targetClock); + + [DllImport(ImportName)] + public static extern int gprsharp_sizeof_timespec(); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] NativeCallbackTestDelegate callback); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_test_nop(IntPtr ptr); + + [DllImport(ImportName)] + public static extern void grpcsharp_test_override_method(string methodName, string variant); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_call_start_unary_echo(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + } + + /// + /// grpc_csharp_ext used as a shared library (with x64.dll suffix) + /// + internal class DllImportsFromSharedLib_x64_dll + { + private const string ImportName = "grpc_csharp_ext.x64.dll"; + + [DllImport(ImportName)] + public static extern void grpcsharp_init(); + + [DllImport(ImportName)] + public static extern void grpcsharp_shutdown(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_version_string(); + + [DllImport(ImportName)] + public static extern BatchContextSafeHandle grpcsharp_batch_context_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_initial_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_message_length(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_message_next_slice_peek(BatchContextSafeHandle ctx, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern StatusCode grpcsharp_batch_context_recv_status_on_client_status(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx, out UIntPtr detailsLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_error_string(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_close_on_server_cancelled(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_reset(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern RequestCallContextSafeHandle grpcsharp_request_call_context_create(); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_request_call_context_call(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_method(RequestCallContextSafeHandle ctx, out UIntPtr methodLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_host(RequestCallContextSafeHandle ctx, out UIntPtr hostLength); + + [DllImport(ImportName)] + public static extern Timespec grpcsharp_request_call_context_deadline(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_request_metadata(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_reset(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_unary(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_client_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_server_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_message(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, int sendEmptyInitialMetadata); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_close_from_client(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, SliceBufferSafeHandle optionalSendBuffer, WriteFlags writeFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_message(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_serverside(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_destroy(IntPtr call); + + [DllImport(ImportName)] + public static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_destroy(IntPtr args); + + [DllImport(ImportName)] + public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); + + [DllImport(ImportName)] + public static extern ChannelState grpcsharp_channel_check_connectivity_state(ChannelSafeHandle channel, int tryToConnect); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_watch_connectivity_state(ChannelSafeHandle channel, ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_channel_get_target(ChannelSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_destroy(IntPtr channel); + + [DllImport(ImportName)] + public static extern int grpcsharp_sizeof_grpc_event(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_async(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_sync(); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_shutdown(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_next(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_pluck(CompletionQueueSafeHandle cq, IntPtr tag); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_destroy(IntPtr cq); + + [DllImport(ImportName)] + public static extern void gprsharp_free(IntPtr ptr); + + [DllImport(ImportName)] + public static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_metadata_array_count(IntPtr metadataArray); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_key(IntPtr metadataArray, UIntPtr index, out UIntPtr keyLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_value(IntPtr metadataArray, UIntPtr index, out UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_destroy_full(IntPtr array); + + [DllImport(ImportName)] + public static extern void grpcsharp_redirect_log(GprLogDelegate callback); + + [DllImport(ImportName)] + public static extern void grpcsharp_native_callback_dispatcher_init(NativeCallbackDispatcherCallback dispatcher); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(IntPtr nativeCallbackTag); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); + + [DllImport(ImportName)] + public static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, SslClientCertificateRequestType clientCertificateRequest); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ServerSafeHandle grpcsharp_server_create(ChannelArgsSafeHandle args); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_register_completion_queue(ServerSafeHandle server, CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_insecure_http2_port(ServerSafeHandle server, string addr); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_start(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_cancel_all_calls(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_shutdown_and_notify_callback(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_destroy(IntPtr server); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle grpcsharp_call_auth_context(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_context_peer_identity_property_name(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle.NativeAuthPropertyIterator grpcsharp_auth_context_property_iterator(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_property_iterator_next(ref AuthContextSafeHandle.NativeAuthPropertyIterator iterator); + + [DllImport(ImportName)] + public static extern void grpcsharp_auth_context_release(IntPtr authContext); + + [DllImport(ImportName)] + public static extern SliceBufferSafeHandle grpcsharp_slice_buffer_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_slice_buffer_adjust_tail_space(SliceBufferSafeHandle sliceBuffer, UIntPtr availableTailSpace, UIntPtr requestedTailSpace); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_slice_buffer_slice_count(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_slice_peek(SliceBufferSafeHandle sliceBuffer, UIntPtr index, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_reset_and_unref(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_destroy(IntPtr sliceBuffer); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_now(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_future(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_past(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_convert_clock_type(Timespec t, ClockType targetClock); + + [DllImport(ImportName)] + public static extern int gprsharp_sizeof_timespec(); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] NativeCallbackTestDelegate callback); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_test_nop(IntPtr ptr); + + [DllImport(ImportName)] + public static extern void grpcsharp_test_override_method(string methodName, string variant); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_call_start_unary_echo(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs new file mode 100644 index 00000000..4e512442 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs @@ -0,0 +1,68 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; + +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + internal delegate void NativeCallbackTestDelegate(bool success); + + /// + /// Provides access to all native methods provided by NativeExtension. + /// An extra level of indirection is added to P/Invoke calls to allow intelligent loading + /// of the right configuration of the native extension based on current platform, architecture etc. + /// + internal partial class NativeMethods + { + // Signatures of native methods are generated from a template + // and can be found in NativeMethods.Generated.cs + + /// + /// Gets singleton instance of this class. + /// + public static NativeMethods Get() + { + return NativeExtension.Get().NativeMethods; + } + + static T GetMethodDelegate(UnmanagedLibrary library) + where T : class + { + var methodName = RemoveStringSuffix(typeof(T).Name, "_delegate"); + return library.GetNativeMethodDelegate(methodName); + } + + static string RemoveStringSuffix(string str, string toRemove) + { + if (!str.EndsWith(toRemove)) + { + return str; + } + return str.Substring(0, str.Length - toRemove.Length); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/PlatformApis.cs b/src/csharp/Grpc.Core/Internal/PlatformApis.cs new file mode 100644 index 00000000..5ad443b5 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/PlatformApis.cs @@ -0,0 +1,253 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Utility methods for detecting platform and architecture. + /// + internal static class PlatformApis + { + const string UnityEngineAssemblyName = "UnityEngine"; + + const string UnityEngineApplicationClassName = "UnityEngine.Application"; + + const string UnityIPhonePlayer = "IPhonePlayer"; + const string XamarinAndroidObjectClassName = "Java.Lang.Object, Mono.Android"; + const string XamarinIOSObjectClassName = "Foundation.NSObject, Xamarin.iOS"; + + static readonly bool isLinux; + static readonly bool isMacOSX; + static readonly bool isWindows; + static readonly bool isMono; + static readonly bool isNet5OrHigher; + static readonly bool isNetCore; + static readonly string frameworkDescription; + static readonly string clrVersion; + static readonly string unityApplicationPlatform; + static readonly bool isXamarin; + static readonly bool isXamarinIOS; + static readonly bool isXamarinAndroid; + + static PlatformApis() + { + // Detect OS + var osKind = CommonPlatformDetection.GetOSKind(); + isLinux = osKind == CommonPlatformDetection.OSKind.Linux; + isMacOSX = osKind == CommonPlatformDetection.OSKind.MacOSX; + isWindows = osKind == CommonPlatformDetection.OSKind.Windows; + +#if NETSTANDARD1_5 + // assume that on .NET 5+, the netstandard2.0 or newer TFM is always going to be selected + // so for netstandard1.5 we assume we are never on .NET5+ + isNet5OrHigher = false; + isNetCore = isNet5OrHigher || RuntimeInformation.FrameworkDescription.StartsWith(".NET Core"); +#elif NETSTANDARD + isNet5OrHigher = Environment.Version.Major >= 5; + isNetCore = isNet5OrHigher || RuntimeInformation.FrameworkDescription.StartsWith(".NET Core"); +#else + isNet5OrHigher = false; + isNetCore = false; +#endif + frameworkDescription = TryGetFrameworkDescription(); + clrVersion = TryGetClrVersion(); + + // Detect mono runtime + isMono = Type.GetType("Mono.Runtime") != null; + + // Unity + unityApplicationPlatform = TryGetUnityApplicationPlatform(); + + // Xamarin + isXamarinIOS = Type.GetType(XamarinIOSObjectClassName) != null; + isXamarinAndroid = Type.GetType(XamarinAndroidObjectClassName) != null; + isXamarin = isXamarinIOS || isXamarinAndroid; + } + + public static bool IsLinux => isLinux; + + public static bool IsMacOSX => isMacOSX; + + public static bool IsWindows => isWindows; + + public static bool IsMono => isMono; + + /// + /// true if running on Unity platform. + /// + public static bool IsUnity => unityApplicationPlatform != null; + + /// + /// true if running on Unity iOS, false otherwise. + /// + public static bool IsUnityIOS => unityApplicationPlatform == UnityIPhonePlayer; + + /// + /// true if running on a Xamarin platform (either Xamarin.Android or Xamarin.iOS), + /// false otherwise. + /// + public static bool IsXamarin => isXamarin; + + /// + /// true if running on Xamarin.iOS, false otherwise. + /// + public static bool IsXamarinIOS => isXamarinIOS; + + /// + /// true if running on Xamarin.Android, false otherwise. + /// + public static bool IsXamarinAndroid => isXamarinAndroid; + + /// + /// true if running on .NET 5+, false otherwise. + /// + public static bool IsNet5OrHigher => isNet5OrHigher; + + /// + /// Contains RuntimeInformation.FrameworkDescription if the property is available on current TFM. + /// null otherwise. + /// + public static string FrameworkDescription => frameworkDescription; + + /// + /// Contains the version of common language runtime obtained from Environment.Version + /// if the property is available on current TFM. null otherwise. + /// + public static string ClrVersion => clrVersion; + + /// + /// true if running on .NET Core (CoreCLR) or NET 5+, false otherwise. + /// + public static bool IsNetCore => isNetCore; + + public static bool Is64Bit => IntPtr.Size == 8; + + public static CommonPlatformDetection.CpuArchitecture ProcessArchitecture => CommonPlatformDetection.GetProcessArchitecture(); + + /// + /// Returns UnityEngine.Application.platform as a string. + /// See https://docs.unity3d.com/ScriptReference/Application-platform.html for possible values. + /// Value is obtained via reflection to avoid compile-time dependency on Unity. + /// This method should only be called if IsUnity is true. + /// + public static string GetUnityApplicationPlatform() + { + GrpcPreconditions.CheckState(IsUnity, "Not running on Unity."); + return unityApplicationPlatform; + } + + /// + /// Returns UnityEngine.Application.platform as a string or null + /// if not running on Unity. + /// Value is obtained via reflection to avoid compile-time dependency on Unity. + /// + static string TryGetUnityApplicationPlatform() + { + Assembly unityAssembly = null; +#if !NETSTANDARD1_5 + // On netstandard1.5, AppDomain is not available and we just short-circuit the logic there. + // This is fine because only the net45 or netstandard2.0 version Grpc.Core assembly is going to used in Unity. + // NOTE: Instead of trying to load the UnityEngine.Application class via Type.GetType() + // we are using a more sneaky approach to avoid inadvertently loading the UnityEngine + // assembly (that might be available even when we are not actually on Unity, resulting + // in false positive). See https://github.com/grpc/grpc/issues/18801 + unityAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(assembly => assembly.GetName().Name == UnityEngineAssemblyName); +#endif + var applicationClass = unityAssembly?.GetType(UnityEngineApplicationClassName); + var platformProperty = applicationClass?.GetTypeInfo().GetProperty("platform", BindingFlags.Static | BindingFlags.Public); + try + { + // Consult value of Application.platform via reflection + // https://docs.unity3d.com/ScriptReference/Application-platform.html + return platformProperty?.GetValue(null)?.ToString(); + } + catch (TargetInvocationException) + { + // The getter for Application.platform is defined as "extern", so if UnityEngine assembly is loaded outside of a Unity application, + // the definition for the getter will be missing - note that this is a sneaky trick that helps us tell a real Unity application from a non-unity + // application which just happens to have loaded the UnityEngine.dll assembly. + // https://github.com/Unity-Technologies/UnityCsReference/blob/61f92bd79ae862c4465d35270f9d1d57befd1761/Runtime/Export/Application/Application.bindings.cs#L375 + // See https://github.com/grpc/grpc/issues/23334 + + // If TargetInvocationException was thrown, it most likely means that the method definition for the extern method is missing, + // and we are going to interpret this as "not running on Unity". + return null; + } + } + + /// + /// Returns description of the framework this process is running on. + /// Value is based on RuntimeInformation.FrameworkDescription. + /// + static string TryGetFrameworkDescription() + { +#if NETSTANDARD + return RuntimeInformation.FrameworkDescription; +#else + // on full .NET framework we are targeting net45, and the property is only available starting from .NET Framework 4.7.1+ + // try obtaining the value by reflection since we might be running on a newer framework even though we're targeting + // an older one. + var runtimeInformationClass = Type.GetType("System.Runtime.InteropServices.RuntimeInformation"); + var frameworkDescriptionProperty = runtimeInformationClass?.GetTypeInfo().GetProperty("FrameworkDescription", BindingFlags.Static | BindingFlags.Public); + return frameworkDescriptionProperty?.GetValue(null)?.ToString(); +#endif + } + + /// + /// Returns version of the common language runtime this process is running on. + /// Value is based on Environment.Version. + /// + static string TryGetClrVersion() + { +#if NETSTANDARD1_5 + return null; +#else + return Environment.Version.ToString(); +#endif + } + + /// + /// Returns the TFM of the Grpc.Core assembly. + /// + public static string GetGrpcCoreTargetFrameworkMoniker() + { +#if NETSTANDARD1_5 + return "netstandard1.5"; +#elif NETSTANDARD2_0 + return "netstandard2.0"; +#elif NET45 + return "net45"; +#else + // The TFM is determined at compile time. + // The is intentionally no "default" return clause here so that + // if the set of TFMs we build for changes and this method is not updated accordingly, + // it will result in compilation error. +#endif + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs b/src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs new file mode 100644 index 00000000..24fde75e --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/RequestCallContextSafeHandle.cs @@ -0,0 +1,124 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Runtime.InteropServices; +using Grpc.Core; +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// grpcsharp_request_call_context + /// + internal class RequestCallContextSafeHandle : SafeHandleZeroIsInvalid, IOpCompletionCallback, IPooledObject + { + static readonly NativeMethods Native = NativeMethods.Get(); + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + Action returnToPoolAction; + + private RequestCallContextSafeHandle() + { + } + + public static RequestCallContextSafeHandle Create() + { + var ctx = Native.grpcsharp_request_call_context_create(); + return ctx; + } + + public IntPtr Handle + { + get + { + return handle; + } + } + + public void SetReturnToPoolAction(Action returnAction) + { + GrpcPreconditions.CheckState(returnToPoolAction == null); + returnToPoolAction = returnAction; + } + + public RequestCallCompletionDelegate CompletionCallback { get; set; } + + // Gets data of server_rpc_new completion. + public ServerRpcNew GetServerRpcNew(Server server) + { + var call = Native.grpcsharp_request_call_context_call(this); + + UIntPtr methodLen; + IntPtr methodPtr = Native.grpcsharp_request_call_context_method(this, out methodLen); + var method = Marshal.PtrToStringAnsi(methodPtr, (int) methodLen.ToUInt32()); + + UIntPtr hostLen; + IntPtr hostPtr = Native.grpcsharp_request_call_context_host(this, out hostLen); + var host = Marshal.PtrToStringAnsi(hostPtr, (int) hostLen.ToUInt32()); + + var deadline = Native.grpcsharp_request_call_context_deadline(this); + + IntPtr metadataArrayPtr = Native.grpcsharp_request_call_context_request_metadata(this); + var metadata = MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr); + + return new ServerRpcNew(server, call, method, host, deadline, metadata); + } + + public void Recycle() + { + if (returnToPoolAction != null) + { + Native.grpcsharp_request_call_context_reset(this); + + var origReturnAction = returnToPoolAction; + // Not clearing all the references to the pool could prevent garbage collection of the pool object + // and thus cause memory leaks. + returnToPoolAction = null; + origReturnAction(this); + } + else + { + Dispose(); + } + } + + protected override bool ReleaseHandle() + { + Native.grpcsharp_request_call_context_destroy(handle); + return true; + } + + void IOpCompletionCallback.OnComplete(bool success) + { + try + { + CompletionCallback(success, this); + } + catch (Exception e) + { + Logger.Error(e, "Exception occurred while invoking request call completion delegate."); + } + finally + { + CompletionCallback = null; + Recycle(); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ReusableSliceBuffer.cs b/src/csharp/Grpc.Core/Internal/ReusableSliceBuffer.cs new file mode 100644 index 00000000..eed6ba4a --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ReusableSliceBuffer.cs @@ -0,0 +1,106 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using Grpc.Core.Utils; +using System; +using System.Threading; + +using System.Buffers; + +namespace Grpc.Core.Internal +{ + internal class ReusableSliceBuffer + { + public const int MaxCachedSegments = 1024; // ~4MB payload for 4K slices + + readonly SliceSegment[] cachedSegments = new SliceSegment[MaxCachedSegments]; + int populatedSegmentCount; + + public ReadOnlySequence PopulateFrom(IBufferReader bufferReader) + { + populatedSegmentCount = 0; + long offset = 0; + SliceSegment prevSegment = null; + while (bufferReader.TryGetNextSlice(out Slice slice)) + { + // Initialize cached segment if still null or just allocate a new segment if we already reached MaxCachedSegments + var current = populatedSegmentCount < cachedSegments.Length ? cachedSegments[populatedSegmentCount] : new SliceSegment(); + if (current == null) + { + current = cachedSegments[populatedSegmentCount] = new SliceSegment(); + } + + current.Reset(slice, offset); + prevSegment?.SetNext(current); + + populatedSegmentCount ++; + offset += slice.Length; + prevSegment = current; + } + + // Not necessary for ending the ReadOnlySequence, but for making sure we + // don't keep more than MaxCachedSegments alive. + prevSegment?.SetNext(null); + + if (populatedSegmentCount == 0) + { + return ReadOnlySequence.Empty; + } + + var firstSegment = cachedSegments[0]; + var lastSegment = prevSegment; + return new ReadOnlySequence(firstSegment, 0, lastSegment, lastSegment.Memory.Length); + } + + public void Invalidate() + { + if (populatedSegmentCount == 0) + { + return; + } + var segment = cachedSegments[0]; + while (segment != null) + { + segment.Reset(new Slice(IntPtr.Zero, 0), 0); + var nextSegment = (SliceSegment) segment.Next; + segment.SetNext(null); + segment = nextSegment; + } + populatedSegmentCount = 0; + } + + // Represents a segment in ReadOnlySequence + // Segment is backed by Slice and the instances are reusable. + private class SliceSegment : ReadOnlySequenceSegment + { + readonly SliceMemoryManager pointerMemoryManager = new SliceMemoryManager(); + + public void Reset(Slice slice, long runningIndex) + { + pointerMemoryManager.Reset(slice); + Memory = pointerMemoryManager.Memory; // maybe not always necessary + RunningIndex = runningIndex; + } + + public void SetNext(ReadOnlySequenceSegment next) + { + Next = next; + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs b/src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs new file mode 100644 index 00000000..0d4238fc --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs @@ -0,0 +1,41 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Runtime.InteropServices; + +namespace Grpc.Core.Internal +{ + /// + /// Safe handle to wrap native objects. + /// + internal abstract class SafeHandleZeroIsInvalid : System.Runtime.InteropServices.SafeHandle + { + public SafeHandleZeroIsInvalid() : base(IntPtr.Zero, true) + { + } + + public override bool IsInvalid + { + get + { + return handle == IntPtr.Zero; + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs new file mode 100644 index 00000000..0c929741 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs @@ -0,0 +1,328 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core.Interceptors; +using Grpc.Core.Internal; +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + internal interface IServerCallHandler + { + Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq); + } + + internal class UnaryServerCallHandler : IServerCallHandler + where TRequest : class + where TResponse : class + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType>(); + + readonly Method method; + readonly UnaryServerMethod handler; + + public UnaryServerCallHandler(Method method, UnaryServerMethod handler) + { + this.method = method; + this.handler = handler; + } + + public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq) + { + var asyncCall = new AsyncCallServer( + method.ResponseMarshaller.ContextualSerializer, + method.RequestMarshaller.ContextualDeserializer, + newRpc.Server); + + asyncCall.Initialize(newRpc.Call, cq); + var finishedTask = asyncCall.ServerSideCallAsync(); + var requestStream = new ServerRequestStream(asyncCall); + var responseStream = new ServerResponseStream(asyncCall); + + Status status; + AsyncCallServer.ResponseWithFlags? responseWithFlags = null; + var context = HandlerUtils.NewContext(newRpc, responseStream, asyncCall.CancellationToken); + try + { + GrpcPreconditions.CheckArgument(await requestStream.MoveNext().ConfigureAwait(false)); + var request = requestStream.Current; + var response = await handler(request, context).ConfigureAwait(false); + status = context.Status; + responseWithFlags = new AsyncCallServer.ResponseWithFlags(response, HandlerUtils.GetWriteFlags(context.WriteOptions)); + } + catch (Exception e) + { + if (!(e is RpcException)) + { + Logger.Warning(e, "Exception occurred in the handler or an interceptor."); + } + status = HandlerUtils.GetStatusFromExceptionAndMergeTrailers(e, context.ResponseTrailers); + } + try + { + await asyncCall.SendStatusFromServerAsync(status, context.ResponseTrailers, responseWithFlags).ConfigureAwait(false); + } + catch (Exception) + { + asyncCall.Cancel(); + throw; + } + await finishedTask.ConfigureAwait(false); + } + } + + internal class ServerStreamingServerCallHandler : IServerCallHandler + where TRequest : class + where TResponse : class + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType>(); + + readonly Method method; + readonly ServerStreamingServerMethod handler; + + public ServerStreamingServerCallHandler(Method method, ServerStreamingServerMethod handler) + { + this.method = method; + this.handler = handler; + } + + public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq) + { + var asyncCall = new AsyncCallServer( + method.ResponseMarshaller.ContextualSerializer, + method.RequestMarshaller.ContextualDeserializer, + newRpc.Server); + + asyncCall.Initialize(newRpc.Call, cq); + var finishedTask = asyncCall.ServerSideCallAsync(); + var requestStream = new ServerRequestStream(asyncCall); + var responseStream = new ServerResponseStream(asyncCall); + + Status status; + var context = HandlerUtils.NewContext(newRpc, responseStream, asyncCall.CancellationToken); + try + { + GrpcPreconditions.CheckArgument(await requestStream.MoveNext().ConfigureAwait(false)); + var request = requestStream.Current; + await handler(request, responseStream, context).ConfigureAwait(false); + status = context.Status; + } + catch (Exception e) + { + if (!(e is RpcException)) + { + Logger.Warning(e, "Exception occurred in the handler or an interceptor."); + } + status = HandlerUtils.GetStatusFromExceptionAndMergeTrailers(e, context.ResponseTrailers); + } + + try + { + await asyncCall.SendStatusFromServerAsync(status, context.ResponseTrailers, null).ConfigureAwait(false); + } + catch (Exception) + { + asyncCall.Cancel(); + throw; + } + await finishedTask.ConfigureAwait(false); + } + } + + internal class ClientStreamingServerCallHandler : IServerCallHandler + where TRequest : class + where TResponse : class + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType>(); + + readonly Method method; + readonly ClientStreamingServerMethod handler; + + public ClientStreamingServerCallHandler(Method method, ClientStreamingServerMethod handler) + { + this.method = method; + this.handler = handler; + } + + public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq) + { + var asyncCall = new AsyncCallServer( + method.ResponseMarshaller.ContextualSerializer, + method.RequestMarshaller.ContextualDeserializer, + newRpc.Server); + + asyncCall.Initialize(newRpc.Call, cq); + var finishedTask = asyncCall.ServerSideCallAsync(); + var requestStream = new ServerRequestStream(asyncCall); + var responseStream = new ServerResponseStream(asyncCall); + + Status status; + AsyncCallServer.ResponseWithFlags? responseWithFlags = null; + var context = HandlerUtils.NewContext(newRpc, responseStream, asyncCall.CancellationToken); + try + { + var response = await handler(requestStream, context).ConfigureAwait(false); + status = context.Status; + responseWithFlags = new AsyncCallServer.ResponseWithFlags(response, HandlerUtils.GetWriteFlags(context.WriteOptions)); + } + catch (Exception e) + { + if (!(e is RpcException)) + { + Logger.Warning(e, "Exception occurred in the handler or an interceptor."); + } + status = HandlerUtils.GetStatusFromExceptionAndMergeTrailers(e, context.ResponseTrailers); + } + + try + { + await asyncCall.SendStatusFromServerAsync(status, context.ResponseTrailers, responseWithFlags).ConfigureAwait(false); + } + catch (Exception) + { + asyncCall.Cancel(); + throw; + } + await finishedTask.ConfigureAwait(false); + } + } + + internal class DuplexStreamingServerCallHandler : IServerCallHandler + where TRequest : class + where TResponse : class + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType>(); + + readonly Method method; + readonly DuplexStreamingServerMethod handler; + + public DuplexStreamingServerCallHandler(Method method, DuplexStreamingServerMethod handler) + { + this.method = method; + this.handler = handler; + } + + public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq) + { + var asyncCall = new AsyncCallServer( + method.ResponseMarshaller.ContextualSerializer, + method.RequestMarshaller.ContextualDeserializer, + newRpc.Server); + + asyncCall.Initialize(newRpc.Call, cq); + var finishedTask = asyncCall.ServerSideCallAsync(); + var requestStream = new ServerRequestStream(asyncCall); + var responseStream = new ServerResponseStream(asyncCall); + + Status status; + var context = HandlerUtils.NewContext(newRpc, responseStream, asyncCall.CancellationToken); + try + { + await handler(requestStream, responseStream, context).ConfigureAwait(false); + status = context.Status; + } + catch (Exception e) + { + if (!(e is RpcException)) + { + Logger.Warning(e, "Exception occurred in the handler or an interceptor."); + } + status = HandlerUtils.GetStatusFromExceptionAndMergeTrailers(e, context.ResponseTrailers); + } + try + { + await asyncCall.SendStatusFromServerAsync(status, context.ResponseTrailers, null).ConfigureAwait(false); + } + catch (Exception) + { + asyncCall.Cancel(); + throw; + } + await finishedTask.ConfigureAwait(false); + } + } + + internal class UnimplementedMethodCallHandler : IServerCallHandler + { + public static readonly UnimplementedMethodCallHandler Instance = new UnimplementedMethodCallHandler(); + + DuplexStreamingServerCallHandler callHandlerImpl; + + public UnimplementedMethodCallHandler() + { + var marshaller = new Marshaller((payload) => payload, (payload) => payload); + var method = new Method(MethodType.DuplexStreaming, "", "", marshaller, marshaller); + this.callHandlerImpl = new DuplexStreamingServerCallHandler(method, new DuplexStreamingServerMethod(UnimplementedMethod)); + } + + /// + /// Handler used for unimplemented method. + /// + private Task UnimplementedMethod(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext ctx) + { + ctx.Status = new Status(StatusCode.Unimplemented, ""); + return TaskUtils.CompletedTask; + } + + public Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq) + { + return callHandlerImpl.HandleCall(newRpc, cq); + } + } + + internal static class HandlerUtils + { + public static Status GetStatusFromExceptionAndMergeTrailers(Exception e, Metadata callContextResponseTrailers) + { + var rpcException = e as RpcException; + if (rpcException != null) + { + // There are two sources of metadata entries on the server-side: + // 1. serverCallContext.ResponseTrailers + // 2. trailers in RpcException thrown by user code in server side handler. + // As metadata allows duplicate keys, the logical thing to do is + // to just merge trailers from RpcException into serverCallContext.ResponseTrailers. + foreach (var entry in rpcException.Trailers) + { + callContextResponseTrailers.Add(entry); + } + // use the status thrown by handler. + return rpcException.Status; + } + + return new Status(StatusCode.Unknown, "Exception was thrown by handler."); + } + + public static WriteFlags GetWriteFlags(WriteOptions writeOptions) + { + return writeOptions != null ? writeOptions.Flags : default(WriteFlags); + } + + public static ServerCallContext NewContext(ServerRpcNew newRpc, IServerResponseStream serverResponseStream, CancellationToken cancellationToken) + { + DateTime realtimeDeadline = newRpc.Deadline.ToClockType(ClockType.Realtime).ToDateTime(); + return new DefaultServerCallContext(newRpc.Call, newRpc.Method, newRpc.Host, realtimeDeadline, newRpc.RequestMetadata, cancellationToken, serverResponseStream); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ServerCalls.cs b/src/csharp/Grpc.Core/Internal/ServerCalls.cs new file mode 100644 index 00000000..0f04233d --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ServerCalls.cs @@ -0,0 +1,56 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; + +namespace Grpc.Core.Internal +{ + internal static class ServerCalls + { + public static IServerCallHandler UnaryCall(Method method, UnaryServerMethod handler) + where TRequest : class + where TResponse : class + { + return new UnaryServerCallHandler(method, handler); + } + + public static IServerCallHandler ClientStreamingCall(Method method, ClientStreamingServerMethod handler) + where TRequest : class + where TResponse : class + { + return new ClientStreamingServerCallHandler(method, handler); + } + + public static IServerCallHandler ServerStreamingCall(Method method, ServerStreamingServerMethod handler) + where TRequest : class + where TResponse : class + { + return new ServerStreamingServerCallHandler(method, handler); + } + + public static IServerCallHandler DuplexStreamingCall(Method method, DuplexStreamingServerMethod handler) + where TRequest : class + where TResponse : class + { + return new DuplexStreamingServerCallHandler(method, handler); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs new file mode 100644 index 00000000..5f8c95c4 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs @@ -0,0 +1,50 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// grpc_server_credentials from grpc/grpc_security.h + /// + internal class ServerCredentialsSafeHandle : SafeHandleZeroIsInvalid + { + static readonly NativeMethods Native = NativeMethods.Get(); + + private ServerCredentialsSafeHandle() + { + } + + public static ServerCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, SslClientCertificateRequestType clientCertificateRequest) + { + GrpcPreconditions.CheckArgument(keyCertPairCertChainArray.Length == keyCertPairPrivateKeyArray.Length); + return Native.grpcsharp_ssl_server_credentials_create(pemRootCerts, + keyCertPairCertChainArray, keyCertPairPrivateKeyArray, + new UIntPtr((ulong)keyCertPairCertChainArray.Length), + clientCertificateRequest); + } + + protected override bool ReleaseHandle() + { + Native.grpcsharp_server_credentials_release(handle); + return true; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs b/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs new file mode 100644 index 00000000..f3655139 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ServerRequestStream.cs @@ -0,0 +1,65 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Grpc.Core.Internal +{ + internal class ServerRequestStream : IAsyncStreamReader + where TRequest : class + where TResponse : class + { + readonly AsyncCallServer call; + TRequest current; + + public ServerRequestStream(AsyncCallServer call) + { + this.call = call; + } + + public TRequest Current + { + get + { + if (current == null) + { + throw new InvalidOperationException("No current element is available."); + } + return current; + } + } + + public async Task MoveNext(CancellationToken token) + { + using (call.RegisterCancellationCallbackForToken(token)) + { + var result = await call.ReadMessageAsync().ConfigureAwait(false); + this.current = result; + return result != null; + } + } + + public void Dispose() + { + // TODO(jtattermusch): implement the semantics of stream disposal. + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs b/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs new file mode 100644 index 00000000..079849e4 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ServerResponseStream.cs @@ -0,0 +1,67 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion + +using System; +using System.Threading.Tasks; +using Grpc.Core.Internal; + +namespace Grpc.Core.Internal +{ + /// + /// Writes responses asynchronously to an underlying AsyncCallServer object. + /// + internal class ServerResponseStream : IServerStreamWriter, IServerResponseStream + where TRequest : class + where TResponse : class + { + readonly AsyncCallServer call; + WriteOptions writeOptions; + + public ServerResponseStream(AsyncCallServer call) + { + this.call = call; + } + + public Task WriteAsync(TResponse message) + { + return call.SendMessageAsync(message, GetWriteFlags()); + } + + public Task WriteResponseHeadersAsync(Metadata responseHeaders) + { + return call.SendInitialMetadataAsync(responseHeaders); + } + + public WriteOptions WriteOptions + { + get + { + return writeOptions; + } + + set + { + writeOptions = value; + } + } + + private WriteFlags GetWriteFlags() + { + var options = writeOptions; + return options != null ? options.Flags : default(WriteFlags); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ServerRpcNew.cs b/src/csharp/Grpc.Core/Internal/ServerRpcNew.cs new file mode 100644 index 00000000..d79d0d12 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ServerRpcNew.cs @@ -0,0 +1,94 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.Core; + +namespace Grpc.Core.Internal +{ + /// + /// Details of a newly received RPC. + /// + internal struct ServerRpcNew + { + readonly Server server; + readonly CallSafeHandle call; + readonly string method; + readonly string host; + readonly Timespec deadline; + readonly Metadata requestMetadata; + + public ServerRpcNew(Server server, CallSafeHandle call, string method, string host, Timespec deadline, Metadata requestMetadata) + { + this.server = server; + this.call = call; + this.method = method; + this.host = host; + this.deadline = deadline; + this.requestMetadata = requestMetadata; + } + + public Server Server + { + get + { + return this.server; + } + } + + public CallSafeHandle Call + { + get + { + return this.call; + } + } + + public string Method + { + get + { + return this.method; + } + } + + public string Host + { + get + { + return this.host; + } + } + + public Timespec Deadline + { + get + { + return this.deadline; + } + } + + public Metadata RequestMetadata + { + get + { + return this.requestMetadata; + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs new file mode 100644 index 00000000..56dda9cf --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs @@ -0,0 +1,96 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +namespace Grpc.Core.Internal +{ + /// + /// grpc_server from grpc/grpc.h + /// + internal sealed class ServerSafeHandle : SafeHandleZeroIsInvalid + { + static readonly NativeMethods Native = NativeMethods.Get(); + + private ServerSafeHandle() + { + } + + public static ServerSafeHandle NewServer(ChannelArgsSafeHandle args) + { + // Increment reference count for the native gRPC environment to make sure we don't do grpc_shutdown() before destroying the server handle. + // Doing so would make object finalizer crash if we end up abandoning the handle. + GrpcEnvironment.GrpcNativeInit(); + return Native.grpcsharp_server_create(args); + } + + public void RegisterCompletionQueue(CompletionQueueSafeHandle cq) + { + using (cq.NewScope()) + { + Native.grpcsharp_server_register_completion_queue(this, cq); + } + } + + public int AddInsecurePort(string addr) + { + return Native.grpcsharp_server_add_insecure_http2_port(this, addr); + } + + public int AddSecurePort(string addr, ServerCredentialsSafeHandle credentials) + { + return Native.grpcsharp_server_add_secure_http2_port(this, addr, credentials); + } + + public void Start() + { + Native.grpcsharp_server_start(this); + } + + public void ShutdownAndNotify(BatchCompletionDelegate callback, CompletionQueueSafeHandle completionQueue) + { + using (completionQueue.NewScope()) + { + // TODO(jtattermusch): delegate allocation by caller can be avoided by utilizing the "state" object, + // but server shutdown isn't worth optimizing right now. + var ctx = completionQueue.CompletionRegistry.RegisterBatchCompletion(callback, null); + Native.grpcsharp_server_shutdown_and_notify_callback(this, completionQueue, ctx); + } + } + + public void RequestCall(RequestCallCompletionDelegate callback, CompletionQueueSafeHandle completionQueue) + { + using (completionQueue.NewScope()) + { + var ctx = completionQueue.CompletionRegistry.RegisterRequestCallCompletion(callback); + Native.grpcsharp_server_request_call(this, completionQueue, ctx).CheckOk(); + } + } + + protected override bool ReleaseHandle() + { + Native.grpcsharp_server_destroy(handle); + GrpcEnvironment.GrpcNativeShutdown(); + return true; + } + + // Only to be called after ShutdownAndNotify. + public void CancelAllCalls() + { + Native.grpcsharp_server_cancel_all_calls(this); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs b/src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs new file mode 100644 index 00000000..cc4654c9 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/ServerServiceDefinitionExtensions.cs @@ -0,0 +1,78 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Grpc.Core.Internal; + +namespace Grpc.Core.Internal +{ + internal static class ServerServiceDefinitionExtensions + { + /// + /// Maps methods from ServerServiceDefinition to server call handlers. + /// + internal static ReadOnlyDictionary GetCallHandlers(this ServerServiceDefinition serviceDefinition) + { + var binder = new DefaultServiceBinder(); + serviceDefinition.BindService(binder); + return binder.GetCallHandlers(); + } + + /// + /// Helper for converting ServerServiceDefinition to server call handlers. + /// + private class DefaultServiceBinder : ServiceBinderBase + { + readonly Dictionary callHandlers = new Dictionary(); + + internal ReadOnlyDictionary GetCallHandlers() + { + return new ReadOnlyDictionary(this.callHandlers); + } + + public override void AddMethod( + Method method, + UnaryServerMethod handler) + { + callHandlers.Add(method.FullName, ServerCalls.UnaryCall(method, handler)); + } + + public override void AddMethod( + Method method, + ClientStreamingServerMethod handler) + { + callHandlers.Add(method.FullName, ServerCalls.ClientStreamingCall(method, handler)); + } + + public override void AddMethod( + Method method, + ServerStreamingServerMethod handler) + { + callHandlers.Add(method.FullName, ServerCalls.ServerStreamingCall(method, handler)); + } + + public override void AddMethod( + Method method, + DuplexStreamingServerMethod handler) + { + callHandlers.Add(method.FullName, ServerCalls.DuplexStreamingCall(method, handler)); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/Slice.cs b/src/csharp/Grpc.Core/Internal/Slice.cs new file mode 100644 index 00000000..b6e07014 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/Slice.cs @@ -0,0 +1,59 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Runtime.InteropServices; +using System.Threading; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Slice of native memory. + /// Rough equivalent of grpc_slice (but doesn't support inlined slices, just a pointer to data and length) + /// + internal struct Slice + { + private readonly IntPtr dataPtr; + private readonly int length; + + public Slice(IntPtr dataPtr, int length) + { + this.dataPtr = dataPtr; + this.length = length; + } + + public int Length => length; + + public Span ToSpanUnsafe() + { + unsafe + { + return new Span((byte*) dataPtr, length); + } + } + + /// + /// Returns a that represents the current . + /// + public override string ToString() + { + return string.Format("[Slice: dataPtr={0}, length={1}]", dataPtr, length); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/SliceBufferSafeHandle.cs b/src/csharp/Grpc.Core/Internal/SliceBufferSafeHandle.cs new file mode 100644 index 00000000..9cbdce1c --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/SliceBufferSafeHandle.cs @@ -0,0 +1,166 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Buffers; +using System.Runtime.InteropServices; +using Grpc.Core; +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Represents grpc_slice_buffer with some extra utility functions to allow + /// writing data to it using the IBufferWriter interface. + /// + internal class SliceBufferSafeHandle : SafeHandleZeroIsInvalid, IBufferWriter + { + const int DefaultTailSpaceSize = 4096; // default buffer to allocate if no size hint is provided + static readonly NativeMethods Native = NativeMethods.Get(); + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + + public static readonly SliceBufferSafeHandle NullInstance = new SliceBufferSafeHandle(); + + private IntPtr tailSpacePtr; + private int tailSpaceLen; + + private SliceMemoryManager memoryManagerLazy; + + private SliceBufferSafeHandle() + { + } + + public static SliceBufferSafeHandle Create() + { + return Native.grpcsharp_slice_buffer_create(); + } + + public IntPtr Handle + { + get + { + return handle; + } + } + + public void Advance(int count) + { + GrpcPreconditions.CheckArgument(count >= 0); + GrpcPreconditions.CheckArgument(tailSpacePtr != IntPtr.Zero || count == 0); + GrpcPreconditions.CheckArgument(tailSpaceLen >= count); + tailSpaceLen = tailSpaceLen - count; + tailSpacePtr += count; + memoryManagerLazy?.Reset(); + } + + // provides access to the "tail space" of this buffer. + // Use GetSpan when possible for better efficiency. + public Memory GetMemory(int sizeHint = 0) + { + EnsureBufferSpace(sizeHint); + if (memoryManagerLazy == null) + { + memoryManagerLazy = new SliceMemoryManager(); + } + memoryManagerLazy.Reset(new Slice(tailSpacePtr, tailSpaceLen)); + return memoryManagerLazy.Memory; + } + + // provides access to the "tail space" of this buffer. + public unsafe Span GetSpan(int sizeHint = 0) + { + EnsureBufferSpace(sizeHint); + return new Span(tailSpacePtr.ToPointer(), tailSpaceLen); + } + + public void Complete() + { + AdjustTailSpace(0); + } + + // resets the data contained by this slice buffer + public void Reset() + { + // deletes all the data in the slice buffer + tailSpacePtr = IntPtr.Zero; + tailSpaceLen = 0; + memoryManagerLazy?.Reset(); + Native.grpcsharp_slice_buffer_reset_and_unref(this); + } + + // copies the content of the slice buffer to a newly allocated byte array + // Note that this method has a relatively high overhead and should maily be used for testing. + public byte[] ToByteArray() + { + ulong sliceCount = Native.grpcsharp_slice_buffer_slice_count(this).ToUInt64(); + + Slice[] slices = new Slice[sliceCount]; + int totalLen = 0; + for (int i = 0; i < (int) sliceCount; i++) + { + Native.grpcsharp_slice_buffer_slice_peek(this, new UIntPtr((ulong) i), out UIntPtr sliceLen, out IntPtr dataPtr); + slices[i] = new Slice(dataPtr, (int) sliceLen.ToUInt64()); + totalLen += (int) sliceLen.ToUInt64(); + + } + var result = new byte[totalLen]; + int offset = 0; + for (int i = 0; i < (int) sliceCount; i++) + { + slices[i].ToSpanUnsafe().CopyTo(result.AsSpan(offset, slices[i].Length)); + offset += slices[i].Length; + } + GrpcPreconditions.CheckState(totalLen == offset); + return result; + } + + private void EnsureBufferSpace(int sizeHint) + { + GrpcPreconditions.CheckArgument(sizeHint >= 0); + if (sizeHint == 0) + { + // if no hint is provided, keep the available space within some "reasonable" boundaries. + // This is quite a naive approach which could use some fine-tuning, but currently in most case we know + // the required buffer size in advance anyway, so this approach seems good enough for now. + if (tailSpaceLen < DefaultTailSpaceSize / 2) + { + AdjustTailSpace(DefaultTailSpaceSize); + } + } + else if (tailSpaceLen < sizeHint) + { + // if hint is provided, always make sure we provide at least that much space + AdjustTailSpace(sizeHint); + } + } + + // make sure there's exactly requestedSize bytes of continguous buffer space at the end of this slice buffer + private void AdjustTailSpace(int requestedSize) + { + GrpcPreconditions.CheckArgument(requestedSize >= 0); + tailSpacePtr = Native.grpcsharp_slice_buffer_adjust_tail_space(this, new UIntPtr((ulong) tailSpaceLen), new UIntPtr((ulong) requestedSize)); + tailSpaceLen = requestedSize; + } + protected override bool ReleaseHandle() + { + Native.grpcsharp_slice_buffer_destroy(handle); + return true; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/SliceMemoryManager.cs b/src/csharp/Grpc.Core/Internal/SliceMemoryManager.cs new file mode 100644 index 00000000..dad2d96b --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/SliceMemoryManager.cs @@ -0,0 +1,65 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using Grpc.Core.Utils; +using System; +using System.Threading; + +using System.Buffers; + +namespace Grpc.Core.Internal +{ + // Allow creating instances of Memory from Slice. + // Represents a chunk of native memory, but doesn't manage its lifetime. + // Instances of this class are reuseable - they can be reset to point to a different memory chunk. + // That is important to make the instances cacheable (rather then creating new instances + // the old ones will be reused to reduce GC pressure). + internal class SliceMemoryManager : MemoryManager + { + private Slice slice; + + public void Reset(Slice slice) + { + this.slice = slice; + } + + public void Reset() + { + Reset(new Slice(IntPtr.Zero, 0)); + } + + public override Span GetSpan() + { + return slice.ToSpanUnsafe(); + } + + public override MemoryHandle Pin(int elementIndex = 0) + { + throw new NotSupportedException(); + } + + public override void Unpin() + { + } + + protected override void Dispose(bool disposing) + { + // NOP + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/Timespec.cs b/src/csharp/Grpc.Core/Internal/Timespec.cs new file mode 100644 index 00000000..0edaffb9 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/Timespec.cs @@ -0,0 +1,287 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Threading; + +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// gpr_timespec from grpc/support/time.h + /// + [StructLayout(LayoutKind.Sequential)] + internal struct Timespec : IEquatable + { + /// + /// Indicates whether this instance and a specified object are equal. + /// + public override bool Equals(object obj) + { + return obj is Timespec && Equals((Timespec)obj); + } + + /// + /// Returns the hash code for this instance. + /// + public override int GetHashCode() + { + unchecked + { + const int Prime = 373587911; + int i = (int)clock_type; + i = (i * Prime) ^ tv_nsec; + i = (i * Prime) ^ tv_nsec.GetHashCode(); + return i; + } + } + + /// + /// Returns the full type name of this instance. + /// + public override string ToString() + { + return typeof(Timespec).FullName; + } + + /// + /// Indicates whether this instance and a specified object are equal. + /// + public bool Equals(Timespec other) + { + return this.clock_type == other.clock_type + && this.tv_nsec == other.tv_nsec + && this.tv_sec == other.tv_sec; + } + + const long NanosPerSecond = 1000 * 1000 * 1000; + const long NanosPerTick = 100; + const long TicksPerSecond = NanosPerSecond / NanosPerTick; + + static readonly NativeMethods Native = NativeMethods.Get(); + static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + + public Timespec(long tv_sec, int tv_nsec) : this(tv_sec, tv_nsec, ClockType.Realtime) + { + } + + public Timespec(long tv_sec, int tv_nsec, ClockType clock_type) + { + this.tv_sec = tv_sec; + this.tv_nsec = tv_nsec; + this.clock_type = clock_type; + } + + private long tv_sec; + private int tv_nsec; + private ClockType clock_type; + + /// + /// Timespec a long time in the future. + /// + public static Timespec InfFuture + { + get + { + return new Timespec(long.MaxValue, 0, ClockType.Realtime); + } + } + + /// + /// Timespec a long time in the past. + /// + public static Timespec InfPast + { + get + { + return new Timespec(long.MinValue, 0, ClockType.Realtime); + } + } + + /// + /// Return Timespec representing the current time. + /// + public static Timespec Now + { + get + { + return Native.gprsharp_now(ClockType.Realtime); + } + } + + /// + /// Seconds since unix epoch. + /// + public long TimevalSeconds + { + get + { + return tv_sec; + } + } + + /// + /// The nanoseconds part of timeval. + /// + public int TimevalNanos + { + get + { + return tv_nsec; + } + } + + /// + /// Converts the timespec to desired clock type. + /// + public Timespec ToClockType(ClockType targetClock) + { + return Native.gprsharp_convert_clock_type(this, targetClock); + } + + /// + /// Converts Timespec to DateTime. + /// Timespec needs to be of type GPRClockType.Realtime and needs to represent a legal value. + /// DateTime has lower resolution (100ns), so rounding can occurs. + /// Value are always rounded up to the nearest DateTime value in the future. + /// + /// For Timespec.InfFuture or if timespec is after the largest representable DateTime, DateTime.MaxValue is returned. + /// For Timespec.InfPast or if timespec is before the lowest representable DateTime, DateTime.MinValue is returned. + /// + /// Unless DateTime.MaxValue or DateTime.MinValue is returned, the resulting DateTime is always in UTC + /// (DateTimeKind.Utc) + /// + public DateTime ToDateTime() + { + GrpcPreconditions.CheckState(tv_nsec >= 0 && tv_nsec < NanosPerSecond); + GrpcPreconditions.CheckState(clock_type == ClockType.Realtime); + + // fast path for InfFuture + if (this.Equals(InfFuture)) + { + return DateTime.MaxValue; + } + + // fast path for InfPast + if (this.Equals(InfPast)) + { + return DateTime.MinValue; + } + + try + { + // convert nanos to ticks, round up to the nearest tick + long ticksFromNanos = tv_nsec / NanosPerTick + ((tv_nsec % NanosPerTick != 0) ? 1 : 0); + long ticksTotal = checked(tv_sec * TicksPerSecond + ticksFromNanos); + return UnixEpoch.AddTicks(ticksTotal); + } + catch (OverflowException) + { + // ticks out of long range + return tv_sec > 0 ? DateTime.MaxValue : DateTime.MinValue; + } + catch (ArgumentOutOfRangeException) + { + // resulting date time would be larger than MaxValue + return tv_sec > 0 ? DateTime.MaxValue : DateTime.MinValue; + } + } + + /// + /// Creates DateTime to Timespec. + /// DateTime has to be in UTC (DateTimeKind.Utc) unless it's DateTime.MaxValue or DateTime.MinValue. + /// For DateTime.MaxValue of date time after the largest representable Timespec, Timespec.InfFuture is returned. + /// For DateTime.MinValue of date time before the lowest representable Timespec, Timespec.InfPast is returned. + /// + /// The date time. + /// Date time. + public static Timespec FromDateTime(DateTime dateTime) + { + if (dateTime == DateTime.MaxValue) + { + return Timespec.InfFuture; + } + + if (dateTime == DateTime.MinValue) + { + return Timespec.InfPast; + } + + GrpcPreconditions.CheckArgument(dateTime.Kind == DateTimeKind.Utc, "dateTime needs of kind DateTimeKind.Utc or be equal to DateTime.MaxValue or DateTime.MinValue."); + + try + { + TimeSpan timeSpan = dateTime - UnixEpoch; + long ticks = timeSpan.Ticks; + + long seconds = ticks / TicksPerSecond; + int nanos = (int)((ticks % TicksPerSecond) * NanosPerTick); + if (nanos < 0) + { + // correct the result based on C# modulo semantics for negative dividend + seconds--; + nanos += (int)NanosPerSecond; + } + return new Timespec(seconds, nanos); + } + catch (ArgumentOutOfRangeException) + { + return dateTime > UnixEpoch ? Timespec.InfFuture : Timespec.InfPast; + } + } + + /// + /// Gets current timestamp using GPRClockType.Precise. + /// Only available internally because core needs to be compiled with + /// GRPC_TIMERS_RDTSC support for this to use RDTSC. + /// + internal static Timespec PreciseNow + { + get + { + return Native.gprsharp_now(ClockType.Precise); + } + } + + // for tests only + internal static int NativeSize + { + get + { + return Native.gprsharp_sizeof_timespec(); + } + } + + // for tests only + internal static Timespec NativeInfFuture + { + get + { + return Native.gprsharp_inf_future(ClockType.Realtime); + } + } + + // for tests only + public static Timespec NativeInfPast + { + get + { + return Native.gprsharp_inf_past(ClockType.Realtime); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/UnimplementedCallInvoker.cs b/src/csharp/Grpc.Core/Internal/UnimplementedCallInvoker.cs new file mode 100644 index 00000000..c7be74ec --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/UnimplementedCallInvoker.cs @@ -0,0 +1,60 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Call invoker that throws NotImplementedException for all requests. + /// + internal class UnimplementedCallInvoker : CallInvoker + { + public UnimplementedCallInvoker() + { + } + + public override TResponse BlockingUnaryCall(Method method, string host, CallOptions options, TRequest request) + { + throw new NotImplementedException(); + } + + public override AsyncUnaryCall AsyncUnaryCall(Method method, string host, CallOptions options, TRequest request) + { + throw new NotImplementedException(); + } + + public override AsyncServerStreamingCall AsyncServerStreamingCall(Method method, string host, CallOptions options, TRequest request) + { + throw new NotImplementedException(); + } + + public override AsyncClientStreamingCall AsyncClientStreamingCall(Method method, string host, CallOptions options) + { + throw new NotImplementedException(); + } + + public override AsyncDuplexStreamingCall AsyncDuplexStreamingCall(Method method, string host, CallOptions options) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs new file mode 100644 index 00000000..c275559d --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs @@ -0,0 +1,265 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; + +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Represents a dynamically loaded unmanaged library in a (partially) platform independent manner. + /// First, the native library is loaded using dlopen (on Unix systems) or using LoadLibrary (on Windows). + /// dlsym or GetProcAddress are then used to obtain symbol addresses. Marshal.GetDelegateForFunctionPointer + /// transforms the addresses into delegates to native methods. + /// See http://stackoverflow.com/questions/13461989/p-invoke-to-dynamically-loaded-library-on-mono. + /// + internal class UnmanagedLibrary + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + + // flags for dlopen + const int RTLD_LAZY = 1; + const int RTLD_GLOBAL = 8; + + readonly string libraryPath; + readonly IntPtr handle; + + public UnmanagedLibrary(string[] libraryPathAlternatives) + { + this.libraryPath = FirstValidLibraryPath(libraryPathAlternatives); + + Logger.Debug("Attempting to load native library \"{0}\"", this.libraryPath); + + this.handle = PlatformSpecificLoadLibrary(this.libraryPath, out string loadLibraryErrorDetail); + + if (this.handle == IntPtr.Zero) + { + throw new IOException(string.Format("Error loading native library \"{0}\". {1}", + this.libraryPath, loadLibraryErrorDetail)); + } + } + + /// + /// Loads symbol in a platform specific way. + /// + /// + /// + private IntPtr LoadSymbol(string symbolName) + { + if (PlatformApis.IsWindows) + { + // See http://stackoverflow.com/questions/10473310 for background on this. + if (PlatformApis.Is64Bit) + { + return Windows.GetProcAddress(this.handle, symbolName); + } + else + { + // Yes, we could potentially predict the size... but it's a lot simpler to just try + // all the candidates. Most functions have a suffix of @0, @4 or @8 so we won't be trying + // many options - and if it takes a little bit longer to fail if we've really got the wrong + // library, that's not a big problem. This is only called once per function in the native library. + symbolName = "_" + symbolName + "@"; + for (int stackSize = 0; stackSize < 128; stackSize += 4) + { + IntPtr candidate = Windows.GetProcAddress(this.handle, symbolName + stackSize); + if (candidate != IntPtr.Zero) + { + return candidate; + } + } + // Fail. + return IntPtr.Zero; + } + } + if (PlatformApis.IsLinux) + { + if (PlatformApis.IsMono) + { + return Mono.dlsym(this.handle, symbolName); + } + if (PlatformApis.IsNetCore) + { + return CoreCLR.dlsym(this.handle, symbolName); + } + return Linux.dlsym(this.handle, symbolName); + } + if (PlatformApis.IsMacOSX) + { + return MacOSX.dlsym(this.handle, symbolName); + } + throw new InvalidOperationException("Unsupported platform."); + } + + public T GetNativeMethodDelegate(string methodName) + where T : class + { + var ptr = LoadSymbol(methodName); + if (ptr == IntPtr.Zero) + { + throw new MissingMethodException(string.Format("The native method \"{0}\" does not exist", methodName)); + } +#if NETSTANDARD + return Marshal.GetDelegateForFunctionPointer(ptr); // non-generic version is obsolete +#else + return Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T; // generic version not available in .NET45 +#endif + } + + /// + /// Loads library in a platform specific way. + /// + private static IntPtr PlatformSpecificLoadLibrary(string libraryPath, out string errorMsg) + { + if (PlatformApis.IsWindows) + { + errorMsg = null; + var handle = Windows.LoadLibrary(libraryPath); + if (handle == IntPtr.Zero) + { + int win32Error = Marshal.GetLastWin32Error(); + errorMsg = $"LoadLibrary failed with error {win32Error}"; + // add extra info for the most common error ERROR_MOD_NOT_FOUND + if (win32Error == 126) + { + errorMsg += ": The specified module could not be found."; + } + } + return handle; + } + if (PlatformApis.IsLinux) + { + if (PlatformApis.IsMono) + { + return LoadLibraryPosix(Mono.dlopen, Mono.dlerror, libraryPath, out errorMsg); + } + if (PlatformApis.IsNetCore) + { + return LoadLibraryPosix(CoreCLR.dlopen, CoreCLR.dlerror, libraryPath, out errorMsg); + } + return LoadLibraryPosix(Linux.dlopen, Linux.dlerror, libraryPath, out errorMsg); + } + if (PlatformApis.IsMacOSX) + { + return LoadLibraryPosix(MacOSX.dlopen, MacOSX.dlerror, libraryPath, out errorMsg); + } + throw new InvalidOperationException("Unsupported platform."); + } + + private static IntPtr LoadLibraryPosix(Func dlopenFunc, Func dlerrorFunc, string libraryPath, out string errorMsg) + { + errorMsg = null; + IntPtr ret = dlopenFunc(libraryPath, RTLD_GLOBAL + RTLD_LAZY); + if (ret == IntPtr.Zero) + { + errorMsg = Marshal.PtrToStringAnsi(dlerrorFunc()); + } + return ret; + } + + private static string FirstValidLibraryPath(string[] libraryPathAlternatives) + { + GrpcPreconditions.CheckArgument(libraryPathAlternatives.Length > 0, "libraryPathAlternatives cannot be empty."); + foreach (var path in libraryPathAlternatives) + { + if (File.Exists(path)) + { + return path; + } + } + throw new FileNotFoundException( + String.Format("Error loading native library. Not found in any of the possible locations: {0}", + string.Join(",", libraryPathAlternatives))); + } + + private static class Windows + { + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern IntPtr LoadLibrary(string filename); + + [DllImport("kernel32.dll")] + internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName); + } + + private static class Linux + { + [DllImport("libdl.so")] + internal static extern IntPtr dlopen(string filename, int flags); + + [DllImport("libdl.so")] + internal static extern IntPtr dlerror(); + + [DllImport("libdl.so")] + internal static extern IntPtr dlsym(IntPtr handle, string symbol); + } + + private static class MacOSX + { + [DllImport("libSystem.dylib")] + internal static extern IntPtr dlopen(string filename, int flags); + + [DllImport("libSystem.dylib")] + internal static extern IntPtr dlerror(); + + [DllImport("libSystem.dylib")] + internal static extern IntPtr dlsym(IntPtr handle, string symbol); + } + + /// + /// On Linux systems, using dlopen and dlsym results in + /// DllNotFoundException("libdl.so not found") if libc6-dev + /// is not installed. As a workaround, we load symbols for + /// dlopen and dlsym from the current process as on Linux + /// Mono sure is linked against these symbols. + /// + private static class Mono + { + [DllImport("__Internal")] + internal static extern IntPtr dlopen(string filename, int flags); + + [DllImport("__Internal")] + internal static extern IntPtr dlerror(); + + [DllImport("__Internal")] + internal static extern IntPtr dlsym(IntPtr handle, string symbol); + } + + /// + /// Similarly as for Mono on Linux, we load symbols for + /// dlopen and dlsym from the "libcoreclr.so", + /// to avoid the dependency on libc-dev Linux. + /// + private static class CoreCLR + { + [DllImport("libcoreclr.so")] + internal static extern IntPtr dlopen(string filename, int flags); + + [DllImport("libcoreclr.so")] + internal static extern IntPtr dlerror(); + + [DllImport("libcoreclr.so")] + internal static extern IntPtr dlsym(IntPtr handle, string symbol); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/UserAgentStringProvider.cs b/src/csharp/Grpc.Core/Internal/UserAgentStringProvider.cs new file mode 100644 index 00000000..01f15850 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/UserAgentStringProvider.cs @@ -0,0 +1,108 @@ +#region Copyright notice and license + +// Copyright 2021 The gRPC Authors +// +// 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. + +#endregion + +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace Grpc.Core.Internal +{ + /// + /// Helps constructing the grpc-csharp component of the user agent string. + /// + internal class UserAgentStringProvider + { + static readonly UserAgentStringProvider defaultInstance; + readonly string userAgentString; + + static UserAgentStringProvider() + { + defaultInstance = new UserAgentStringProvider(VersionInfo.CurrentVersion, PlatformApis.FrameworkDescription, PlatformApis.ClrVersion, PlatformApis.GetGrpcCoreTargetFrameworkMoniker(), PlatformApis.ProcessArchitecture); + } + + public static UserAgentStringProvider DefaultInstance => defaultInstance; + + public string GrpcCsharpUserAgentString => userAgentString; + + public UserAgentStringProvider(string grpcCsharpVersion, string frameworkDescription, string clrVersion, string tfm, CommonPlatformDetection.CpuArchitecture arch) + { + var detailComponents = new List(); + + string sanitizedFrameworkDescription = SanitizeFrameworkDescription(frameworkDescription); + if (sanitizedFrameworkDescription != null) + { + detailComponents.Add(sanitizedFrameworkDescription); + } + + if (clrVersion != null) + { + detailComponents.Add($"CLR {clrVersion}"); + } + + if (tfm != null) + { + detailComponents.Add(tfm); + } + + string architectureString = TryGetArchitectureString(arch); + if (architectureString != null) + { + detailComponents.Add(architectureString); + } + + // TODO(jtattermusch): consider adding details about running under unity / xamarin etc. + var details = string.Join("; ", detailComponents); + userAgentString = $"grpc-csharp/{grpcCsharpVersion} ({details})"; + } + + static string TryGetArchitectureString(CommonPlatformDetection.CpuArchitecture arch) + { + if (arch == CommonPlatformDetection.CpuArchitecture.Unknown) + { + return null; + } + return arch.ToString().ToLowerInvariant(); + } + + static string SanitizeFrameworkDescription(string frameworkDescription) + { + if (frameworkDescription == null) + { + return null; + } + + // Some platforms return more details in the FrameworkDescription string than we want. + // e.g. on mono, we will get something like "Mono 6.12.0.93 (2020-02/620cf538206 Tue Aug 25 14:04:52 EDT 2020)" + // For user agent string, we only want basic info on framework name and its version. + var parts = new List(frameworkDescription.Split(' ')); + + int i = 0; + for (; i < parts.Count; i++) + { + var part = parts[i]; + if (!Regex.IsMatch(part, @"^[-.,+@A-Za-z0-9]*$")) + { + // stop once we find first part that's not framework name or version + break; + } + } + + var result = string.Join(" ", parts.GetRange(0, i)); + return !string.IsNullOrEmpty(result) ? result : null; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/WellKnownStrings.cs b/src/csharp/Grpc.Core/Internal/WellKnownStrings.cs new file mode 100644 index 00000000..fa33e9a1 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/WellKnownStrings.cs @@ -0,0 +1,92 @@ +#region Copyright notice and license +// Copyright 2019 The gRPC Authors +// +// 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. +#endregion + +using System; +using System.Runtime.CompilerServices; + +namespace Grpc.Core.Internal +{ + /// + /// Utility type for identifying "well-known" strings (i.e. headers/keys etc that + /// we expect to see frequently, and don't want to allocate lots of copies of) + /// + internal static class WellKnownStrings + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static unsafe ulong Coerce64(byte* value) + { + return *(ulong*)value; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static unsafe uint Coerce32(byte* value) + { + return *(uint*)value; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static unsafe ushort Coerce16(byte* value) + { + return *(ushort*)value; + } + + + /// + /// Test whether the provided byte sequence is recognized as a well-known string; if + /// so, return a shared instance of that string; otherwise, return null + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe string TryIdentify(IntPtr source, int length) + { + return TryIdentify((byte*)source.ToPointer(), length); + } + + /// + /// Test whether the provided byte sequence is recognized as a well-known string; if + /// so, return a shared instance of that string; otherwise, return null + /// + public static unsafe string TryIdentify(byte* source, int length) + { + // note: the logic here is hard-coded to constants for optimal processing; + // refer to an ASCII/hex converter (and remember to reverse **segments** for little-endian) + if (BitConverter.IsLittleEndian) // this is a JIT intrinsic; branch removal happens on modern runtimes + { + switch (length) + { + case 0: return ""; + case 10: + switch(Coerce64(source)) + { + case 0x6567612d72657375: return Coerce16(source + 8) == 0x746e ? "user-agent" : null; + } + break; + } + } + else + { + switch (length) + { + case 0: return ""; + case 10: + switch (Coerce64(source)) + { + case 0x757365722d616765: return Coerce16(source + 8) == 0x6e74 ? "user-agent" : null; + } + break; + } + } + return null; + } + } +} diff --git a/src/csharp/Grpc.Core/Logging/ConsoleLogger.cs b/src/csharp/Grpc.Core/Logging/ConsoleLogger.cs new file mode 100644 index 00000000..fcb22c88 --- /dev/null +++ b/src/csharp/Grpc.Core/Logging/ConsoleLogger.cs @@ -0,0 +1,50 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Globalization; + +namespace Grpc.Core.Logging +{ + /// Logger that logs to System.Console. + public class ConsoleLogger : TextWriterLogger + { + /// Creates a console logger not associated to any specific type. + public ConsoleLogger() : this(null) + { + } + + /// Creates a console logger that logs messsage specific for given type. + private ConsoleLogger(Type forType) : base(() => Console.Error, forType) + { + } + + /// + /// Returns a logger associated with the specified type. + /// + public override ILogger ForType() + { + if (typeof(T) == AssociatedType) + { + return this; + } + return new ConsoleLogger(typeof(T)); + } + } +} diff --git a/src/csharp/Grpc.Core/Logging/ILogger.cs b/src/csharp/Grpc.Core/Logging/ILogger.cs new file mode 100644 index 00000000..e3f68fec --- /dev/null +++ b/src/csharp/Grpc.Core/Logging/ILogger.cs @@ -0,0 +1,60 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; + +namespace Grpc.Core.Logging +{ + /// For logging messages. + public interface ILogger + { + /// Returns a logger associated with the specified type. + ILogger ForType(); + + /// Logs a message with severity Debug. + void Debug(string message); + + /// Logs a formatted message with severity Debug. + void Debug(string format, params object[] formatArgs); + + /// Logs a message with severity Info. + void Info(string message); + + /// Logs a formatted message with severity Info. + void Info(string format, params object[] formatArgs); + + /// Logs a message with severity Warning. + void Warning(string message); + + /// Logs a formatted message with severity Warning. + void Warning(string format, params object[] formatArgs); + + /// Logs a message and an associated exception with severity Warning. + void Warning(Exception exception, string message); + + /// Logs a message with severity Error. + void Error(string message); + + /// Logs a formatted message with severity Error. + void Error(string format, params object[] formatArgs); + + /// Logs a message and an associated exception with severity Error. + void Error(Exception exception, string message); + } +} diff --git a/src/csharp/Grpc.Core/Logging/LogLevel.cs b/src/csharp/Grpc.Core/Logging/LogLevel.cs new file mode 100644 index 00000000..4db0e47b --- /dev/null +++ b/src/csharp/Grpc.Core/Logging/LogLevel.cs @@ -0,0 +1,48 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; + +namespace Grpc.Core.Logging +{ + /// Standard logging levels. + public enum LogLevel + { + /// + /// Debug severity. + /// + Debug = 0, + /// + /// Info severity. + /// + Info, + /// + /// Warning severity. + /// + Warning, + /// + /// Error severity. + /// + Error, + /// + /// Logging is off. + /// + Off = int.MaxValue + } +} diff --git a/src/csharp/Grpc.Core/Logging/LogLevelFilterLogger.cs b/src/csharp/Grpc.Core/Logging/LogLevelFilterLogger.cs new file mode 100644 index 00000000..a650d029 --- /dev/null +++ b/src/csharp/Grpc.Core/Logging/LogLevelFilterLogger.cs @@ -0,0 +1,188 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using Grpc.Core.Utils; + +namespace Grpc.Core.Logging +{ + /// Logger that filters out messages below certain log level. + public class LogLevelFilterLogger : ILogger + { + // Verbosity environment variable used by C core. + private const string CoreVerbosityEnvVarName = "GRPC_VERBOSITY"; + readonly ILogger innerLogger; + readonly LogLevel logLevel; + + /// + /// Creates and instance of LogLevelFilter. + /// + public LogLevelFilterLogger(ILogger logger, LogLevel logLevel) + { + this.innerLogger = GrpcPreconditions.CheckNotNull(logger); + this.logLevel = logLevel; + } + + /// + /// Creates and instance of LogLevelFilter. + /// The fromEnvironmentVariable parameter allows looking up "GRPC_VERBOSITY" setting provided by C-core + /// and uses the same log level for C# logs. Using this setting is recommended as it can prevent unintentionally hiding + /// C core logs requested by "GRPC_VERBOSITY" environment variable (which could happen if C# logger's log level was set to a more restrictive value). + /// + /// the logger to forward filtered logs to. + /// the default log level, unless overriden by env variable. + /// if true, override log level with setting from environment variable. + public LogLevelFilterLogger(ILogger logger, LogLevel defaultLogLevel, bool fromEnvironmentVariable) : this(logger, GetLogLevelFromEnvironment(defaultLogLevel, fromEnvironmentVariable)) + { + } + + /// + /// Returns a logger associated with the specified type. + /// + public virtual ILogger ForType() + { + var newInnerLogger = innerLogger.ForType(); + if (object.ReferenceEquals(this.innerLogger, newInnerLogger)) + { + return this; + } + return new LogLevelFilterLogger(newInnerLogger, logLevel); + } + + /// Logs a message with severity Debug. + public void Debug(string message) + { + if (logLevel <= LogLevel.Debug) + { + innerLogger.Debug(message); + } + } + + /// Logs a formatted message with severity Debug. + public void Debug(string format, params object[] formatArgs) + { + if (logLevel <= LogLevel.Debug) + { + innerLogger.Debug(format, formatArgs); + } + } + + /// Logs a message with severity Info. + public void Info(string message) + { + if (logLevel <= LogLevel.Info) + { + innerLogger.Info(message); + } + } + + /// Logs a formatted message with severity Info. + public void Info(string format, params object[] formatArgs) + { + if (logLevel <= LogLevel.Info) + { + innerLogger.Info(format, formatArgs); + } + } + + /// Logs a message with severity Warning. + public void Warning(string message) + { + if (logLevel <= LogLevel.Warning) + { + innerLogger.Warning(message); + } + } + + /// Logs a formatted message with severity Warning. + public void Warning(string format, params object[] formatArgs) + { + if (logLevel <= LogLevel.Warning) + { + innerLogger.Warning(format, formatArgs); + } + } + + /// Logs a message and an associated exception with severity Warning. + public void Warning(Exception exception, string message) + { + if (logLevel <= LogLevel.Warning) + { + innerLogger.Warning(exception, message); + } + } + + /// Logs a message with severity Error. + public void Error(string message) + { + if (logLevel <= LogLevel.Error) + { + innerLogger.Error(message); + } + } + + /// Logs a formatted message with severity Error. + public void Error(string format, params object[] formatArgs) + { + if (logLevel <= LogLevel.Error) + { + innerLogger.Error(format, formatArgs); + } + } + + /// Logs a message and an associated exception with severity Error. + public void Error(Exception exception, string message) + { + if (logLevel <= LogLevel.Error) + { + innerLogger.Error(exception, message); + } + } + + /// Get log level based on a default and lookup of GRPC_VERBOSITY environment variable. + private static LogLevel GetLogLevelFromEnvironment(LogLevel defaultLogLevel, bool fromEnvironmentVariable) + { + if (!fromEnvironmentVariable) + { + return defaultLogLevel; + } + + var verbosityString = System.Environment.GetEnvironmentVariable(CoreVerbosityEnvVarName); + if (verbosityString == null) + { + return defaultLogLevel; + } + + // NOTE: C core doesn't have "WARNING" log level + switch (verbosityString.ToUpperInvariant()) + { + case "DEBUG": + return LogLevel.Debug; + case "INFO": + return LogLevel.Info; + case "ERROR": + return LogLevel.Error; + default: + return defaultLogLevel; + } + } + } +} diff --git a/src/csharp/Grpc.Core/Logging/NullLogger.cs b/src/csharp/Grpc.Core/Logging/NullLogger.cs new file mode 100644 index 00000000..949d1d3d --- /dev/null +++ b/src/csharp/Grpc.Core/Logging/NullLogger.cs @@ -0,0 +1,107 @@ +#region Copyright notice and license + +// Copyright 2016 gRPC authors. +// +// 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. + +#endregion + +using System; + +namespace Grpc.Core.Logging +{ + /// + /// Logger which doesn't log any information anywhere. + /// + public sealed class NullLogger : ILogger + { + /// + /// As with all logging calls on this logger, this method is a no-op. + /// + public void Debug(string message) + { + } + + /// + /// As with all logging calls on this logger, this method is a no-op. + /// + public void Debug(string format, params object[] formatArgs) + { + } + + /// + /// As with all logging calls on this logger, this method is a no-op. + /// + public void Error(string message) + { + } + + /// + /// As with all logging calls on this logger, this method is a no-op. + /// + public void Error(Exception exception, string message) + { + } + + /// + /// As with all logging calls on this logger, this method is a no-op. + /// + public void Error(string format, params object[] formatArgs) + { + } + + /// + /// Returns a reference to the instance on which the method is called, as + /// instances aren't associated with specific types. + /// + public ILogger ForType() + { + return this; + } + + /// + /// As with all logging calls on this logger, this method is a no-op. + /// + public void Info(string message) + { + } + + /// + /// As with all logging calls on this logger, this method is a no-op. + /// + public void Info(string format, params object[] formatArgs) + { + } + + /// + /// As with all logging calls on this logger, this method is a no-op. + /// + public void Warning(string message) + { + } + + /// + /// As with all logging calls on this logger, this method is a no-op. + /// + public void Warning(Exception exception, string message) + { + } + + /// + /// As with all logging calls on this logger, this method is a no-op. + /// + public void Warning(string format, params object[] formatArgs) + { + } + } +} diff --git a/src/csharp/Grpc.Core/Logging/TextWriterLogger.cs b/src/csharp/Grpc.Core/Logging/TextWriterLogger.cs new file mode 100644 index 00000000..a51c3308 --- /dev/null +++ b/src/csharp/Grpc.Core/Logging/TextWriterLogger.cs @@ -0,0 +1,161 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using Grpc.Core.Utils; + +namespace Grpc.Core.Logging +{ + /// Logger that logs to an arbitrary System.IO.TextWriter. + public class TextWriterLogger : ILogger + { + // Format similar enough to C core log format except nanosecond precision is not supported. + const string DateTimeFormatString = "MMdd HH:mm:ss.ffffff"; + + readonly Func textWriterProvider; + readonly Type forType; + readonly string forTypeString; + + /// + /// Creates a console logger not associated to any specific type and writes to given System.IO.TextWriter. + /// User is responsible for providing an instance of TextWriter that is thread-safe. + /// + public TextWriterLogger(TextWriter textWriter) : this(() => textWriter) + { + GrpcPreconditions.CheckNotNull(textWriter); + } + + /// + /// Creates a console logger not associated to any specific type and writes to a System.IO.TextWriter obtained from given provider. + /// User is responsible for providing an instance of TextWriter that is thread-safe. + /// + public TextWriterLogger(Func textWriterProvider) : this(textWriterProvider, null) + { + } + + /// Creates a console logger that logs messsage specific for given type. + protected TextWriterLogger(Func textWriterProvider, Type forType) + { + this.textWriterProvider = GrpcPreconditions.CheckNotNull(textWriterProvider); + this.forType = forType; + if (forType != null) + { + var namespaceStr = forType.Namespace ?? ""; + if (namespaceStr.Length > 0) + { + namespaceStr += "."; + } + this.forTypeString = namespaceStr + forType.Name + " "; + } + else + { + this.forTypeString = ""; + } + } + + /// + /// Returns a logger associated with the specified type. + /// + public virtual ILogger ForType() + { + if (typeof(T) == forType) + { + return this; + } + return new TextWriterLogger(this.textWriterProvider, typeof(T)); + } + + /// Logs a message with severity Debug. + public void Debug(string message) + { + Log("D", message); + } + + /// Logs a formatted message with severity Debug. + public void Debug(string format, params object[] formatArgs) + { + Debug(string.Format(format, formatArgs)); + } + + /// Logs a message with severity Info. + public void Info(string message) + { + Log("I", message); + } + + /// Logs a formatted message with severity Info. + public void Info(string format, params object[] formatArgs) + { + Info(string.Format(format, formatArgs)); + } + + /// Logs a message with severity Warning. + public void Warning(string message) + { + Log("W", message); + } + + /// Logs a formatted message with severity Warning. + public void Warning(string format, params object[] formatArgs) + { + Warning(string.Format(format, formatArgs)); + } + + /// Logs a message and an associated exception with severity Warning. + public void Warning(Exception exception, string message) + { + Warning(message + " " + exception); + } + + /// Logs a message with severity Error. + public void Error(string message) + { + Log("E", message); + } + + /// Logs a formatted message with severity Error. + public void Error(string format, params object[] formatArgs) + { + Error(string.Format(format, formatArgs)); + } + + /// Logs a message and an associated exception with severity Error. + public void Error(Exception exception, string message) + { + Error(message + " " + exception); + } + + /// Gets the type associated with this logger. + protected Type AssociatedType + { + get { return forType; } + } + + private void Log(string severityString, string message) + { + textWriterProvider().WriteLine("{0}{1} {2}{3}", + severityString, + DateTime.Now.ToString(DateTimeFormatString, CultureInfo.InvariantCulture), + forTypeString, + message); + } + } +} diff --git a/src/csharp/Grpc.Core/Profiling/IProfiler.cs b/src/csharp/Grpc.Core/Profiling/IProfiler.cs new file mode 100644 index 00000000..f8ae34ed --- /dev/null +++ b/src/csharp/Grpc.Core/Profiling/IProfiler.cs @@ -0,0 +1,34 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.IO; +using System.Threading; +using Grpc.Core.Internal; + +namespace Grpc.Core.Profiling +{ + internal interface IProfiler + { + void Begin(string tag); + + void End(string tag); + + void Mark(string tag); + } +} diff --git a/src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs b/src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs new file mode 100644 index 00000000..55031d39 --- /dev/null +++ b/src/csharp/Grpc.Core/Profiling/ProfilerEntry.cs @@ -0,0 +1,73 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.IO; +using System.Threading; +using Grpc.Core.Internal; + +namespace Grpc.Core.Profiling +{ + internal struct ProfilerEntry + { + public enum Type + { + BEGIN, + END, + MARK + } + + public ProfilerEntry(Timespec timespec, Type type, string tag) + { + this.timespec = timespec; + this.type = type; + this.tag = tag; + } + + public Timespec timespec; + public Type type; + public string tag; + + public override string ToString() + { + // mimic the output format used by C core. + return string.Format( + "{{\"t\": {0}.{1}, \"thd\":\"unknown\", \"type\": \"{2}\", \"tag\": \"{3}\", " + + "\"file\": \"unknown\", \"line\": 0, \"imp\": 0}}", + timespec.TimevalSeconds, timespec.TimevalNanos.ToString("D9"), + GetTypeAbbreviation(type), tag); + } + + internal static string GetTypeAbbreviation(Type type) + { + switch (type) + { + case Type.BEGIN: + return "{"; + + case Type.END: + return "}"; + + case Type.MARK: + return "."; + default: + throw new ArgumentException("Unknown type"); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Profiling/ProfilerScope.cs b/src/csharp/Grpc.Core/Profiling/ProfilerScope.cs new file mode 100644 index 00000000..334bc2fa --- /dev/null +++ b/src/csharp/Grpc.Core/Profiling/ProfilerScope.cs @@ -0,0 +1,45 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.IO; +using System.Threading; +using Grpc.Core.Internal; + +namespace Grpc.Core.Profiling +{ + // Allows declaring Begin and End of a profiler scope with a using statement. + // declared as struct for better performance. + internal struct ProfilerScope : IDisposable + { + readonly IProfiler profiler; + readonly string tag; + + public ProfilerScope(IProfiler profiler, string tag) + { + this.profiler = profiler; + this.tag = tag; + this.profiler.Begin(this.tag); + } + + public void Dispose() + { + profiler.End(tag); + } + } +} diff --git a/src/csharp/Grpc.Core/Profiling/Profilers.cs b/src/csharp/Grpc.Core/Profiling/Profilers.cs new file mode 100644 index 00000000..0746f2ab --- /dev/null +++ b/src/csharp/Grpc.Core/Profiling/Profilers.cs @@ -0,0 +1,119 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.IO; +using System.Threading; +using Grpc.Core.Internal; + +namespace Grpc.Core.Profiling +{ + internal static class Profilers + { + static readonly NopProfiler DefaultProfiler = new NopProfiler(); + static readonly ThreadLocal profilers = new ThreadLocal(); + + public static IProfiler ForCurrentThread() + { + return profilers.Value ?? DefaultProfiler; + } + + public static void SetForCurrentThread(IProfiler profiler) + { + profilers.Value = profiler; + } + + public static ProfilerScope NewScope(this IProfiler profiler, string tag) + { + return new ProfilerScope(profiler, tag); + } + } + + internal class NopProfiler : IProfiler + { + public void Begin(string tag) + { + } + + public void End(string tag) + { + } + + public void Mark(string tag) + { + } + } + + // Profiler using Timespec.PreciseNow + internal class BasicProfiler : IProfiler + { + ProfilerEntry[] entries; + int count; + + public BasicProfiler() : this(20*1024*1024) + { + } + + public BasicProfiler(int capacity) + { + this.entries = new ProfilerEntry[capacity]; + } + + public void Begin(string tag) + { + AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.BEGIN, tag)); + } + + public void End(string tag) + { + AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.END, tag)); + } + + public void Mark(string tag) + { + AddEntry(new ProfilerEntry(Timespec.PreciseNow, ProfilerEntry.Type.MARK, tag)); + } + + public void Reset() + { + count = 0; + } + + public void Dump(string filepath) + { + using (var stream = File.CreateText(filepath)) + { + Dump(stream); + } + } + + public void Dump(TextWriter stream) + { + for (int i = 0; i < count; i++) + { + var entry = entries[i]; + stream.WriteLine(entry.ToString()); + } + } + + // NOT THREADSAFE! + void AddEntry(ProfilerEntry entry) { + entries[count++] = entry; + } + } +} diff --git a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..505f5455 --- /dev/null +++ b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs @@ -0,0 +1,50 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.Core")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: InternalsVisibleTo("Grpc.Core.Tests,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] +[assembly: InternalsVisibleTo("Grpc.Core.Testing,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] +[assembly: InternalsVisibleTo("Grpc.IntegrationTesting,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] +[assembly: InternalsVisibleTo("Grpc.Microbenchmarks,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs new file mode 100644 index 00000000..bdcbc11a --- /dev/null +++ b/src/csharp/Grpc.Core/Server.cs @@ -0,0 +1,487 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Grpc.Core.Internal; +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// gRPC server. A single server can serve an arbitrary number of services and can listen on more than one port. + /// + public class Server + { + const int DefaultRequestCallTokensPerCq = 2000; + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + + readonly AtomicCounter activeCallCounter = new AtomicCounter(); + + readonly ServiceDefinitionCollection serviceDefinitions; + readonly ServerPortCollection ports; + readonly GrpcEnvironment environment; + readonly List options; + readonly ServerSafeHandle handle; + readonly object myLock = new object(); + + readonly List serviceDefinitionsList = new List(); + readonly List serverPortList = new List(); + readonly Dictionary callHandlers = new Dictionary(); + readonly TaskCompletionSource shutdownTcs = new TaskCompletionSource(); + + bool startRequested; + volatile bool shutdownRequested; + int requestCallTokensPerCq = DefaultRequestCallTokensPerCq; + + /// + /// Creates a new server. + /// + public Server() : this(null) + { + } + + /// + /// Creates a new server. + /// + /// Channel options. + public Server(IEnumerable options) + { + this.serviceDefinitions = new ServiceDefinitionCollection(this); + this.ports = new ServerPortCollection(this); + this.environment = GrpcEnvironment.AddRef(); + this.options = options != null ? new List(options) : new List(); + using (var channelArgs = ChannelOptions.CreateChannelArgs(this.options)) + { + this.handle = ServerSafeHandle.NewServer(channelArgs); + } + + foreach (var cq in environment.CompletionQueues) + { + this.handle.RegisterCompletionQueue(cq); + } + GrpcEnvironment.RegisterServer(this); + } + + /// + /// Services that will be exported by the server once started. Register a service with this + /// server by adding its definition to this collection. + /// + public ServiceDefinitionCollection Services + { + get + { + return serviceDefinitions; + } + } + + /// + /// Ports on which the server will listen once started. Register a port with this + /// server by adding its definition to this collection. + /// + public ServerPortCollection Ports + { + get + { + return ports; + } + } + + /// + /// To allow awaiting termination of the server. + /// + public Task ShutdownTask + { + get + { + return shutdownTcs.Task; + } + } + + /// + /// Experimental API. Might anytime change without prior notice. + /// Number or calls requested via grpc_server_request_call at any given time for each completion queue. + /// + public int RequestCallTokensPerCompletionQueue + { + get + { + return requestCallTokensPerCq; + } + set + { + lock (myLock) + { + GrpcPreconditions.CheckState(!startRequested); + GrpcPreconditions.CheckArgument(value > 0); + requestCallTokensPerCq = value; + } + } + } + + /// + /// Starts the server. + /// Throws IOException if not all ports have been bound successfully (see Ports.Add method). + /// Even if some of that ports haven't been bound, the server will still serve normally on all ports that have been + /// bound successfully (and the user is expected to shutdown the server by invoking ShutdownAsync or KillAsync). + /// + public void Start() + { + lock (myLock) + { + GrpcPreconditions.CheckState(!startRequested); + GrpcPreconditions.CheckState(!shutdownRequested); + startRequested = true; + + handle.Start(); + + for (int i = 0; i < requestCallTokensPerCq; i++) + { + foreach (var cq in environment.CompletionQueues) + { + AllowOneRpc(cq); + } + } + + // Throw if some ports weren't bound successfully. + // Even when that happens, some server ports might have been + // bound successfully, so we let server initialization + // proceed as usual and we only throw at the very end of the + // Start() method. + CheckPortsBoundSuccessfully(); + } + } + + /// + /// Requests server shutdown and when there are no more calls being serviced, + /// cleans up used resources. The returned task finishes when shutdown procedure + /// is complete. + /// + /// + /// It is strongly recommended to shutdown all previously created servers before exiting from the process. + /// + public Task ShutdownAsync() + { + return ShutdownInternalAsync(false); + } + + /// + /// Requests server shutdown while cancelling all the in-progress calls. + /// The returned task finishes when shutdown procedure is complete. + /// + /// + /// It is strongly recommended to shutdown all previously created servers before exiting from the process. + /// + public Task KillAsync() + { + return ShutdownInternalAsync(true); + } + + internal void AddCallReference(object call) + { + activeCallCounter.Increment(); + + bool success = false; + handle.DangerousAddRef(ref success); + GrpcPreconditions.CheckState(success); + } + + internal void RemoveCallReference(object call) + { + handle.DangerousRelease(); + activeCallCounter.Decrement(); + } + + /// + /// Shuts down the server. + /// + private async Task ShutdownInternalAsync(bool kill) + { + lock (myLock) + { + GrpcPreconditions.CheckState(!shutdownRequested); + shutdownRequested = true; + } + GrpcEnvironment.UnregisterServer(this); + + var cq = environment.CompletionQueues.First(); // any cq will do + handle.ShutdownAndNotify(HandleServerShutdown, cq); + if (kill) + { + handle.CancelAllCalls(); + } + await ShutdownCompleteOrEnvironmentDeadAsync().ConfigureAwait(false); + + DisposeHandle(); + + await GrpcEnvironment.ReleaseAsync().ConfigureAwait(false); + } + + /// + /// In case the environment's threadpool becomes dead, the shutdown completion will + /// never be delivered, but we need to release the environment's handle anyway. + /// + private async Task ShutdownCompleteOrEnvironmentDeadAsync() + { + while (true) + { + var task = await Task.WhenAny(shutdownTcs.Task, Task.Delay(20)).ConfigureAwait(false); + if (shutdownTcs.Task == task) + { + return; + } + if (!environment.IsAlive) + { + return; + } + } + } + + /// + /// Adds a service definition. + /// + private void AddServiceDefinitionInternal(ServerServiceDefinition serviceDefinition) + { + lock (myLock) + { + GrpcPreconditions.CheckState(!startRequested); + foreach (var entry in serviceDefinition.GetCallHandlers()) + { + callHandlers.Add(entry.Key, entry.Value); + } + serviceDefinitionsList.Add(serviceDefinition); + } + } + + /// + /// Adds a listening port. + /// + private int AddPortInternal(ServerPort serverPort) + { + lock (myLock) + { + GrpcPreconditions.CheckNotNull(serverPort.Credentials, "serverPort"); + GrpcPreconditions.CheckState(!startRequested); + var address = string.Format("{0}:{1}", serverPort.Host, serverPort.Port); + int boundPort; + using (var nativeCredentials = serverPort.Credentials.ToNativeCredentials()) + { + if (nativeCredentials != null) + { + boundPort = handle.AddSecurePort(address, nativeCredentials); + } + else + { + boundPort = handle.AddInsecurePort(address); + } + } + var newServerPort = new ServerPort(serverPort, boundPort); + this.serverPortList.Add(newServerPort); + return boundPort; + } + } + + /// + /// Allows one new RPC call to be received by server. + /// + private void AllowOneRpc(CompletionQueueSafeHandle cq) + { + if (!shutdownRequested) + { + // TODO(jtattermusch): avoid unnecessary delegate allocation + handle.RequestCall((success, ctx) => HandleNewServerRpc(success, ctx, cq), cq); + } + } + + /// + /// Checks that all ports have been bound successfully. + /// + private void CheckPortsBoundSuccessfully() + { + lock (myLock) + { + var unboundPort = ports.FirstOrDefault(port => port.BoundPort == 0); + if (unboundPort != null) + { + throw new IOException( + string.Format("Failed to bind port \"{0}:{1}\"", unboundPort.Host, unboundPort.Port)); + } + } + } + + private void DisposeHandle() + { + var activeCallCount = activeCallCounter.Count; + if (activeCallCount > 0) + { + Logger.Warning("Server shutdown has finished but there are still {0} active calls for that server.", activeCallCount); + } + handle.Dispose(); + } + + /// + /// Selects corresponding handler for given call and handles the call. + /// + private async Task HandleCallAsync(ServerRpcNew newRpc, CompletionQueueSafeHandle cq, Action continuation) + { + try + { + IServerCallHandler callHandler; + if (!callHandlers.TryGetValue(newRpc.Method, out callHandler)) + { + callHandler = UnimplementedMethodCallHandler.Instance; + } + await callHandler.HandleCall(newRpc, cq).ConfigureAwait(false); + } + catch (Exception e) + { + Logger.Warning(e, "Exception while handling RPC."); + } + finally + { + continuation(this, cq); + } + } + + /// + /// Handles the native callback. + /// + private void HandleNewServerRpc(bool success, RequestCallContextSafeHandle ctx, CompletionQueueSafeHandle cq) + { + bool nextRpcRequested = false; + if (success) + { + var newRpc = ctx.GetServerRpcNew(this); + + // after server shutdown, the callback returns with null call + if (!newRpc.Call.IsInvalid) + { + nextRpcRequested = true; + + // Start asynchronous handler for the call. + // Don't await, the continuations will run on gRPC thread pool once triggered + // by cq.Next(). + #pragma warning disable 4014 + HandleCallAsync(newRpc, cq, (server, state) => server.AllowOneRpc(state)); + #pragma warning restore 4014 + } + } + + if (!nextRpcRequested) + { + AllowOneRpc(cq); + } + } + + /// + /// Handles native callback. + /// + private void HandleServerShutdown(bool success, BatchContextSafeHandle ctx, object state) + { + shutdownTcs.SetResult(null); + } + + /// + /// Collection of service definitions. + /// + public class ServiceDefinitionCollection : IEnumerable + { + readonly Server server; + + internal ServiceDefinitionCollection(Server server) + { + this.server = server; + } + + /// + /// Adds a service definition to the server. This is how you register + /// handlers for a service with the server. Only call this before Start(). + /// + public void Add(ServerServiceDefinition serviceDefinition) + { + server.AddServiceDefinitionInternal(serviceDefinition); + } + + /// + /// Gets enumerator for this collection. + /// + public IEnumerator GetEnumerator() + { + return server.serviceDefinitionsList.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return server.serviceDefinitionsList.GetEnumerator(); + } + } + + /// + /// Collection of server ports. + /// + public class ServerPortCollection : IEnumerable + { + readonly Server server; + + internal ServerPortCollection(Server server) + { + this.server = server; + } + + /// + /// Adds a new port on which server should listen. + /// Only call this before Start(). + /// The port on which server will be listening. Return value of zero means that binding the port has failed. + /// + public int Add(ServerPort serverPort) + { + return server.AddPortInternal(serverPort); + } + + /// + /// Adds a new port on which server should listen. + /// The port on which server will be listening. Return value of zero means that binding the port has failed. + /// + /// the host + /// the port. If zero, an unused port is chosen automatically. + /// credentials to use to secure this port. + public int Add(string host, int port, ServerCredentials credentials) + { + return Add(new ServerPort(host, port, credentials)); + } + + /// + /// Gets enumerator for this collection. + /// + public IEnumerator GetEnumerator() + { + return server.serverPortList.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return server.serverPortList.GetEnumerator(); + } + } + } +} diff --git a/src/csharp/Grpc.Core/ServerCredentials.cs b/src/csharp/Grpc.Core/ServerCredentials.cs new file mode 100644 index 00000000..d0fc600f --- /dev/null +++ b/src/csharp/Grpc.Core/ServerCredentials.cs @@ -0,0 +1,221 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Server side credentials. + /// + public abstract class ServerCredentials + { + static readonly ServerCredentials InsecureInstance = new InsecureServerCredentialsImpl(); + + /// + /// Returns instance of credential that provides no security and + /// will result in creating an unsecure server port with no encryption whatsoever. + /// + public static ServerCredentials Insecure + { + get + { + return InsecureInstance; + } + } + + /// + /// Creates native object for the credentials. + /// + /// The native credentials. + internal abstract ServerCredentialsSafeHandle ToNativeCredentials(); + + private sealed class InsecureServerCredentialsImpl : ServerCredentials + { + internal override ServerCredentialsSafeHandle ToNativeCredentials() + { + return null; + } + } + } + + /// + /// Modes of requesting client's SSL certificate by the server. + /// Corresponds to grpc_ssl_client_certificate_request_type. + /// + public enum SslClientCertificateRequestType { + /// + /// Server does not request client certificate. + /// The certificate presented by the client is not checked by the server at + /// all. (A client may present a self signed or signed certificate or not + /// present a certificate at all and any of those option would be accepted) + /// + DontRequest = 0, + /// + /// Server requests client certificate but does not enforce that the client + /// presents a certificate. + /// If the client presents a certificate, the client authentication is left to + /// the application (the necessary metadata will be available to the + /// application via authentication context properties, see grpc_auth_context). + /// The client's key certificate pair must be valid for the SSL connection to + /// be established. + /// + RequestButDontVerify, + /// + /// Server requests client certificate but does not enforce that the client + /// presents a certificate. + /// If the client presents a certificate, the client authentication is done by + /// the gRPC framework. (For a successful connection the client needs to either + /// present a certificate that can be verified against the root certificate + /// configured by the server or not present a certificate at all) + /// The client's key certificate pair must be valid for the SSL connection to + /// be established. + /// + RequestAndVerify, + /// + /// Server requests client certificate and enforces that the client presents a + /// certificate. + /// If the client presents a certificate, the client authentication is left to + /// the application (the necessary metadata will be available to the + /// application via authentication context properties, see grpc_auth_context). + /// The client's key certificate pair must be valid for the SSL connection to + /// be established. + /// + RequestAndRequireButDontVerify, + /// + /// Server requests client certificate and enforces that the client presents a + /// certificate. + /// The certificate presented by the client is verified by the gRPC framework. + /// (For a successful connection the client needs to present a certificate that + /// can be verified against the root certificate configured by the server) + /// The client's key certificate pair must be valid for the SSL connection to + /// be established. + /// + RequestAndRequireAndVerify, + } + /// + /// Server-side SSL credentials. + /// + public class SslServerCredentials : ServerCredentials + { + readonly IList keyCertificatePairs; + readonly string rootCertificates; + readonly SslClientCertificateRequestType clientCertificateRequest; + + /// + /// Creates server-side SSL credentials. + /// + /// Key-certificates to use. + /// PEM encoded client root certificates used to authenticate client. + /// Deprecated, use clientCertificateRequest overload instead. + public SslServerCredentials(IEnumerable keyCertificatePairs, string rootCertificates, bool forceClientAuth) + : this(keyCertificatePairs, rootCertificates, forceClientAuth ? SslClientCertificateRequestType.RequestAndRequireAndVerify : SslClientCertificateRequestType.DontRequest) + { + } + + /// + /// Creates server-side SSL credentials. + /// + /// Key-certificates to use. + /// PEM encoded client root certificates used to authenticate client. + /// Options for requesting and verifying client certificate. + public SslServerCredentials(IEnumerable keyCertificatePairs, string rootCertificates, SslClientCertificateRequestType clientCertificateRequest) + { + this.keyCertificatePairs = new List(keyCertificatePairs).AsReadOnly(); + GrpcPreconditions.CheckArgument(this.keyCertificatePairs.Count > 0, + "At least one KeyCertificatePair needs to be provided."); + if (clientCertificateRequest == SslClientCertificateRequestType.RequestAndRequireAndVerify) + { + GrpcPreconditions.CheckNotNull(rootCertificates, + "Cannot require and verify client certificate unless you provide rootCertificates."); + } + this.rootCertificates = rootCertificates; + this.clientCertificateRequest = clientCertificateRequest; + } + + /// + /// Creates server-side SSL credentials. + /// This constructor should be used if you do not wish to authenticate the client. + /// (client certificate won't be requested and checked by the server at all). + /// + /// Key-certificates to use. + public SslServerCredentials(IEnumerable keyCertificatePairs) : this(keyCertificatePairs, null, SslClientCertificateRequestType.DontRequest) + { + } + + /// + /// Key-certificate pairs. + /// + public IList KeyCertificatePairs + { + get + { + return this.keyCertificatePairs; + } + } + + /// + /// PEM encoded client root certificates. + /// + public string RootCertificates + { + get + { + return this.rootCertificates; + } + } + + /// + /// Deprecated. If true, the authenticity of client check will be enforced. + /// + public bool ForceClientAuthentication + { + get + { + return this.clientCertificateRequest == SslClientCertificateRequestType.RequestAndRequireAndVerify; + } + } + + /// + /// Mode of requesting certificate from client by the server. + /// + public SslClientCertificateRequestType ClientCertificateRequest + { + get + { + return this.clientCertificateRequest; + } + } + + internal override ServerCredentialsSafeHandle ToNativeCredentials() + { + int count = keyCertificatePairs.Count; + string[] certChains = new string[count]; + string[] keys = new string[count]; + for (int i = 0; i < count; i++) + { + certChains[i] = keyCertificatePairs[i].CertificateChain; + keys[i] = keyCertificatePairs[i].PrivateKey; + } + return ServerCredentialsSafeHandle.CreateSslCredentials(rootCertificates, certChains, keys, clientCertificateRequest); + } + } +} diff --git a/src/csharp/Grpc.Core/ServerPort.cs b/src/csharp/Grpc.Core/ServerPort.cs new file mode 100644 index 00000000..7eb7f9d0 --- /dev/null +++ b/src/csharp/Grpc.Core/ServerPort.cs @@ -0,0 +1,105 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; + +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// A port exposed by a server. + /// + public class ServerPort + { + /// + /// Pass this value as port to have the server choose an unused listening port for you. + /// Ports added to a server will contain the bound port in their property. + /// + public const int PickUnused = 0; + + readonly string host; + readonly int port; + readonly ServerCredentials credentials; + readonly int boundPort; + + /// + /// Creates a new port on which server should listen. + /// + /// The port on which server will be listening. + /// the host + /// the port. If zero, an unused port is chosen automatically. + /// credentials to use to secure this port. + public ServerPort(string host, int port, ServerCredentials credentials) + { + this.host = GrpcPreconditions.CheckNotNull(host, "host"); + this.port = port; + this.credentials = GrpcPreconditions.CheckNotNull(credentials, "credentials"); + } + + /// + /// Creates a port from an existing ServerPort instance and boundPort value. + /// + internal ServerPort(ServerPort serverPort, int boundPort) + { + this.host = serverPort.host; + this.port = serverPort.port; + this.credentials = serverPort.credentials; + this.boundPort = boundPort; + } + + /// The host. + public string Host + { + get + { + return host; + } + } + + /// The port. + public int Port + { + get + { + return port; + } + } + + /// The server credentials. + public ServerCredentials Credentials + { + get + { + return credentials; + } + } + + /// + /// The port actually bound by the server. This is useful if you let server + /// pick port automatically. + /// + public int BoundPort + { + get + { + return boundPort; + } + } + } +} diff --git a/src/csharp/Grpc.Core/Utils/AsyncStreamExtensions.cs b/src/csharp/Grpc.Core/Utils/AsyncStreamExtensions.cs new file mode 100644 index 00000000..fce53c70 --- /dev/null +++ b/src/csharp/Grpc.Core/Utils/AsyncStreamExtensions.cs @@ -0,0 +1,85 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Grpc.Core.Utils +{ + /// + /// Extension methods that simplify work with gRPC streaming calls. + /// + public static class AsyncStreamExtensions + { + /// + /// Reads the entire stream and executes an async action for each element. + /// + public static async Task ForEachAsync(this IAsyncStreamReader streamReader, Func asyncAction) + where T : class + { + while (await streamReader.MoveNext().ConfigureAwait(false)) + { + await asyncAction(streamReader.Current).ConfigureAwait(false); + } + } + + /// + /// Reads the entire stream and creates a list containing all the elements read. + /// + public static async Task> ToListAsync(this IAsyncStreamReader streamReader) + where T : class + { + var result = new List(); + while (await streamReader.MoveNext().ConfigureAwait(false)) + { + result.Add(streamReader.Current); + } + return result; + } + + /// + /// Writes all elements from given enumerable to the stream. + /// Completes the stream afterwards unless close = false. + /// + public static async Task WriteAllAsync(this IClientStreamWriter streamWriter, IEnumerable elements, bool complete = true) + where T : class + { + foreach (var element in elements) + { + await streamWriter.WriteAsync(element).ConfigureAwait(false); + } + if (complete) + { + await streamWriter.CompleteAsync().ConfigureAwait(false); + } + } + + /// + /// Writes all elements from given enumerable to the stream. + /// + public static async Task WriteAllAsync(this IServerStreamWriter streamWriter, IEnumerable elements) + where T : class + { + foreach (var element in elements) + { + await streamWriter.WriteAsync(element).ConfigureAwait(false); + } + } + } +} diff --git a/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs b/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs new file mode 100644 index 00000000..881994fb --- /dev/null +++ b/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs @@ -0,0 +1,57 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading.Tasks; + +namespace Grpc.Core.Utils +{ + /// + /// Utility methods to run microbenchmarks. + /// + public static class BenchmarkUtil + { + /// + /// Runs a simple benchmark preceded by warmup phase. + /// + public static void RunBenchmark(int warmupIterations, int benchmarkIterations, Action action) + { + var logger = GrpcEnvironment.Logger; + + logger.Info("Warmup iterations: {0}", warmupIterations); + for (int i = 0; i < warmupIterations; i++) + { + action(); + } + + logger.Info("Benchmark iterations: {0}", benchmarkIterations); + var stopwatch = new Stopwatch(); + stopwatch.Start(); + for (int i = 0; i < benchmarkIterations; i++) + { + action(); + } + stopwatch.Stop(); + logger.Info("Elapsed time: {0}ms", stopwatch.ElapsedMilliseconds); + logger.Info("Ops per second: {0}", (int)((double)benchmarkIterations * 1000 / stopwatch.ElapsedMilliseconds)); + } + } +} diff --git a/src/csharp/Grpc.Core/Utils/TaskUtils.cs b/src/csharp/Grpc.Core/Utils/TaskUtils.cs new file mode 100644 index 00000000..34b40cc8 --- /dev/null +++ b/src/csharp/Grpc.Core/Utils/TaskUtils.cs @@ -0,0 +1,44 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Threading.Tasks; + +namespace Grpc.Core.Utils +{ + /// + /// Utility methods for task parallel library. + /// + public static class TaskUtils + { + /// + /// Framework independent equivalent of Task.CompletedTask. + /// + public static Task CompletedTask + { + get + { +#if NETSTANDARD + return Task.CompletedTask; +#else + return Task.FromResult(null); // for .NET45, emulate the functionality +#endif + } + } + } +} diff --git a/src/csharp/Grpc.Examples.MathClient/MathClient.cs b/src/csharp/Grpc.Examples.MathClient/MathClient.cs new file mode 100644 index 00000000..ac13eddc --- /dev/null +++ b/src/csharp/Grpc.Examples.MathClient/MathClient.cs @@ -0,0 +1,42 @@ +#region Copyright notice and license +// Copyright 2015-2016 gRPC authors. +// +// 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. +#endregion +using System.Threading.Tasks; +using Grpc.Core; + +namespace Math +{ + class MathClient + { + public static async Task Main(string[] args) + { + var channel = new Channel("127.0.0.1", 23456, ChannelCredentials.Insecure); + Math.MathClient client = new Math.MathClient(channel); + MathExamples.DivExample(client); + + await MathExamples.DivAsyncExample(client); + + await MathExamples.FibExample(client); + + await MathExamples.SumExample(client); + + await MathExamples.DivManyExample(client); + + await MathExamples.DependentRequestsExample(client); + + await channel.ShutdownAsync(); + } + } +} diff --git a/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..072279e2 --- /dev/null +++ b/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.Examples.MathClient")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.Examples.MathServer/MathServer.cs b/src/csharp/Grpc.Examples.MathServer/MathServer.cs new file mode 100644 index 00000000..56cc1851 --- /dev/null +++ b/src/csharp/Grpc.Examples.MathServer/MathServer.cs @@ -0,0 +1,45 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion + +using System; +using System.Threading.Tasks; +using Grpc.Core; + +namespace Math +{ + class MainClass + { + const string Host = "0.0.0.0"; + const int Port = 23456; + + public static async Task Main(string[] args) + { + Server server = new Server + { + Services = { Math.BindService(new MathServiceImpl()) }, + Ports = { { Host, Port, ServerCredentials.Insecure } } + }; + server.Start(); + + Console.WriteLine("MathServer listening on port " + Port); + + Console.WriteLine("Press any key to stop the server..."); + Console.ReadKey(); + + await server.ShutdownAsync(); + } + } +} diff --git a/src/csharp/Grpc.Examples.MathServer/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Examples.MathServer/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..0d2095e8 --- /dev/null +++ b/src/csharp/Grpc.Examples.MathServer/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.Examples.MathServer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.Examples.Tests/MathClientMockableTest.cs b/src/csharp/Grpc.Examples.Tests/MathClientMockableTest.cs new file mode 100644 index 00000000..6ed7b0a9 --- /dev/null +++ b/src/csharp/Grpc.Examples.Tests/MathClientMockableTest.cs @@ -0,0 +1,101 @@ +#region Copyright notice and license + +// Copyright 2018 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Testing; +using NUnit.Framework; + +namespace Math.Tests +{ + /// + /// Demonstrates how to mock method stubs for all method types in a generated client. + /// + public class MathClientMockableTest + { + [Test] + public void ClientBaseBlockingUnaryCallCanBeMocked() + { + var mockClient = new Moq.Mock(); + + var expected = new DivReply(); + mockClient.Setup(m => m.Div(Moq.It.IsAny(), null, null, CancellationToken.None)).Returns(expected); + Assert.AreSame(expected, mockClient.Object.Div(new DivArgs())); + } + + [Test] + public void ClientBaseBlockingUnaryCallWithCallOptionsCallCanBeMocked() + { + var mockClient = new Moq.Mock(); + + var expected = new DivReply(); + mockClient.Setup(m => m.Div(Moq.It.IsAny(), Moq.It.IsAny())).Returns(expected); + Assert.AreSame(expected, mockClient.Object.Div(new DivArgs(), new CallOptions())); + } + + [Test] + public void ClientBaseAsyncUnaryCallCanBeMocked() + { + var mockClient = new Moq.Mock(); + + // Use a factory method provided by Grpc.Core.Testing.TestCalls to create an instance of a call. + var fakeCall = TestCalls.AsyncUnaryCall(Task.FromResult(new DivReply()), Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }); + mockClient.Setup(m => m.DivAsync(Moq.It.IsAny(), null, null, CancellationToken.None)).Returns(fakeCall); + Assert.AreSame(fakeCall, mockClient.Object.DivAsync(new DivArgs())); + } + + [Test] + public void ClientBaseClientStreamingCallCanBeMocked() + { + var mockClient = new Moq.Mock(); + var mockRequestStream = new Moq.Mock>(); + + // Use a factory method provided by Grpc.Core.Testing.TestCalls to create an instance of a call. + var fakeCall = TestCalls.AsyncClientStreamingCall(mockRequestStream.Object, Task.FromResult(new Num()), Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }); + mockClient.Setup(m => m.Sum(null, null, CancellationToken.None)).Returns(fakeCall); + Assert.AreSame(fakeCall, mockClient.Object.Sum()); + } + + [Test] + public void ClientBaseServerStreamingCallCanBeMocked() + { + var mockClient = new Moq.Mock(); + var mockResponseStream = new Moq.Mock>(); + + // Use a factory method provided by Grpc.Core.Testing.TestCalls to create an instance of a call. + var fakeCall = TestCalls.AsyncServerStreamingCall(mockResponseStream.Object, Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }); + mockClient.Setup(m => m.Fib(Moq.It.IsAny(), null, null, CancellationToken.None)).Returns(fakeCall); + Assert.AreSame(fakeCall, mockClient.Object.Fib(new FibArgs())); + } + + [Test] + public void ClientBaseDuplexStreamingCallCanBeMocked() + { + var mockClient = new Moq.Mock(); + var mockRequestStream = new Moq.Mock>(); + var mockResponseStream = new Moq.Mock>(); + + // Use a factory method provided by Grpc.Core.Testing.TestCalls to create an instance of a call. + var fakeCall = TestCalls.AsyncDuplexStreamingCall(mockRequestStream.Object, mockResponseStream.Object, Task.FromResult(new Metadata()), () => Status.DefaultSuccess, () => new Metadata(), () => { }); + mockClient.Setup(m => m.DivMany(null, null, CancellationToken.None)).Returns(fakeCall); + Assert.AreSame(fakeCall, mockClient.Object.DivMany()); + } + } +} diff --git a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs new file mode 100644 index 00000000..6fa27a6b --- /dev/null +++ b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs @@ -0,0 +1,177 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Math.Tests +{ + /// + /// Math client talks to local math server. + /// + public class MathClientServerTest + { + const string Host = "localhost"; + Server server; + Channel channel; + Math.MathClient client; + + [OneTimeSetUp] + public void Init() + { + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { Math.BindService(new MathServiceImpl()) }, + Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } + }; + server.Start(); + channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure); + client = new Math.MathClient(channel); + } + + [OneTimeTearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void Div1() + { + DivReply response = client.Div(new DivArgs { Dividend = 10, Divisor = 3 }); + Assert.AreEqual(3, response.Quotient); + Assert.AreEqual(1, response.Remainder); + } + + [Test] + public void Div2() + { + DivReply response = client.Div(new DivArgs { Dividend = 0, Divisor = 1 }); + Assert.AreEqual(0, response.Quotient); + Assert.AreEqual(0, response.Remainder); + } + + [Test] + public void DivByZero() + { + var ex = Assert.Throws(() => client.Div(new DivArgs { Dividend = 0, Divisor = 0 })); + Assert.AreEqual(StatusCode.InvalidArgument, ex.Status.StatusCode); + } + + [Test] + public async Task DivAsync() + { + DivReply response = await client.DivAsync(new DivArgs { Dividend = 10, Divisor = 3 }); + Assert.AreEqual(3, response.Quotient); + Assert.AreEqual(1, response.Remainder); + } + + [Test] + public async Task Fib() + { + using (var call = client.Fib(new FibArgs { Limit = 6 })) + { + var responses = await call.ResponseStream.ToListAsync(); + CollectionAssert.AreEqual(new List { 1, 1, 2, 3, 5, 8 }, + responses.Select((n) => n.Num_)); + } + } + + [Test] + public async Task FibWithCancel() + { + var cts = new CancellationTokenSource(); + + using (var call = client.Fib(new FibArgs { Limit = 0 }, cancellationToken: cts.Token)) + { + List responses = new List(); + + try + { + while (await call.ResponseStream.MoveNext()) + { + if (responses.Count == 0) + { + cts.CancelAfter(500); // make sure we cancel soon + } + responses.Add(call.ResponseStream.Current.Num_); + } + Assert.Fail(); + } + catch (RpcException e) + { + Assert.IsTrue(responses.Count > 0); + Assert.AreEqual(StatusCode.Cancelled, e.Status.StatusCode); + } + } + } + + [Test] + public void FibWithDeadline() + { + using (var call = client.Fib(new FibArgs { Limit = 0 }, + deadline: DateTime.UtcNow.AddMilliseconds(500))) + { + var ex = Assert.ThrowsAsync(async () => await call.ResponseStream.ToListAsync()); + Assert.AreEqual(StatusCode.DeadlineExceeded, ex.Status.StatusCode); + } + } + + // TODO: test Fib with limit=0 and cancellation + [Test] + public async Task Sum() + { + using (var call = client.Sum()) + { + var numbers = new List { 10, 20, 30 }.Select(n => new Num { Num_ = n }); + + await call.RequestStream.WriteAllAsync(numbers); + var result = await call.ResponseAsync; + Assert.AreEqual(60, result.Num_); + } + } + + [Test] + public async Task DivMany() + { + var divArgsList = new List + { + new DivArgs { Dividend = 10, Divisor = 3 }, + new DivArgs { Dividend = 100, Divisor = 21 }, + new DivArgs { Dividend = 7, Divisor = 2 } + }; + + using (var call = client.DivMany()) + { + await call.RequestStream.WriteAllAsync(divArgsList); + var result = await call.ResponseStream.ToListAsync(); + + CollectionAssert.AreEqual(new long[] { 3, 4, 3 }, result.Select((divReply) => divReply.Quotient)); + CollectionAssert.AreEqual(new long[] { 1, 16, 1 }, result.Select((divReply) => divReply.Remainder)); + } + } + } +} diff --git a/src/csharp/Grpc.Examples.Tests/MathServiceImplTestabilityTest.cs b/src/csharp/Grpc.Examples.Tests/MathServiceImplTestabilityTest.cs new file mode 100644 index 00000000..7c5fb944 --- /dev/null +++ b/src/csharp/Grpc.Examples.Tests/MathServiceImplTestabilityTest.cs @@ -0,0 +1,47 @@ +#region Copyright notice and license + +// Copyright 2018 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Testing; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Math.Tests +{ + /// + /// Demonstrates how to unit test implementations of generated server stubs. + /// + public class MathServiceImplTestabilityTest + { + [Test] + public async Task ServerCallImplIsTestable() + { + var mathImpl = new MathServiceImpl(); + + // Use a factory method provided by Grpc.Core.Testing.TestServerCallContext to create an instance of server call context. + // This allows testing even those server-side implementations that rely on the contents of ServerCallContext. + var fakeServerCallContext = TestServerCallContext.Create("fooMethod", null, DateTime.UtcNow.AddHours(1), new Metadata(), CancellationToken.None, "127.0.0.1", null, null, (metadata) => TaskUtils.CompletedTask, () => new WriteOptions(), (writeOptions) => { }); + var response = await mathImpl.Div(new DivArgs { Dividend = 10, Divisor = 2 }, fakeServerCallContext); + Assert.AreEqual(5, response.Quotient); + Assert.AreEqual(0, response.Remainder); + } + } +} diff --git a/src/csharp/Grpc.Examples.Tests/NUnitMain.cs b/src/csharp/Grpc.Examples.Tests/NUnitMain.cs new file mode 100644 index 00000000..107df648 --- /dev/null +++ b/src/csharp/Grpc.Examples.Tests/NUnitMain.cs @@ -0,0 +1,40 @@ +#region Copyright notice and license + +// Copyright 2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Reflection; +using Grpc.Core; +using Grpc.Core.Logging; +using NUnit.Common; +using NUnitLite; + +namespace Grpc.Examples.Tests +{ + /// + /// Provides entry point for NUnitLite + /// + public class NUnitMain + { + public static int Main(string[] args) + { + // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. + GrpcEnvironment.SetLogger(new ConsoleLogger()); + return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args); + } + } +} diff --git a/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..7f3c852b --- /dev/null +++ b/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.Examples.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.Examples/Math.cs b/src/csharp/Grpc.Examples/Math.cs new file mode 100644 index 00000000..0eece852 --- /dev/null +++ b/src/csharp/Grpc.Examples/Math.cs @@ -0,0 +1,1073 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: math/math.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Math { + + /// Holder for reflection information generated from math/math.proto + public static partial class MathReflection { + + #region Descriptor + /// File descriptor for math/math.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static MathReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Cg9tYXRoL21hdGgucHJvdG8SBG1hdGgiLAoHRGl2QXJncxIQCghkaXZpZGVu", + "ZBgBIAEoAxIPCgdkaXZpc29yGAIgASgDIi8KCERpdlJlcGx5EhAKCHF1b3Rp", + "ZW50GAEgASgDEhEKCXJlbWFpbmRlchgCIAEoAyIYCgdGaWJBcmdzEg0KBWxp", + "bWl0GAEgASgDIhIKA051bRILCgNudW0YASABKAMiGQoIRmliUmVwbHkSDQoF", + "Y291bnQYASABKAMypAEKBE1hdGgSJgoDRGl2Eg0ubWF0aC5EaXZBcmdzGg4u", + "bWF0aC5EaXZSZXBseSIAEi4KB0Rpdk1hbnkSDS5tYXRoLkRpdkFyZ3MaDi5t", + "YXRoLkRpdlJlcGx5IgAoATABEiMKA0ZpYhINLm1hdGguRmliQXJncxoJLm1h", + "dGguTnVtIgAwARIfCgNTdW0SCS5tYXRoLk51bRoJLm1hdGguTnVtIgAoAWIG", + "cHJvdG8z")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Math.DivArgs), global::Math.DivArgs.Parser, new[]{ "Dividend", "Divisor" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Math.DivReply), global::Math.DivReply.Parser, new[]{ "Quotient", "Remainder" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Math.FibArgs), global::Math.FibArgs.Parser, new[]{ "Limit" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Math.Num), global::Math.Num.Parser, new[]{ "Num_" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Math.FibReply), global::Math.FibReply.Parser, new[]{ "Count" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class DivArgs : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DivArgs()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Math.MathReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public DivArgs() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public DivArgs(DivArgs other) : this() { + dividend_ = other.dividend_; + divisor_ = other.divisor_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public DivArgs Clone() { + return new DivArgs(this); + } + + /// Field number for the "dividend" field. + public const int DividendFieldNumber = 1; + private long dividend_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long Dividend { + get { return dividend_; } + set { + dividend_ = value; + } + } + + /// Field number for the "divisor" field. + public const int DivisorFieldNumber = 2; + private long divisor_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long Divisor { + get { return divisor_; } + set { + divisor_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as DivArgs); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(DivArgs other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Dividend != other.Dividend) return false; + if (Divisor != other.Divisor) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Dividend != 0L) hash ^= Dividend.GetHashCode(); + if (Divisor != 0L) hash ^= Divisor.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Dividend != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Dividend); + } + if (Divisor != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Divisor); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Dividend != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Dividend); + } + if (Divisor != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Divisor); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Dividend != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Dividend); + } + if (Divisor != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Divisor); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(DivArgs other) { + if (other == null) { + return; + } + if (other.Dividend != 0L) { + Dividend = other.Dividend; + } + if (other.Divisor != 0L) { + Divisor = other.Divisor; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Dividend = input.ReadInt64(); + break; + } + case 16: { + Divisor = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Dividend = input.ReadInt64(); + break; + } + case 16: { + Divisor = input.ReadInt64(); + break; + } + } + } + } + #endif + + } + + public sealed partial class DivReply : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DivReply()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Math.MathReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public DivReply() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public DivReply(DivReply other) : this() { + quotient_ = other.quotient_; + remainder_ = other.remainder_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public DivReply Clone() { + return new DivReply(this); + } + + /// Field number for the "quotient" field. + public const int QuotientFieldNumber = 1; + private long quotient_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long Quotient { + get { return quotient_; } + set { + quotient_ = value; + } + } + + /// Field number for the "remainder" field. + public const int RemainderFieldNumber = 2; + private long remainder_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long Remainder { + get { return remainder_; } + set { + remainder_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as DivReply); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(DivReply other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Quotient != other.Quotient) return false; + if (Remainder != other.Remainder) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Quotient != 0L) hash ^= Quotient.GetHashCode(); + if (Remainder != 0L) hash ^= Remainder.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Quotient != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Quotient); + } + if (Remainder != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Remainder); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Quotient != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Quotient); + } + if (Remainder != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Remainder); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Quotient != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Quotient); + } + if (Remainder != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Remainder); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(DivReply other) { + if (other == null) { + return; + } + if (other.Quotient != 0L) { + Quotient = other.Quotient; + } + if (other.Remainder != 0L) { + Remainder = other.Remainder; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Quotient = input.ReadInt64(); + break; + } + case 16: { + Remainder = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Quotient = input.ReadInt64(); + break; + } + case 16: { + Remainder = input.ReadInt64(); + break; + } + } + } + } + #endif + + } + + public sealed partial class FibArgs : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FibArgs()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Math.MathReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public FibArgs() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public FibArgs(FibArgs other) : this() { + limit_ = other.limit_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public FibArgs Clone() { + return new FibArgs(this); + } + + /// Field number for the "limit" field. + public const int LimitFieldNumber = 1; + private long limit_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long Limit { + get { return limit_; } + set { + limit_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as FibArgs); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(FibArgs other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Limit != other.Limit) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Limit != 0L) hash ^= Limit.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Limit != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Limit); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Limit != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Limit); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Limit != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Limit); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(FibArgs other) { + if (other == null) { + return; + } + if (other.Limit != 0L) { + Limit = other.Limit; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Limit = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Limit = input.ReadInt64(); + break; + } + } + } + } + #endif + + } + + public sealed partial class Num : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Num()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Math.MathReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Num() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Num(Num other) : this() { + num_ = other.num_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Num Clone() { + return new Num(this); + } + + /// Field number for the "num" field. + public const int Num_FieldNumber = 1; + private long num_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long Num_ { + get { return num_; } + set { + num_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Num); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Num other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Num_ != other.Num_) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Num_ != 0L) hash ^= Num_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Num_ != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Num_); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Num_ != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Num_); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Num_ != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Num_); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Num other) { + if (other == null) { + return; + } + if (other.Num_ != 0L) { + Num_ = other.Num_; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Num_ = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Num_ = input.ReadInt64(); + break; + } + } + } + } + #endif + + } + + public sealed partial class FibReply : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FibReply()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Math.MathReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public FibReply() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public FibReply(FibReply other) : this() { + count_ = other.count_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public FibReply Clone() { + return new FibReply(this); + } + + /// Field number for the "count" field. + public const int CountFieldNumber = 1; + private long count_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long Count { + get { return count_; } + set { + count_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as FibReply); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(FibReply other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Count != other.Count) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Count != 0L) hash ^= Count.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Count != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Count); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Count != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Count); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Count != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Count); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(FibReply other) { + if (other == null) { + return; + } + if (other.Count != 0L) { + Count = other.Count; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Count = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Count = input.ReadInt64(); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.Examples/MathExamples.cs b/src/csharp/Grpc.Examples/MathExamples.cs new file mode 100644 index 00000000..d29c41a6 --- /dev/null +++ b/src/csharp/Grpc.Examples/MathExamples.cs @@ -0,0 +1,137 @@ +#region Copyright notice and license +// Copyright 2015-2016 gRPC authors. +// +// 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. +#endregion + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; + +namespace Math +{ + public static class MathExamples + { + public static void DivExample(Math.MathClient client) + { + DivReply result = client.Div(new DivArgs { Dividend = 10, Divisor = 3 }); + Console.WriteLine("Div Result: " + result); + } + + public static async Task DivAsyncExample(Math.MathClient client) + { + DivReply result = await client.DivAsync(new DivArgs { Dividend = 4, Divisor = 5 }); + Console.WriteLine("DivAsync Result: " + result); + } + + public static async Task FibExample(Math.MathClient client) + { + using (var call = client.Fib(new FibArgs { Limit = 5 })) + { + List result = await call.ResponseStream.ToListAsync(); + Console.WriteLine("Fib Result: " + string.Join("|", result)); + } + } + + public static async Task SumExample(Math.MathClient client) + { + var numbers = new List + { + new Num { Num_ = 1 }, + new Num { Num_ = 2 }, + new Num { Num_ = 3 } + }; + + using (var call = client.Sum()) + { + await call.RequestStream.WriteAllAsync(numbers); + Console.WriteLine("Sum Result: " + await call.ResponseAsync); + } + } + + public static async Task DivManyExample(Math.MathClient client) + { + var divArgsList = new List + { + new DivArgs { Dividend = 10, Divisor = 3 }, + new DivArgs { Dividend = 100, Divisor = 21 }, + new DivArgs { Dividend = 7, Divisor = 2 } + }; + + using (var call = client.DivMany()) + { + await call.RequestStream.WriteAllAsync(divArgsList); + Console.WriteLine("DivMany Result: " + string.Join("|", await call.ResponseStream.ToListAsync())); + } + } + + public static async Task DependentRequestsExample(Math.MathClient client) + { + var numbers = new List + { + new Num { Num_ = 1 }, + new Num { Num_ = 2 }, + new Num { Num_ = 3 } + }; + + Num sum; + using (var sumCall = client.Sum()) + { + await sumCall.RequestStream.WriteAllAsync(numbers); + sum = await sumCall.ResponseAsync; + } + + DivReply result = await client.DivAsync(new DivArgs { Dividend = sum.Num_, Divisor = numbers.Count }); + Console.WriteLine("Avg Result: " + result); + } + + /// + /// Shows how to handle a call ending with non-OK status. + /// + public static async Task HandleErrorExample(Math.MathClient client) + { + try + { + DivReply result = await client.DivAsync(new DivArgs { Dividend = 5, Divisor = 0 }); + } + catch (RpcException ex) + { + Console.WriteLine(string.Format("RPC ended with status {0}", ex.Status)); + } + } + + /// + /// Shows how to send request headers and how to access response headers + /// and response trailers. + /// + public static async Task MetadataExample(Math.MathClient client) + { + var requestHeaders = new Metadata + { + { "custom-header", "custom-value" } + }; + + var call = client.DivAsync(new DivArgs { Dividend = 5, Divisor = 0 }, requestHeaders); + + // Get response headers + Metadata responseHeaders = await call.ResponseHeadersAsync; + + var result = await call; + + // Get response trailers after the call has finished. + Metadata responseTrailers = call.GetTrailers(); + } + } +} diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs new file mode 100644 index 00000000..50657c21 --- /dev/null +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -0,0 +1,367 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: math/math.proto +// +// Original file comments: +// Copyright 2015 gRPC authors. +// +// 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. +// +#pragma warning disable 0414, 1591 +#region Designer generated code + +using grpc = global::Grpc.Core; + +namespace Math { + public static partial class Math + { + static readonly string __ServiceName = "math.Math"; + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context) + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (message is global::Google.Protobuf.IBufferMessage) + { + context.SetPayloadLength(message.CalculateSize()); + global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter()); + context.Complete(); + return; + } + #endif + context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static class __Helper_MessageCache + { + public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static T __Helper_DeserializeMessage(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser parser) where T : global::Google.Protobuf.IMessage + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (__Helper_MessageCache.IsBufferMessage) + { + return parser.ParseFrom(context.PayloadAsReadOnlySequence()); + } + #endif + return parser.ParseFrom(context.PayloadAsNewBuffer()); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_math_DivArgs = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Math.DivArgs.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_math_DivReply = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Math.DivReply.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_math_FibArgs = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Math.FibArgs.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_math_Num = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Math.Num.Parser)); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_Div = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "Div", + __Marshaller_math_DivArgs, + __Marshaller_math_DivReply); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_DivMany = new grpc::Method( + grpc::MethodType.DuplexStreaming, + __ServiceName, + "DivMany", + __Marshaller_math_DivArgs, + __Marshaller_math_DivReply); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_Fib = new grpc::Method( + grpc::MethodType.ServerStreaming, + __ServiceName, + "Fib", + __Marshaller_math_FibArgs, + __Marshaller_math_Num); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_Sum = new grpc::Method( + grpc::MethodType.ClientStreaming, + __ServiceName, + "Sum", + __Marshaller_math_Num, + __Marshaller_math_Num); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Math.MathReflection.Descriptor.Services[0]; } + } + + /// Base class for server-side implementations of Math + [grpc::BindServiceMethod(typeof(Math), "BindService")] + public abstract partial class MathBase + { + /// + /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient + /// and remainder. + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task Div(global::Math.DivArgs request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// DivMany accepts an arbitrary number of division args from the client stream + /// and sends back the results in the reply stream. The stream continues until + /// the client closes its end; the server does the same after sending all the + /// replies. The stream ends immediately if either end aborts. + /// + /// Used for reading requests from the client. + /// Used for sending responses back to the client. + /// The context of the server-side call handler being invoked. + /// A task indicating completion of the handler. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task DivMany(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// Fib generates numbers in the Fibonacci sequence. If FibArgs.limit > 0, Fib + /// generates up to limit numbers; otherwise it continues until the call is + /// canceled. Unlike Fib above, Fib has no final FibReply. + /// + /// The request received from the client. + /// Used for sending responses back to the client. + /// The context of the server-side call handler being invoked. + /// A task indicating completion of the handler. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task Fib(global::Math.FibArgs request, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// Sum sums a stream of numbers, returning the final result once the stream + /// is closed. + /// + /// Used for reading requests from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task Sum(grpc::IAsyncStreamReader requestStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for Math + public partial class MathClient : grpc::ClientBase + { + /// Creates a new client for Math + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public MathClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for Math that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public MathClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected MathClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected MathClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient + /// and remainder. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Math.DivReply Div(global::Math.DivArgs request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return Div(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient + /// and remainder. + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Math.DivReply Div(global::Math.DivArgs request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_Div, null, options, request); + } + /// + /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient + /// and remainder. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall DivAsync(global::Math.DivArgs request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return DivAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient + /// and remainder. + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall DivAsync(global::Math.DivArgs request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_Div, null, options, request); + } + /// + /// DivMany accepts an arbitrary number of division args from the client stream + /// and sends back the results in the reply stream. The stream continues until + /// the client closes its end; the server does the same after sending all the + /// replies. The stream ends immediately if either end aborts. + /// + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall DivMany(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return DivMany(new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// DivMany accepts an arbitrary number of division args from the client stream + /// and sends back the results in the reply stream. The stream continues until + /// the client closes its end; the server does the same after sending all the + /// replies. The stream ends immediately if either end aborts. + /// + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall DivMany(grpc::CallOptions options) + { + return CallInvoker.AsyncDuplexStreamingCall(__Method_DivMany, null, options); + } + /// + /// Fib generates numbers in the Fibonacci sequence. If FibArgs.limit > 0, Fib + /// generates up to limit numbers; otherwise it continues until the call is + /// canceled. Unlike Fib above, Fib has no final FibReply. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncServerStreamingCall Fib(global::Math.FibArgs request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return Fib(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Fib generates numbers in the Fibonacci sequence. If FibArgs.limit > 0, Fib + /// generates up to limit numbers; otherwise it continues until the call is + /// canceled. Unlike Fib above, Fib has no final FibReply. + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncServerStreamingCall Fib(global::Math.FibArgs request, grpc::CallOptions options) + { + return CallInvoker.AsyncServerStreamingCall(__Method_Fib, null, options, request); + } + /// + /// Sum sums a stream of numbers, returning the final result once the stream + /// is closed. + /// + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncClientStreamingCall Sum(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return Sum(new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Sum sums a stream of numbers, returning the final result once the stream + /// is closed. + /// + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncClientStreamingCall Sum(grpc::CallOptions options) + { + return CallInvoker.AsyncClientStreamingCall(__Method_Sum, null, options); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override MathClient NewInstance(ClientBaseConfiguration configuration) + { + return new MathClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static grpc::ServerServiceDefinition BindService(MathBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_Div, serviceImpl.Div) + .AddMethod(__Method_DivMany, serviceImpl.DivMany) + .AddMethod(__Method_Fib, serviceImpl.Fib) + .AddMethod(__Method_Sum, serviceImpl.Sum).Build(); + } + + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static void BindService(grpc::ServiceBinderBase serviceBinder, MathBase serviceImpl) + { + serviceBinder.AddMethod(__Method_Div, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.Div)); + serviceBinder.AddMethod(__Method_DivMany, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.DivMany)); + serviceBinder.AddMethod(__Method_Fib, serviceImpl == null ? null : new grpc::ServerStreamingServerMethod(serviceImpl.Fib)); + serviceBinder.AddMethod(__Method_Sum, serviceImpl == null ? null : new grpc::ClientStreamingServerMethod(serviceImpl.Sum)); + } + + } +} +#endregion diff --git a/src/csharp/Grpc.Examples/MathServiceImpl.cs b/src/csharp/Grpc.Examples/MathServiceImpl.cs new file mode 100644 index 00000000..2ef76290 --- /dev/null +++ b/src/csharp/Grpc.Examples/MathServiceImpl.cs @@ -0,0 +1,95 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System.Collections.Generic; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; + +namespace Math +{ + /// + /// Implementation of MathService server + /// + public class MathServiceImpl : Math.MathBase + { + public override Task Div(DivArgs request, ServerCallContext context) + { + return Task.FromResult(DivInternal(request)); + } + + public override async Task Fib(FibArgs request, IServerStreamWriter responseStream, ServerCallContext context) + { + var limit = request.Limit > 0 ? request.Limit : long.MaxValue; + var fibEnumerator = FibInternal(limit).GetEnumerator(); + + // Keep streaming the sequence until the call is cancelled. + // Use CancellationToken from ServerCallContext to detect the cancellation. + while (!context.CancellationToken.IsCancellationRequested && fibEnumerator.MoveNext()) + { + await responseStream.WriteAsync(fibEnumerator.Current); + await Task.Delay(100); + } + } + + public override async Task Sum(IAsyncStreamReader requestStream, ServerCallContext context) + { + long sum = 0; + await requestStream.ForEachAsync(num => + { + sum += num.Num_; + return TaskUtils.CompletedTask; + }); + return new Num { Num_ = sum }; + } + + public override async Task DivMany(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + { + await requestStream.ForEachAsync(async divArgs => await responseStream.WriteAsync(DivInternal(divArgs))); + } + + static DivReply DivInternal(DivArgs args) + { + if (args.Divisor == 0) + { + // One can finish the RPC with non-ok status by throwing RpcException instance. + // Alternatively, resulting status can be set using ServerCallContext.Status + throw new RpcException(new Status(StatusCode.InvalidArgument, "Division by zero")); + } + + long quotient = args.Dividend / args.Divisor; + long remainder = args.Dividend % args.Divisor; + return new DivReply { Quotient = quotient, Remainder = remainder }; + } + + static IEnumerable FibInternal(long n) + { + long a = 1; + yield return new Num { Num_ = a }; + + long b = 1; + for (long i = 0; i < n - 1; i++) + { + long temp = a; + a = b; + b = temp + b; + yield return new Num { Num_ = a }; + } + } + } +} diff --git a/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..e8b375b3 --- /dev/null +++ b/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.Examples")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs new file mode 100644 index 00000000..371825bc --- /dev/null +++ b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs @@ -0,0 +1,83 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Health.V1; +using NUnit.Framework; + +namespace Grpc.HealthCheck.Tests +{ + /// + /// Health client talks to health server. + /// + public class HealthClientServerTest + { + const string Host = "localhost"; + Server server; + Channel channel; + Grpc.Health.V1.Health.HealthClient client; + Grpc.HealthCheck.HealthServiceImpl serviceImpl; + + [OneTimeSetUp] + public void Init() + { + serviceImpl = new HealthServiceImpl(); + + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { Grpc.Health.V1.Health.BindService(serviceImpl) }, + Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } + }; + server.Start(); + channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure); + + client = new Grpc.Health.V1.Health.HealthClient(channel); + } + + [OneTimeTearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + + server.ShutdownAsync().Wait(); + } + + [Test] + public void ServiceIsRunning() + { + serviceImpl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving); + + var response = client.Check(new HealthCheckRequest { Service = "" }); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, response.Status); + } + + [Test] + public void ServiceDoesntExist() + { + var ex = Assert.Throws(() => client.Check(new HealthCheckRequest { Service = "nonexistent.service" })); + Assert.AreEqual(StatusCode.NotFound, ex.Status.StatusCode); + } + + // TODO(jtattermusch): add test with timeout once timeouts are supported + } +} diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs new file mode 100644 index 00000000..08fe84ca --- /dev/null +++ b/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs @@ -0,0 +1,260 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Health.V1; +using NUnit.Framework; + +namespace Grpc.HealthCheck.Tests +{ + /// + /// Tests for HealthCheckServiceImpl + /// + public class HealthServiceImplTest + { + [Test] + public void SetStatus() + { + var impl = new HealthServiceImpl(); + impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, GetStatusHelper(impl, "")); + + impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.NotServing); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.NotServing, GetStatusHelper(impl, "")); + + impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Unknown); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Unknown, GetStatusHelper(impl, "")); + + impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.Serving); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, GetStatusHelper(impl, "grpc.test.TestService")); + } + + [Test] + public void ClearStatus() + { + var impl = new HealthServiceImpl(); + impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving); + impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.Unknown); + + impl.ClearStatus(""); + + var ex = Assert.Throws(() => GetStatusHelper(impl, "")); + Assert.AreEqual(StatusCode.NotFound, ex.Status.StatusCode); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Unknown, GetStatusHelper(impl, "grpc.test.TestService")); + } + + [Test] + public void ClearAll() + { + var impl = new HealthServiceImpl(); + impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving); + impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.Unknown); + + impl.ClearAll(); + Assert.Throws(typeof(RpcException), () => GetStatusHelper(impl, "")); + Assert.Throws(typeof(RpcException), () => GetStatusHelper(impl, "grpc.test.TestService")); + } + + [Test] + public void NullsRejected() + { + var impl = new HealthServiceImpl(); + Assert.Throws(typeof(ArgumentNullException), () => impl.SetStatus(null, HealthCheckResponse.Types.ServingStatus.Serving)); + + Assert.Throws(typeof(ArgumentNullException), () => impl.ClearStatus(null)); + } + +#if GRPC_SUPPORT_WATCH + [Test] + public async Task Watch() + { + var cts = new CancellationTokenSource(); + var context = new TestServerCallContext(cts.Token); + var writer = new TestResponseStreamWriter(); + + var impl = new HealthServiceImpl(); + var callTask = impl.Watch(new HealthCheckRequest { Service = "" }, writer, context); + + // Calling Watch on a service that doesn't have a value set will initially return ServiceUnknown + var nextWriteTask = writer.WrittenMessagesReader.ReadAsync(); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask).Status); + + nextWriteTask = writer.WrittenMessagesReader.ReadAsync(); + impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, (await nextWriteTask).Status); + + nextWriteTask = writer.WrittenMessagesReader.ReadAsync(); + impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.NotServing); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.NotServing, (await nextWriteTask).Status); + + nextWriteTask = writer.WrittenMessagesReader.ReadAsync(); + impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Unknown); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Unknown, (await nextWriteTask).Status); + + // Setting status for a different service name will not update Watch results + nextWriteTask = writer.WrittenMessagesReader.ReadAsync(); + impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.Serving); + Assert.IsFalse(nextWriteTask.IsCompleted); + + impl.ClearStatus(""); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask).Status); + + Assert.IsFalse(callTask.IsCompleted); + cts.Cancel(); + await callTask; + } + + [Test] + public async Task Watch_MultipleWatchesForSameService() + { + var cts = new CancellationTokenSource(); + var context = new TestServerCallContext(cts.Token); + var writer1 = new TestResponseStreamWriter(); + var writer2 = new TestResponseStreamWriter(); + + var impl = new HealthServiceImpl(); + var callTask1 = impl.Watch(new HealthCheckRequest { Service = "" }, writer1, context); + var callTask2 = impl.Watch(new HealthCheckRequest { Service = "" }, writer2, context); + + // Calling Watch on a service that doesn't have a value set will initially return ServiceUnknown + var nextWriteTask1 = writer1.WrittenMessagesReader.ReadAsync(); + var nextWriteTask2 = writer2.WrittenMessagesReader.ReadAsync(); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask1).Status); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask2).Status); + + nextWriteTask1 = writer1.WrittenMessagesReader.ReadAsync(); + nextWriteTask2 = writer2.WrittenMessagesReader.ReadAsync(); + impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, (await nextWriteTask1).Status); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, (await nextWriteTask2).Status); + + nextWriteTask1 = writer1.WrittenMessagesReader.ReadAsync(); + nextWriteTask2 = writer2.WrittenMessagesReader.ReadAsync(); + impl.ClearStatus(""); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask1).Status); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask2).Status); + + cts.Cancel(); + await callTask1; + await callTask2; + } + + [Test] + public async Task Watch_MultipleWatchesForDifferentServices() + { + var cts = new CancellationTokenSource(); + var context = new TestServerCallContext(cts.Token); + var writer1 = new TestResponseStreamWriter(); + var writer2 = new TestResponseStreamWriter(); + + var impl = new HealthServiceImpl(); + var callTask1 = impl.Watch(new HealthCheckRequest { Service = "One" }, writer1, context); + var callTask2 = impl.Watch(new HealthCheckRequest { Service = "Two" }, writer2, context); + + // Calling Watch on a service that doesn't have a value set will initially return ServiceUnknown + var nextWriteTask1 = writer1.WrittenMessagesReader.ReadAsync(); + var nextWriteTask2 = writer2.WrittenMessagesReader.ReadAsync(); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask1).Status); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask2).Status); + + nextWriteTask1 = writer1.WrittenMessagesReader.ReadAsync(); + nextWriteTask2 = writer2.WrittenMessagesReader.ReadAsync(); + impl.SetStatus("One", HealthCheckResponse.Types.ServingStatus.Serving); + impl.SetStatus("Two", HealthCheckResponse.Types.ServingStatus.NotServing); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, (await nextWriteTask1).Status); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.NotServing, (await nextWriteTask2).Status); + + nextWriteTask1 = writer1.WrittenMessagesReader.ReadAsync(); + nextWriteTask2 = writer2.WrittenMessagesReader.ReadAsync(); + impl.ClearAll(); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask1).Status); + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask2).Status); + + cts.Cancel(); + await callTask1; + await callTask2; + } + + [Test] + public async Task Watch_ExceedMaximumCapacitySize_DiscardOldValues() + { + var cts = new CancellationTokenSource(); + var context = new TestServerCallContext(cts.Token); + var writer = new TestResponseStreamWriter(started: false); + + var impl = new HealthServiceImpl(); + var callTask = impl.Watch(new HealthCheckRequest { Service = "" }, writer, context); + + // Write new statuses. Only last statuses will be returned when we read them from watch writer + for (var i = 0; i < HealthServiceImpl.MaxStatusBufferSize * 2; i++) + { + // These statuses aren't "valid" but it is useful for testing to have an incrementing number + impl.SetStatus("", (HealthCheckResponse.Types.ServingStatus)i + 10); + } + + // Start reading responses now that statuses have been queued up + // This is to keep the test non-flakey + writer.Start(); + + // Read messages in a background task + var statuses = new List(); + var readStatusesTask = Task.Run(async () => { + while (await writer.WrittenMessagesReader.WaitToReadAsync()) + { + if (writer.WrittenMessagesReader.TryRead(out var response)) + { + statuses.Add(response.Status); + } + } + }); + + // Tell server we're done watching and it can write what it has left and then exit + cts.Cancel(); + await callTask; + + // Ensure we've read all the queued statuses + writer.Complete(); + await readStatusesTask; + + // Collection will contain initial written message (ServiceUnknown) plus 5 queued messages + Assert.AreEqual(HealthServiceImpl.MaxStatusBufferSize + 1, statuses.Count); + + // Initial written message + Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, statuses[0]); + + // Last 5 queued messages + Assert.AreEqual((HealthCheckResponse.Types.ServingStatus)15, statuses[statuses.Count - 5]); + Assert.AreEqual((HealthCheckResponse.Types.ServingStatus)16, statuses[statuses.Count - 4]); + Assert.AreEqual((HealthCheckResponse.Types.ServingStatus)17, statuses[statuses.Count - 3]); + Assert.AreEqual((HealthCheckResponse.Types.ServingStatus)18, statuses[statuses.Count - 2]); + Assert.AreEqual((HealthCheckResponse.Types.ServingStatus)19, statuses[statuses.Count - 1]); + } +#endif + + private static HealthCheckResponse.Types.ServingStatus GetStatusHelper(HealthServiceImpl impl, string service) + { + return impl.Check(new HealthCheckRequest { Service = service }, null).Result.Status; + } + } +} diff --git a/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs b/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs new file mode 100644 index 00000000..db6d32a5 --- /dev/null +++ b/src/csharp/Grpc.HealthCheck.Tests/NUnitMain.cs @@ -0,0 +1,40 @@ +#region Copyright notice and license + +// Copyright 2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Reflection; +using Grpc.Core; +using Grpc.Core.Logging; +using NUnit.Common; +using NUnitLite; + +namespace Grpc.HealthCheck.Tests +{ + /// + /// Provides entry point for NUnitLite + /// + public class NUnitMain + { + public static int Main(string[] args) + { + // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. + GrpcEnvironment.SetLogger(new ConsoleLogger()); + return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args); + } + } +} diff --git a/src/csharp/Grpc.HealthCheck.Tests/Properties/AssemblyInfo.cs b/src/csharp/Grpc.HealthCheck.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..cf331716 --- /dev/null +++ b/src/csharp/Grpc.HealthCheck.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.HealthCheck.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.HealthCheck.Tests/TestResponseStreamWriter.cs b/src/csharp/Grpc.HealthCheck.Tests/TestResponseStreamWriter.cs new file mode 100644 index 00000000..a0b1a51c --- /dev/null +++ b/src/csharp/Grpc.HealthCheck.Tests/TestResponseStreamWriter.cs @@ -0,0 +1,72 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion + +#if GRPC_SUPPORT_WATCH +using System.Threading.Channels; +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Health.V1; + +namespace Grpc.HealthCheck.Tests +{ + internal class TestResponseStreamWriter : IServerStreamWriter + { + private readonly Channel _channel; + private readonly TaskCompletionSource _startTcs; + + public TestResponseStreamWriter(int maxCapacity = 1, bool started = true) + { + _channel = System.Threading.Channels.Channel.CreateBounded(new BoundedChannelOptions(maxCapacity) { + SingleReader = false, + SingleWriter = true, + FullMode = BoundedChannelFullMode.Wait + }); + if (!started) + { + _startTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + } + } + + public ChannelReader WrittenMessagesReader => _channel.Reader; + + public WriteOptions WriteOptions { get; set; } + + public async Task WriteAsync(HealthCheckResponse message) + { + if (_startTcs != null) + { + await _startTcs.Task; + } + + await _channel.Writer.WriteAsync(message); + } + + public void Start() + { + if (_startTcs != null) + { + _startTcs.TrySetResult(null); + } + } + + public void Complete() + { + _channel.Writer.Complete(); + } + } +} +#endif diff --git a/src/csharp/Grpc.HealthCheck.Tests/TestServerCallContext.cs b/src/csharp/Grpc.HealthCheck.Tests/TestServerCallContext.cs new file mode 100644 index 00000000..34a244c0 --- /dev/null +++ b/src/csharp/Grpc.HealthCheck.Tests/TestServerCallContext.cs @@ -0,0 +1,57 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion + +#if GRPC_SUPPORT_WATCH +using System; +using System.Threading; +using System.Threading.Tasks; + +using Grpc.Core; + +namespace Grpc.HealthCheck.Tests +{ + internal class TestServerCallContext : ServerCallContext + { + private readonly CancellationToken _cancellationToken; + + public TestServerCallContext(CancellationToken cancellationToken) + { + _cancellationToken = cancellationToken; + } + + protected override string MethodCore { get; } + protected override string HostCore { get; } + protected override string PeerCore { get; } + protected override DateTime DeadlineCore { get; } + protected override Metadata RequestHeadersCore { get; } + protected override CancellationToken CancellationTokenCore => _cancellationToken; + protected override Metadata ResponseTrailersCore { get; } + protected override Status StatusCore { get; set; } + protected override WriteOptions WriteOptionsCore { get; set; } + protected override AuthContext AuthContextCore { get; } + + protected override ContextPropagationToken CreatePropagationTokenCore(ContextPropagationOptions options) + { + throw new NotImplementedException(); + } + + protected override Task WriteResponseHeadersAsyncCore(Metadata responseHeaders) + { + throw new NotImplementedException(); + } + } +} +#endif diff --git a/src/csharp/Grpc.HealthCheck/Health.cs b/src/csharp/Grpc.HealthCheck/Health.cs new file mode 100644 index 00000000..2bc976f1 --- /dev/null +++ b/src/csharp/Grpc.HealthCheck/Health.cs @@ -0,0 +1,450 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: grpc/health/v1/health.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Health.V1 { + + /// Holder for reflection information generated from grpc/health/v1/health.proto + public static partial class HealthReflection { + + #region Descriptor + /// File descriptor for grpc/health/v1/health.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static HealthReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChtncnBjL2hlYWx0aC92MS9oZWFsdGgucHJvdG8SDmdycGMuaGVhbHRoLnYx", + "IiUKEkhlYWx0aENoZWNrUmVxdWVzdBIPCgdzZXJ2aWNlGAEgASgJIqkBChNI", + "ZWFsdGhDaGVja1Jlc3BvbnNlEkEKBnN0YXR1cxgBIAEoDjIxLmdycGMuaGVh", + "bHRoLnYxLkhlYWx0aENoZWNrUmVzcG9uc2UuU2VydmluZ1N0YXR1cyJPCg1T", + "ZXJ2aW5nU3RhdHVzEgsKB1VOS05PV04QABILCgdTRVJWSU5HEAESDwoLTk9U", + "X1NFUlZJTkcQAhITCg9TRVJWSUNFX1VOS05PV04QAzKuAQoGSGVhbHRoElAK", + "BUNoZWNrEiIuZ3JwYy5oZWFsdGgudjEuSGVhbHRoQ2hlY2tSZXF1ZXN0GiMu", + "Z3JwYy5oZWFsdGgudjEuSGVhbHRoQ2hlY2tSZXNwb25zZRJSCgVXYXRjaBIi", + "LmdycGMuaGVhbHRoLnYxLkhlYWx0aENoZWNrUmVxdWVzdBojLmdycGMuaGVh", + "bHRoLnYxLkhlYWx0aENoZWNrUmVzcG9uc2UwAUJhChFpby5ncnBjLmhlYWx0", + "aC52MUILSGVhbHRoUHJvdG9QAVosZ29vZ2xlLmdvbGFuZy5vcmcvZ3JwYy9o", + "ZWFsdGgvZ3JwY19oZWFsdGhfdjGqAg5HcnBjLkhlYWx0aC5WMWIGcHJvdG8z")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Health.V1.HealthCheckRequest), global::Grpc.Health.V1.HealthCheckRequest.Parser, new[]{ "Service" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Health.V1.HealthCheckResponse), global::Grpc.Health.V1.HealthCheckResponse.Parser, new[]{ "Status" }, null, new[]{ typeof(global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus) }, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class HealthCheckRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HealthCheckRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Health.V1.HealthReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public HealthCheckRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public HealthCheckRequest(HealthCheckRequest other) : this() { + service_ = other.service_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public HealthCheckRequest Clone() { + return new HealthCheckRequest(this); + } + + /// Field number for the "service" field. + public const int ServiceFieldNumber = 1; + private string service_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Service { + get { return service_; } + set { + service_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as HealthCheckRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(HealthCheckRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Service != other.Service) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Service.Length != 0) hash ^= Service.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Service.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Service); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Service.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Service); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Service.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Service); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(HealthCheckRequest other) { + if (other == null) { + return; + } + if (other.Service.Length != 0) { + Service = other.Service; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Service = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Service = input.ReadString(); + break; + } + } + } + } + #endif + + } + + public sealed partial class HealthCheckResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HealthCheckResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Health.V1.HealthReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public HealthCheckResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public HealthCheckResponse(HealthCheckResponse other) : this() { + status_ = other.status_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public HealthCheckResponse Clone() { + return new HealthCheckResponse(this); + } + + /// Field number for the "status" field. + public const int StatusFieldNumber = 1; + private global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus status_ = global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.Unknown; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus Status { + get { return status_; } + set { + status_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as HealthCheckResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(HealthCheckResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Status != other.Status) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Status != global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.Unknown) hash ^= Status.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Status != global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.Unknown) { + output.WriteRawTag(8); + output.WriteEnum((int) Status); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Status != global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.Unknown) { + output.WriteRawTag(8); + output.WriteEnum((int) Status); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Status != global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.Unknown) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Status); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(HealthCheckResponse other) { + if (other == null) { + return; + } + if (other.Status != global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus.Unknown) { + Status = other.Status; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Status = (global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus) input.ReadEnum(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Status = (global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus) input.ReadEnum(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the HealthCheckResponse message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static partial class Types { + public enum ServingStatus { + [pbr::OriginalName("UNKNOWN")] Unknown = 0, + [pbr::OriginalName("SERVING")] Serving = 1, + [pbr::OriginalName("NOT_SERVING")] NotServing = 2, + /// + /// Used only by the Watch method. + /// + [pbr::OriginalName("SERVICE_UNKNOWN")] ServiceUnknown = 3, + } + + } + #endregion + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs new file mode 100644 index 00000000..523f112a --- /dev/null +++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs @@ -0,0 +1,301 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: grpc/health/v1/health.proto +// +// Original file comments: +// Copyright 2015 The gRPC Authors +// +// 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. +// +// The canonical version of this proto can be found at +// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto +// +#pragma warning disable 0414, 1591 +#region Designer generated code + +using grpc = global::Grpc.Core; + +namespace Grpc.Health.V1 { + public static partial class Health + { + static readonly string __ServiceName = "grpc.health.v1.Health"; + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context) + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (message is global::Google.Protobuf.IBufferMessage) + { + context.SetPayloadLength(message.CalculateSize()); + global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter()); + context.Complete(); + return; + } + #endif + context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static class __Helper_MessageCache + { + public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static T __Helper_DeserializeMessage(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser parser) where T : global::Google.Protobuf.IMessage + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (__Helper_MessageCache.IsBufferMessage) + { + return parser.ParseFrom(context.PayloadAsReadOnlySequence()); + } + #endif + return parser.ParseFrom(context.PayloadAsNewBuffer()); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_health_v1_HealthCheckRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Health.V1.HealthCheckRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_health_v1_HealthCheckResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Health.V1.HealthCheckResponse.Parser)); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_Check = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "Check", + __Marshaller_grpc_health_v1_HealthCheckRequest, + __Marshaller_grpc_health_v1_HealthCheckResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_Watch = new grpc::Method( + grpc::MethodType.ServerStreaming, + __ServiceName, + "Watch", + __Marshaller_grpc_health_v1_HealthCheckRequest, + __Marshaller_grpc_health_v1_HealthCheckResponse); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Health.V1.HealthReflection.Descriptor.Services[0]; } + } + + /// Base class for server-side implementations of Health + [grpc::BindServiceMethod(typeof(Health), "BindService")] + public abstract partial class HealthBase + { + /// + /// If the requested service is unknown, the call will fail with status + /// NOT_FOUND. + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task Check(global::Grpc.Health.V1.HealthCheckRequest request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// Performs a watch for the serving status of the requested service. + /// The server will immediately send back a message indicating the current + /// serving status. It will then subsequently send a new message whenever + /// the service's serving status changes. + /// + /// If the requested service is unknown when the call is received, the + /// server will send a message setting the serving status to + /// SERVICE_UNKNOWN but will *not* terminate the call. If at some + /// future point, the serving status of the service becomes known, the + /// server will send a new message with the service's serving status. + /// + /// If the call terminates with status UNIMPLEMENTED, then clients + /// should assume this method is not supported and should not retry the + /// call. If the call terminates with any other status (including OK), + /// clients should retry the call with appropriate exponential backoff. + /// + /// The request received from the client. + /// Used for sending responses back to the client. + /// The context of the server-side call handler being invoked. + /// A task indicating completion of the handler. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task Watch(global::Grpc.Health.V1.HealthCheckRequest request, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for Health + public partial class HealthClient : grpc::ClientBase + { + /// Creates a new client for Health + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public HealthClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for Health that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public HealthClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected HealthClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected HealthClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// If the requested service is unknown, the call will fail with status + /// NOT_FOUND. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return Check(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// If the requested service is unknown, the call will fail with status + /// NOT_FOUND. + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_Check, null, options, request); + } + /// + /// If the requested service is unknown, the call will fail with status + /// NOT_FOUND. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return CheckAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// If the requested service is unknown, the call will fail with status + /// NOT_FOUND. + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_Check, null, options, request); + } + /// + /// Performs a watch for the serving status of the requested service. + /// The server will immediately send back a message indicating the current + /// serving status. It will then subsequently send a new message whenever + /// the service's serving status changes. + /// + /// If the requested service is unknown when the call is received, the + /// server will send a message setting the serving status to + /// SERVICE_UNKNOWN but will *not* terminate the call. If at some + /// future point, the serving status of the service becomes known, the + /// server will send a new message with the service's serving status. + /// + /// If the call terminates with status UNIMPLEMENTED, then clients + /// should assume this method is not supported and should not retry the + /// call. If the call terminates with any other status (including OK), + /// clients should retry the call with appropriate exponential backoff. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncServerStreamingCall Watch(global::Grpc.Health.V1.HealthCheckRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return Watch(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Performs a watch for the serving status of the requested service. + /// The server will immediately send back a message indicating the current + /// serving status. It will then subsequently send a new message whenever + /// the service's serving status changes. + /// + /// If the requested service is unknown when the call is received, the + /// server will send a message setting the serving status to + /// SERVICE_UNKNOWN but will *not* terminate the call. If at some + /// future point, the serving status of the service becomes known, the + /// server will send a new message with the service's serving status. + /// + /// If the call terminates with status UNIMPLEMENTED, then clients + /// should assume this method is not supported and should not retry the + /// call. If the call terminates with any other status (including OK), + /// clients should retry the call with appropriate exponential backoff. + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncServerStreamingCall Watch(global::Grpc.Health.V1.HealthCheckRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncServerStreamingCall(__Method_Watch, null, options, request); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override HealthClient NewInstance(ClientBaseConfiguration configuration) + { + return new HealthClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static grpc::ServerServiceDefinition BindService(HealthBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_Check, serviceImpl.Check) + .AddMethod(__Method_Watch, serviceImpl.Watch).Build(); + } + + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static void BindService(grpc::ServiceBinderBase serviceBinder, HealthBase serviceImpl) + { + serviceBinder.AddMethod(__Method_Check, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.Check)); + serviceBinder.AddMethod(__Method_Watch, serviceImpl == null ? null : new grpc::ServerStreamingServerMethod(serviceImpl.Watch)); + } + + } +} +#endregion diff --git a/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs new file mode 100644 index 00000000..8ff95552 --- /dev/null +++ b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs @@ -0,0 +1,277 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +#if GRPC_SUPPORT_WATCH +using System.Threading.Channels; +#endif +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Health.V1; + +namespace Grpc.HealthCheck +{ + /// + /// Implementation of a simple Health service. Useful for health checking. + /// + /// Registering service with a server: + /// + /// var serviceImpl = new HealthServiceImpl(); + /// server = new Server(); + /// server.AddServiceDefinition(Grpc.Health.V1.Health.BindService(serviceImpl)); + /// + /// + public class HealthServiceImpl : Grpc.Health.V1.Health.HealthBase + { + // The maximum number of statuses to buffer on the server. + internal const int MaxStatusBufferSize = 5; + + private readonly object statusLock = new object(); + private readonly Dictionary statusMap = + new Dictionary(); + +#if GRPC_SUPPORT_WATCH + private readonly object watchersLock = new object(); + private readonly Dictionary>> watchers = + new Dictionary>>(); +#endif + + /// + /// Sets the health status for given service. + /// + /// The service. Cannot be null. + /// the health status + public void SetStatus(string service, HealthCheckResponse.Types.ServingStatus status) + { + HealthCheckResponse.Types.ServingStatus previousStatus; + lock (statusLock) + { + previousStatus = GetServiceStatus(service); + statusMap[service] = status; + } + +#if GRPC_SUPPORT_WATCH + if (status != previousStatus) + { + NotifyStatus(service, status); + } +#endif + } + + /// + /// Clears health status for given service. + /// + /// The service. Cannot be null. + public void ClearStatus(string service) + { + HealthCheckResponse.Types.ServingStatus previousStatus; + lock (statusLock) + { + previousStatus = GetServiceStatus(service); + statusMap.Remove(service); + } + +#if GRPC_SUPPORT_WATCH + if (previousStatus != HealthCheckResponse.Types.ServingStatus.ServiceUnknown) + { + NotifyStatus(service, HealthCheckResponse.Types.ServingStatus.ServiceUnknown); + } +#endif + } + + /// + /// Clears statuses for all services. + /// + public void ClearAll() + { + List> statuses; + lock (statusLock) + { + statuses = statusMap.ToList(); + statusMap.Clear(); + } + +#if GRPC_SUPPORT_WATCH + foreach (KeyValuePair status in statuses) + { + if (status.Value != HealthCheckResponse.Types.ServingStatus.ServiceUnknown) + { + NotifyStatus(status.Key, HealthCheckResponse.Types.ServingStatus.ServiceUnknown); + } + } +#endif + } + + /// + /// Performs a health status check. + /// + /// The check request. + /// The call context. + /// The asynchronous response. + public override Task Check(HealthCheckRequest request, ServerCallContext context) + { + HealthCheckResponse response = GetHealthCheckResponse(request.Service, throwOnNotFound: true); + + return Task.FromResult(response); + } + +#if GRPC_SUPPORT_WATCH + /// + /// Performs a watch for the serving status of the requested service. + /// The server will immediately send back a message indicating the current + /// serving status. It will then subsequently send a new message whenever + /// the service's serving status changes. + /// + /// If the requested service is unknown when the call is received, the + /// server will send a message setting the serving status to + /// SERVICE_UNKNOWN but will *not* terminate the call. If at some + /// future point, the serving status of the service becomes known, the + /// server will send a new message with the service's serving status. + /// + /// If the call terminates with status UNIMPLEMENTED, then clients + /// should assume this method is not supported and should not retry the + /// call. If the call terminates with any other status (including OK), + /// clients should retry the call with appropriate exponential backoff. + /// + /// The request received from the client. + /// Used for sending responses back to the client. + /// The context of the server-side call handler being invoked. + /// A task indicating completion of the handler. + public override async Task Watch(HealthCheckRequest request, IServerStreamWriter responseStream, ServerCallContext context) + { + string service = request.Service; + + // Channel is used to to marshall multiple callers updating status into a single queue. + // This is required because IServerStreamWriter is not thread safe. + // + // A queue of unwritten statuses could build up if flow control causes responseStream.WriteAsync to await. + // When this number is exceeded the server will discard older statuses. The discarded intermediate statues + // will never be sent to the client. + Channel channel = Channel.CreateBounded(new BoundedChannelOptions(capacity: MaxStatusBufferSize) { + SingleReader = true, + SingleWriter = false, + FullMode = BoundedChannelFullMode.DropOldest + }); + + lock (watchersLock) + { + if (!watchers.TryGetValue(service, out List> channelWriters)) + { + channelWriters = new List>(); + watchers.Add(service, channelWriters); + } + + channelWriters.Add(channel.Writer); + } + + // Watch calls run until ended by the client canceling them. + context.CancellationToken.Register(() => { + lock (watchersLock) + { + if (watchers.TryGetValue(service, out List> channelWriters)) + { + // Remove the writer from the watchers + if (channelWriters.Remove(channel.Writer)) + { + // Remove empty collection if service has no more response streams + if (channelWriters.Count == 0) + { + watchers.Remove(service); + } + } + } + } + + // Signal the writer is complete and the watch method can exit. + channel.Writer.Complete(); + }); + + // Send current status immediately + HealthCheckResponse response = GetHealthCheckResponse(service, throwOnNotFound: false); + await responseStream.WriteAsync(response); + + // Read messages. WaitToReadAsync will wait until new messages are available. + // Loop will exit when the call is canceled and the writer is marked as complete. + while (await channel.Reader.WaitToReadAsync()) + { + if (channel.Reader.TryRead(out HealthCheckResponse item)) + { + await responseStream.WriteAsync(item); + } + } + } + + private void NotifyStatus(string service, HealthCheckResponse.Types.ServingStatus status) + { + lock (watchersLock) + { + if (watchers.TryGetValue(service, out List> channelWriters)) + { + HealthCheckResponse response = new HealthCheckResponse { Status = status }; + + foreach (ChannelWriter writer in channelWriters) + { + if (!writer.TryWrite(response)) + { + throw new InvalidOperationException("Unable to queue health check notification."); + } + } + } + } + } +#endif + + private HealthCheckResponse GetHealthCheckResponse(string service, bool throwOnNotFound) + { + HealthCheckResponse response = null; + lock (statusLock) + { + HealthCheckResponse.Types.ServingStatus status; + if (!statusMap.TryGetValue(service, out status)) + { + if (throwOnNotFound) + { + // TODO(jtattermusch): returning specific status from server handler is not supported yet. + throw new RpcException(new Status(StatusCode.NotFound, "")); + } + else + { + status = HealthCheckResponse.Types.ServingStatus.ServiceUnknown; + } + } + response = new HealthCheckResponse { Status = status }; + } + + return response; + } + + private HealthCheckResponse.Types.ServingStatus GetServiceStatus(string service) + { + if (statusMap.TryGetValue(service, out HealthCheckResponse.Types.ServingStatus s)) + { + return s; + } + else + { + // A service with no set status has a status of ServiceUnknown + return HealthCheckResponse.Types.ServingStatus.ServiceUnknown; + } + } + } +} diff --git a/src/csharp/Grpc.HealthCheck/Properties/AssemblyInfo.cs b/src/csharp/Grpc.HealthCheck/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..73895fd8 --- /dev/null +++ b/src/csharp/Grpc.HealthCheck/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.HealthCheck")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: InternalsVisibleTo("Grpc.HealthCheck.Tests,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] diff --git a/src/csharp/Grpc.IntegrationTesting.Client/Program.cs b/src/csharp/Grpc.IntegrationTesting.Client/Program.cs new file mode 100644 index 00000000..faf4eeee --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting.Client/Program.cs @@ -0,0 +1,31 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.IntegrationTesting; + +namespace Grpc.IntegrationTesting.Client +{ + class Program + { + public static void Main(string[] args) + { + InteropClient.Run(args); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..35c8c673 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.IntegrationTesting.Client")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/Program.cs b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Program.cs new file mode 100644 index 00000000..e0fba11a --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Program.cs @@ -0,0 +1,31 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.IntegrationTesting; + +namespace Grpc.IntegrationTesting +{ + class Program + { + public static void Main(string[] args) + { + QpsWorker.Run(args); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..616245ba --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.IntegrationTesting.QpsWorker")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.IntegrationTesting.Server/Program.cs b/src/csharp/Grpc.IntegrationTesting.Server/Program.cs new file mode 100644 index 00000000..6a618c52 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting.Server/Program.cs @@ -0,0 +1,30 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; + +namespace Grpc.IntegrationTesting.Server +{ + class Program + { + public static void Main(string[] args) + { + InteropServer.Run(args); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..41953fec --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.IntegrationTesting.Server")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/Program.cs b/src/csharp/Grpc.IntegrationTesting.StressClient/Program.cs new file mode 100644 index 00000000..0364a1c1 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting.StressClient/Program.cs @@ -0,0 +1,30 @@ +#region Copyright notice and license + +// Copyright 2016 gRPC authors. +// +// 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. + +#endregion + +using System; + +namespace Grpc.IntegrationTesting.StressClient +{ + class MainClass + { + public static void Main(string[] args) + { + StressTestClient.Run(args); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.StressClient/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..455ab4d0 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting.StressClient/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.IntegrationTesting.StressClient")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.IntegrationTesting.XdsClient/Program.cs b/src/csharp/Grpc.IntegrationTesting.XdsClient/Program.cs new file mode 100644 index 00000000..19214439 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting.XdsClient/Program.cs @@ -0,0 +1,31 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.IntegrationTesting; + +namespace Grpc.IntegrationTesting.XdsClient +{ + class Program + { + public static void Main(string[] args) + { + XdsInteropClient.Run(args); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting.XdsClient/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.XdsClient/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..80289be1 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting.XdsClient/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.IntegrationTesting.XdsClient")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkService.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkService.cs new file mode 100644 index 00000000..e33fd69c --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkService.cs @@ -0,0 +1,48 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/benchmark_service.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Testing { + + /// Holder for reflection information generated from src/proto/grpc/testing/benchmark_service.proto + public static partial class BenchmarkServiceReflection { + + #region Descriptor + /// File descriptor for src/proto/grpc/testing/benchmark_service.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static BenchmarkServiceReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Ci5zcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2JlbmNobWFya19zZXJ2aWNlLnBy", + "b3RvEgxncnBjLnRlc3RpbmcaJXNyYy9wcm90by9ncnBjL3Rlc3RpbmcvbWVz", + "c2FnZXMucHJvdG8ypgMKEEJlbmNobWFya1NlcnZpY2USRgoJVW5hcnlDYWxs", + "EhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlcXVlc3QaHC5ncnBjLnRlc3Rpbmcu", + "U2ltcGxlUmVzcG9uc2USTgoNU3RyZWFtaW5nQ2FsbBIbLmdycGMudGVzdGlu", + "Zy5TaW1wbGVSZXF1ZXN0GhwuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlc3BvbnNl", + "KAEwARJSChNTdHJlYW1pbmdGcm9tQ2xpZW50EhsuZ3JwYy50ZXN0aW5nLlNp", + "bXBsZVJlcXVlc3QaHC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9uc2UoARJS", + "ChNTdHJlYW1pbmdGcm9tU2VydmVyEhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJl", + "cXVlc3QaHC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9uc2UwARJSChFTdHJl", + "YW1pbmdCb3RoV2F5cxIbLmdycGMudGVzdGluZy5TaW1wbGVSZXF1ZXN0Ghwu", + "Z3JwYy50ZXN0aW5nLlNpbXBsZVJlc3BvbnNlKAEwAWIGcHJvdG8z")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Grpc.Testing.MessagesReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, null, null)); + } + #endregion + + } +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs new file mode 100644 index 00000000..d39cb5bd --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs @@ -0,0 +1,407 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/benchmark_service.proto +// +// Original file comments: +// Copyright 2015 gRPC authors. +// +// 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. +// +// An integration test service that covers all the method signature permutations +// of unary/streaming requests/responses. +#pragma warning disable 0414, 1591 +#region Designer generated code + +using grpc = global::Grpc.Core; + +namespace Grpc.Testing { + public static partial class BenchmarkService + { + static readonly string __ServiceName = "grpc.testing.BenchmarkService"; + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context) + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (message is global::Google.Protobuf.IBufferMessage) + { + context.SetPayloadLength(message.CalculateSize()); + global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter()); + context.Complete(); + return; + } + #endif + context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static class __Helper_MessageCache + { + public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static T __Helper_DeserializeMessage(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser parser) where T : global::Google.Protobuf.IMessage + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (__Helper_MessageCache.IsBufferMessage) + { + return parser.ParseFrom(context.PayloadAsReadOnlySequence()); + } + #endif + return parser.ParseFrom(context.PayloadAsNewBuffer()); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_SimpleRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.SimpleRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_SimpleResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.SimpleResponse.Parser)); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_UnaryCall = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "UnaryCall", + __Marshaller_grpc_testing_SimpleRequest, + __Marshaller_grpc_testing_SimpleResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_StreamingCall = new grpc::Method( + grpc::MethodType.DuplexStreaming, + __ServiceName, + "StreamingCall", + __Marshaller_grpc_testing_SimpleRequest, + __Marshaller_grpc_testing_SimpleResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_StreamingFromClient = new grpc::Method( + grpc::MethodType.ClientStreaming, + __ServiceName, + "StreamingFromClient", + __Marshaller_grpc_testing_SimpleRequest, + __Marshaller_grpc_testing_SimpleResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_StreamingFromServer = new grpc::Method( + grpc::MethodType.ServerStreaming, + __ServiceName, + "StreamingFromServer", + __Marshaller_grpc_testing_SimpleRequest, + __Marshaller_grpc_testing_SimpleResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_StreamingBothWays = new grpc::Method( + grpc::MethodType.DuplexStreaming, + __ServiceName, + "StreamingBothWays", + __Marshaller_grpc_testing_SimpleRequest, + __Marshaller_grpc_testing_SimpleResponse); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Testing.BenchmarkServiceReflection.Descriptor.Services[0]; } + } + + /// Base class for server-side implementations of BenchmarkService + [grpc::BindServiceMethod(typeof(BenchmarkService), "BindService")] + public abstract partial class BenchmarkServiceBase + { + /// + /// One request followed by one response. + /// The server returns the client payload as-is. + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// Repeated sequence of one request followed by one response. + /// Should be called streaming ping-pong + /// The server returns the client payload as-is on each response + /// + /// Used for reading requests from the client. + /// Used for sending responses back to the client. + /// The context of the server-side call handler being invoked. + /// A task indicating completion of the handler. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task StreamingCall(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// Single-sided unbounded streaming from client to server + /// The server returns the client payload as-is once the client does WritesDone + /// + /// Used for reading requests from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task StreamingFromClient(grpc::IAsyncStreamReader requestStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// Single-sided unbounded streaming from server to client + /// The server repeatedly returns the client payload as-is + /// + /// The request received from the client. + /// Used for sending responses back to the client. + /// The context of the server-side call handler being invoked. + /// A task indicating completion of the handler. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task StreamingFromServer(global::Grpc.Testing.SimpleRequest request, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// Two-sided unbounded streaming between server to client + /// Both sides send the content of their own choice to the other + /// + /// Used for reading requests from the client. + /// Used for sending responses back to the client. + /// The context of the server-side call handler being invoked. + /// A task indicating completion of the handler. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task StreamingBothWays(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for BenchmarkService + public partial class BenchmarkServiceClient : grpc::ClientBase + { + /// Creates a new client for BenchmarkService + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public BenchmarkServiceClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for BenchmarkService that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public BenchmarkServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected BenchmarkServiceClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected BenchmarkServiceClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// One request followed by one response. + /// The server returns the client payload as-is. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return UnaryCall(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// One request followed by one response. + /// The server returns the client payload as-is. + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request); + } + /// + /// One request followed by one response. + /// The server returns the client payload as-is. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return UnaryCallAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// One request followed by one response. + /// The server returns the client payload as-is. + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request); + } + /// + /// Repeated sequence of one request followed by one response. + /// Should be called streaming ping-pong + /// The server returns the client payload as-is on each response + /// + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall StreamingCall(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return StreamingCall(new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Repeated sequence of one request followed by one response. + /// Should be called streaming ping-pong + /// The server returns the client payload as-is on each response + /// + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall StreamingCall(grpc::CallOptions options) + { + return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingCall, null, options); + } + /// + /// Single-sided unbounded streaming from client to server + /// The server returns the client payload as-is once the client does WritesDone + /// + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncClientStreamingCall StreamingFromClient(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return StreamingFromClient(new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Single-sided unbounded streaming from client to server + /// The server returns the client payload as-is once the client does WritesDone + /// + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncClientStreamingCall StreamingFromClient(grpc::CallOptions options) + { + return CallInvoker.AsyncClientStreamingCall(__Method_StreamingFromClient, null, options); + } + /// + /// Single-sided unbounded streaming from server to client + /// The server repeatedly returns the client payload as-is + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncServerStreamingCall StreamingFromServer(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return StreamingFromServer(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Single-sided unbounded streaming from server to client + /// The server repeatedly returns the client payload as-is + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncServerStreamingCall StreamingFromServer(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncServerStreamingCall(__Method_StreamingFromServer, null, options, request); + } + /// + /// Two-sided unbounded streaming between server to client + /// Both sides send the content of their own choice to the other + /// + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall StreamingBothWays(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return StreamingBothWays(new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Two-sided unbounded streaming between server to client + /// Both sides send the content of their own choice to the other + /// + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall StreamingBothWays(grpc::CallOptions options) + { + return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingBothWays, null, options); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override BenchmarkServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new BenchmarkServiceClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static grpc::ServerServiceDefinition BindService(BenchmarkServiceBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall) + .AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall) + .AddMethod(__Method_StreamingFromClient, serviceImpl.StreamingFromClient) + .AddMethod(__Method_StreamingFromServer, serviceImpl.StreamingFromServer) + .AddMethod(__Method_StreamingBothWays, serviceImpl.StreamingBothWays).Build(); + } + + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static void BindService(grpc::ServiceBinderBase serviceBinder, BenchmarkServiceBase serviceImpl) + { + serviceBinder.AddMethod(__Method_UnaryCall, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.UnaryCall)); + serviceBinder.AddMethod(__Method_StreamingCall, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.StreamingCall)); + serviceBinder.AddMethod(__Method_StreamingFromClient, serviceImpl == null ? null : new grpc::ClientStreamingServerMethod(serviceImpl.StreamingFromClient)); + serviceBinder.AddMethod(__Method_StreamingFromServer, serviceImpl == null ? null : new grpc::ServerStreamingServerMethod(serviceImpl.StreamingFromServer)); + serviceBinder.AddMethod(__Method_StreamingBothWays, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.StreamingBothWays)); + } + + } +} +#endregion diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs new file mode 100644 index 00000000..4ebd294d --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs @@ -0,0 +1,58 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Google.Protobuf; +using Grpc.Core; +using Grpc.Core.Utils; + +namespace Grpc.Testing +{ + /// + /// Implementation of BenchmarkService server + /// + public class BenchmarkServiceImpl : BenchmarkService.BenchmarkServiceBase + { + public BenchmarkServiceImpl() + { + } + + public override Task UnaryCall(SimpleRequest request, ServerCallContext context) + { + var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) }; + return Task.FromResult(response); + } + + public override async Task StreamingCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + { + await requestStream.ForEachAsync(async request => + { + var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) }; + await responseStream.WriteAsync(response); + }); + } + + private static Payload CreateZerosPayload(int size) + { + return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs new file mode 100644 index 00000000..9d41d344 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs @@ -0,0 +1,364 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Google.Protobuf; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Logging; +using Grpc.Core.Profiling; +using Grpc.Core.Utils; +using NUnit.Framework; +using Grpc.Testing; + +namespace Grpc.IntegrationTesting +{ + /// + /// Helper methods to start client runners for performance testing. + /// + public class ClientRunners + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + + // Profilers to use for clients. + static readonly BlockingCollection profilers = new BlockingCollection(); + + internal static void AddProfiler(BasicProfiler profiler) + { + GrpcPreconditions.CheckNotNull(profiler); + profilers.Add(profiler); + } + + /// + /// Creates a started client runner. + /// + public static IClientRunner CreateStarted(ClientConfig config) + { + Logger.Debug("ClientConfig: {0}", config); + + if (config.AsyncClientThreads != 0) + { + Logger.Warning("ClientConfig.AsyncClientThreads is not supported for C#. Ignoring the value"); + } + if (config.CoreLimit != 0) + { + Logger.Warning("ClientConfig.CoreLimit is not supported for C#. Ignoring the value"); + } + if (config.CoreList.Count > 0) + { + Logger.Warning("ClientConfig.CoreList is not supported for C#. Ignoring the value"); + } + + var channels = CreateChannels(config.ClientChannels, config.ServerTargets, config.SecurityParams, config.ChannelArgs); + + return new ClientRunnerImpl(channels, + config.ClientType, + config.RpcType, + config.OutstandingRpcsPerChannel, + config.LoadParams, + config.PayloadConfig, + config.HistogramParams, + () => GetNextProfiler()); + } + + private static List CreateChannels(int clientChannels, IEnumerable serverTargets, SecurityParams securityParams, IEnumerable channelArguments) + { + GrpcPreconditions.CheckArgument(clientChannels > 0, "clientChannels needs to be at least 1."); + GrpcPreconditions.CheckArgument(serverTargets.Count() > 0, "at least one serverTarget needs to be specified."); + + var credentials = securityParams != null ? TestCredentials.CreateSslCredentials() : ChannelCredentials.Insecure; + var channelOptions = new List(); + if (securityParams != null && securityParams.ServerHostOverride != "") + { + channelOptions.Add(new ChannelOption(ChannelOptions.SslTargetNameOverride, securityParams.ServerHostOverride)); + } + foreach (var channelArgument in channelArguments) + { + channelOptions.Add(channelArgument.ToChannelOption()); + } + + var result = new List(); + for (int i = 0; i < clientChannels; i++) + { + var target = serverTargets.ElementAt(i % serverTargets.Count()); + var channel = new Channel(target, credentials, channelOptions); + result.Add(channel); + } + return result; + } + + private static BasicProfiler GetNextProfiler() + { + BasicProfiler result = null; + profilers.TryTake(out result); + return result; + } + } + + internal class ClientRunnerImpl : IClientRunner + { + const double SecondsToNanos = 1e9; + + readonly List channels; + readonly ClientType clientType; + readonly RpcType rpcType; + readonly PayloadConfig payloadConfig; + readonly Lazy cachedByteBufferRequest; + readonly ThreadLocal threadLocalHistogram; + + readonly List runnerTasks; + readonly CancellationTokenSource stoppedCts = new CancellationTokenSource(); + readonly TimeStats timeStats = new TimeStats(); + readonly AtomicCounter statsResetCount = new AtomicCounter(); + + public ClientRunnerImpl(List channels, ClientType clientType, RpcType rpcType, int outstandingRpcsPerChannel, LoadParams loadParams, PayloadConfig payloadConfig, HistogramParams histogramParams, Func profilerFactory) + { + GrpcPreconditions.CheckArgument(outstandingRpcsPerChannel > 0, "outstandingRpcsPerChannel"); + GrpcPreconditions.CheckNotNull(histogramParams, "histogramParams"); + this.channels = new List(channels); + this.clientType = clientType; + this.rpcType = rpcType; + this.payloadConfig = payloadConfig; + this.cachedByteBufferRequest = new Lazy(() => new byte[payloadConfig.BytebufParams.ReqSize]); + this.threadLocalHistogram = new ThreadLocal(() => new Histogram(histogramParams.Resolution, histogramParams.MaxPossible), true); + + this.runnerTasks = new List(); + foreach (var channel in this.channels) + { + for (int i = 0; i < outstandingRpcsPerChannel; i++) + { + var timer = CreateTimer(loadParams, 1.0 / this.channels.Count / outstandingRpcsPerChannel); + var optionalProfiler = profilerFactory(); + this.runnerTasks.Add(RunClientAsync(channel, timer, optionalProfiler)); + } + } + } + + public ClientStats GetStats(bool reset) + { + var histogramData = new HistogramData(); + foreach (var hist in threadLocalHistogram.Values) + { + hist.GetSnapshot(histogramData, reset); + } + + var timeSnapshot = timeStats.GetSnapshot(reset); + + if (reset) + { + statsResetCount.Increment(); + } + + GrpcEnvironment.Logger.Info("[ClientRunnerImpl.GetStats] GC collection counts: gen0 {0}, gen1 {1}, gen2 {2}, (histogram reset count:{3}, seconds since reset: {4})", + GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2), statsResetCount.Count, timeSnapshot.WallClockTime.TotalSeconds); + + return new ClientStats + { + Latencies = histogramData, + TimeElapsed = timeSnapshot.WallClockTime.TotalSeconds, + TimeUser = timeSnapshot.UserProcessorTime.TotalSeconds, + TimeSystem = timeSnapshot.PrivilegedProcessorTime.TotalSeconds + }; + } + + public async Task StopAsync() + { + stoppedCts.Cancel(); + foreach (var runnerTask in runnerTasks) + { + await runnerTask; + } + foreach (var channel in channels) + { + await channel.ShutdownAsync(); + } + } + + private void RunUnary(Channel channel, IInterarrivalTimer timer, BasicProfiler optionalProfiler) + { + if (optionalProfiler != null) + { + Profilers.SetForCurrentThread(optionalProfiler); + } + + bool profilerReset = false; + + var client = new BenchmarkService.BenchmarkServiceClient(channel); + var request = CreateSimpleRequest(); + var stopwatch = new Stopwatch(); + + while (!stoppedCts.Token.IsCancellationRequested) + { + // after the first stats reset, also reset the profiler. + if (optionalProfiler != null && !profilerReset && statsResetCount.Count > 0) + { + optionalProfiler.Reset(); + profilerReset = true; + } + + stopwatch.Restart(); + client.UnaryCall(request); + stopwatch.Stop(); + + // spec requires data point in nanoseconds. + threadLocalHistogram.Value.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos); + + timer.WaitForNext(); + } + } + + private async Task RunUnaryAsync(Channel channel, IInterarrivalTimer timer) + { + var client = new BenchmarkService.BenchmarkServiceClient(channel); + var request = CreateSimpleRequest(); + var stopwatch = new Stopwatch(); + + while (!stoppedCts.Token.IsCancellationRequested) + { + stopwatch.Restart(); + await client.UnaryCallAsync(request); + stopwatch.Stop(); + + // spec requires data point in nanoseconds. + threadLocalHistogram.Value.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos); + + await timer.WaitForNextAsync(); + } + } + + private async Task RunStreamingPingPongAsync(Channel channel, IInterarrivalTimer timer) + { + var client = new BenchmarkService.BenchmarkServiceClient(channel); + var request = CreateSimpleRequest(); + var stopwatch = new Stopwatch(); + + using (var call = client.StreamingCall()) + { + while (!stoppedCts.Token.IsCancellationRequested) + { + stopwatch.Restart(); + await call.RequestStream.WriteAsync(request); + await call.ResponseStream.MoveNext(); + stopwatch.Stop(); + + // spec requires data point in nanoseconds. + threadLocalHistogram.Value.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos); + + await timer.WaitForNextAsync(); + } + + // finish the streaming call + await call.RequestStream.CompleteAsync(); + Assert.IsFalse(await call.ResponseStream.MoveNext()); + } + } + + private async Task RunGenericStreamingAsync(Channel channel, IInterarrivalTimer timer) + { + var request = cachedByteBufferRequest.Value; + var stopwatch = new Stopwatch(); + + var callDetails = new CallInvocationDetails(channel, GenericService.StreamingCallMethod, new CallOptions()); + + using (var call = Calls.AsyncDuplexStreamingCall(callDetails)) + { + while (!stoppedCts.Token.IsCancellationRequested) + { + stopwatch.Restart(); + await call.RequestStream.WriteAsync(request); + await call.ResponseStream.MoveNext(); + stopwatch.Stop(); + + // spec requires data point in nanoseconds. + threadLocalHistogram.Value.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos); + + await timer.WaitForNextAsync(); + } + + // finish the streaming call + await call.RequestStream.CompleteAsync(); + Assert.IsFalse(await call.ResponseStream.MoveNext()); + } + } + + private Task RunClientAsync(Channel channel, IInterarrivalTimer timer, BasicProfiler optionalProfiler) + { + if (payloadConfig.PayloadCase == PayloadConfig.PayloadOneofCase.BytebufParams) + { + GrpcPreconditions.CheckArgument(clientType == ClientType.AsyncClient, "Generic client only supports async API"); + GrpcPreconditions.CheckArgument(rpcType == RpcType.Streaming, "Generic client only supports streaming calls"); + return RunGenericStreamingAsync(channel, timer); + } + + GrpcPreconditions.CheckNotNull(payloadConfig.SimpleParams); + if (clientType == ClientType.SyncClient) + { + GrpcPreconditions.CheckArgument(rpcType == RpcType.Unary, "Sync client can only be used for Unary calls in C#"); + // create a dedicated thread for the synchronous client + return Task.Factory.StartNew(() => RunUnary(channel, timer, optionalProfiler), TaskCreationOptions.LongRunning); + } + else if (clientType == ClientType.AsyncClient) + { + switch (rpcType) + { + case RpcType.Unary: + return RunUnaryAsync(channel, timer); + case RpcType.Streaming: + return RunStreamingPingPongAsync(channel, timer); + } + } + throw new ArgumentException("Unsupported configuration."); + } + + private SimpleRequest CreateSimpleRequest() + { + GrpcPreconditions.CheckNotNull(payloadConfig.SimpleParams); + return new SimpleRequest + { + Payload = CreateZerosPayload(payloadConfig.SimpleParams.ReqSize), + ResponseSize = payloadConfig.SimpleParams.RespSize + }; + } + + private static Payload CreateZerosPayload(int size) + { + return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; + } + + private static IInterarrivalTimer CreateTimer(LoadParams loadParams, double loadMultiplier) + { + switch (loadParams.LoadCase) + { + case LoadParams.LoadOneofCase.ClosedLoop: + return new ClosedLoopInterarrivalTimer(); + case LoadParams.LoadOneofCase.Poisson: + return new PoissonInterarrivalTimer(loadParams.Poisson.OfferedLoad * loadMultiplier); + default: + throw new ArgumentException("Unknown load type"); + } + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/Control.cs b/src/csharp/Grpc.IntegrationTesting/Control.cs new file mode 100644 index 00000000..1837bc81 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/Control.cs @@ -0,0 +1,6647 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/control.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Testing { + + /// Holder for reflection information generated from src/proto/grpc/testing/control.proto + public static partial class ControlReflection { + + #region Descriptor + /// File descriptor for src/proto/grpc/testing/control.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static ControlReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CiRzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2NvbnRyb2wucHJvdG8SDGdycGMu", + "dGVzdGluZxolc3JjL3Byb3RvL2dycGMvdGVzdGluZy9wYXlsb2Fkcy5wcm90", + "bxoic3JjL3Byb3RvL2dycGMvdGVzdGluZy9zdGF0cy5wcm90byIlCg1Qb2lz", + "c29uUGFyYW1zEhQKDG9mZmVyZWRfbG9hZBgBIAEoASISChBDbG9zZWRMb29w", + "UGFyYW1zInsKCkxvYWRQYXJhbXMSNQoLY2xvc2VkX2xvb3AYASABKAsyHi5n", + "cnBjLnRlc3RpbmcuQ2xvc2VkTG9vcFBhcmFtc0gAEi4KB3BvaXNzb24YAiAB", + "KAsyGy5ncnBjLnRlc3RpbmcuUG9pc3NvblBhcmFtc0gAQgYKBGxvYWQiVgoO", + "U2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2VydmVy", + "X2hvc3Rfb3ZlcnJpZGUYAiABKAkSEQoJY3JlZF90eXBlGAMgASgJIk0KCkNo", + "YW5uZWxBcmcSDAoEbmFtZRgBIAEoCRITCglzdHJfdmFsdWUYAiABKAlIABIT", + "CglpbnRfdmFsdWUYAyABKAVIAEIHCgV2YWx1ZSK8BQoMQ2xpZW50Q29uZmln", + "EhYKDnNlcnZlcl90YXJnZXRzGAEgAygJEi0KC2NsaWVudF90eXBlGAIgASgO", + "MhguZ3JwYy50ZXN0aW5nLkNsaWVudFR5cGUSNQoPc2VjdXJpdHlfcGFyYW1z", + "GAMgASgLMhwuZ3JwYy50ZXN0aW5nLlNlY3VyaXR5UGFyYW1zEiQKHG91dHN0", + "YW5kaW5nX3JwY3NfcGVyX2NoYW5uZWwYBCABKAUSFwoPY2xpZW50X2NoYW5u", + "ZWxzGAUgASgFEhwKFGFzeW5jX2NsaWVudF90aHJlYWRzGAcgASgFEicKCHJw", + "Y190eXBlGAggASgOMhUuZ3JwYy50ZXN0aW5nLlJwY1R5cGUSLQoLbG9hZF9w", + "YXJhbXMYCiABKAsyGC5ncnBjLnRlc3RpbmcuTG9hZFBhcmFtcxIzCg5wYXls", + "b2FkX2NvbmZpZxgLIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmln", + "EjcKEGhpc3RvZ3JhbV9wYXJhbXMYDCABKAsyHS5ncnBjLnRlc3RpbmcuSGlz", + "dG9ncmFtUGFyYW1zEhEKCWNvcmVfbGlzdBgNIAMoBRISCgpjb3JlX2xpbWl0", + "GA4gASgFEhgKEG90aGVyX2NsaWVudF9hcGkYDyABKAkSLgoMY2hhbm5lbF9h", + "cmdzGBAgAygLMhguZ3JwYy50ZXN0aW5nLkNoYW5uZWxBcmcSFgoOdGhyZWFk", + "c19wZXJfY3EYESABKAUSGwoTbWVzc2FnZXNfcGVyX3N0cmVhbRgSIAEoBRIY", + "ChB1c2VfY29hbGVzY2VfYXBpGBMgASgIEjEKKW1lZGlhbl9sYXRlbmN5X2Nv", + "bGxlY3Rpb25faW50ZXJ2YWxfbWlsbGlzGBQgASgFEhgKEGNsaWVudF9wcm9j", + "ZXNzZXMYFSABKAUiOAoMQ2xpZW50U3RhdHVzEigKBXN0YXRzGAEgASgLMhku", + "Z3JwYy50ZXN0aW5nLkNsaWVudFN0YXRzIhUKBE1hcmsSDQoFcmVzZXQYASAB", + "KAgiaAoKQ2xpZW50QXJncxIrCgVzZXR1cBgBIAEoCzIaLmdycGMudGVzdGlu", + "Zy5DbGllbnRDb25maWdIABIiCgRtYXJrGAIgASgLMhIuZ3JwYy50ZXN0aW5n", + "Lk1hcmtIAEIJCgdhcmd0eXBlIpcDCgxTZXJ2ZXJDb25maWcSLQoLc2VydmVy", + "X3R5cGUYASABKA4yGC5ncnBjLnRlc3RpbmcuU2VydmVyVHlwZRI1Cg9zZWN1", + "cml0eV9wYXJhbXMYAiABKAsyHC5ncnBjLnRlc3RpbmcuU2VjdXJpdHlQYXJh", + "bXMSDAoEcG9ydBgEIAEoBRIcChRhc3luY19zZXJ2ZXJfdGhyZWFkcxgHIAEo", + "BRISCgpjb3JlX2xpbWl0GAggASgFEjMKDnBheWxvYWRfY29uZmlnGAkgASgL", + "MhsuZ3JwYy50ZXN0aW5nLlBheWxvYWRDb25maWcSEQoJY29yZV9saXN0GAog", + "AygFEhgKEG90aGVyX3NlcnZlcl9hcGkYCyABKAkSFgoOdGhyZWFkc19wZXJf", + "Y3EYDCABKAUSHAoTcmVzb3VyY2VfcXVvdGFfc2l6ZRjpByABKAUSLwoMY2hh", + "bm5lbF9hcmdzGOoHIAMoCzIYLmdycGMudGVzdGluZy5DaGFubmVsQXJnEhgK", + "EHNlcnZlcl9wcm9jZXNzZXMYFSABKAUiaAoKU2VydmVyQXJncxIrCgVzZXR1", + "cBgBIAEoCzIaLmdycGMudGVzdGluZy5TZXJ2ZXJDb25maWdIABIiCgRtYXJr", + "GAIgASgLMhIuZ3JwYy50ZXN0aW5nLk1hcmtIAEIJCgdhcmd0eXBlIlUKDFNl", + "cnZlclN0YXR1cxIoCgVzdGF0cxgBIAEoCzIZLmdycGMudGVzdGluZy5TZXJ2", + "ZXJTdGF0cxIMCgRwb3J0GAIgASgFEg0KBWNvcmVzGAMgASgFIg0KC0NvcmVS", + "ZXF1ZXN0Ih0KDENvcmVSZXNwb25zZRINCgVjb3JlcxgBIAEoBSIGCgRWb2lk", + "Iv0BCghTY2VuYXJpbxIMCgRuYW1lGAEgASgJEjEKDWNsaWVudF9jb25maWcY", + "AiABKAsyGi5ncnBjLnRlc3RpbmcuQ2xpZW50Q29uZmlnEhMKC251bV9jbGll", + "bnRzGAMgASgFEjEKDXNlcnZlcl9jb25maWcYBCABKAsyGi5ncnBjLnRlc3Rp", + "bmcuU2VydmVyQ29uZmlnEhMKC251bV9zZXJ2ZXJzGAUgASgFEhYKDndhcm11", + "cF9zZWNvbmRzGAYgASgFEhkKEWJlbmNobWFya19zZWNvbmRzGAcgASgFEiAK", + "GHNwYXduX2xvY2FsX3dvcmtlcl9jb3VudBgIIAEoBSI2CglTY2VuYXJpb3MS", + "KQoJc2NlbmFyaW9zGAEgAygLMhYuZ3JwYy50ZXN0aW5nLlNjZW5hcmlvIoQE", + "ChVTY2VuYXJpb1Jlc3VsdFN1bW1hcnkSCwoDcXBzGAEgASgBEhsKE3Fwc19w", + "ZXJfc2VydmVyX2NvcmUYAiABKAESGgoSc2VydmVyX3N5c3RlbV90aW1lGAMg", + "ASgBEhgKEHNlcnZlcl91c2VyX3RpbWUYBCABKAESGgoSY2xpZW50X3N5c3Rl", + "bV90aW1lGAUgASgBEhgKEGNsaWVudF91c2VyX3RpbWUYBiABKAESEgoKbGF0", + "ZW5jeV81MBgHIAEoARISCgpsYXRlbmN5XzkwGAggASgBEhIKCmxhdGVuY3lf", + "OTUYCSABKAESEgoKbGF0ZW5jeV85ORgKIAEoARITCgtsYXRlbmN5Xzk5ORgL", + "IAEoARIYChBzZXJ2ZXJfY3B1X3VzYWdlGAwgASgBEiYKHnN1Y2Nlc3NmdWxf", + "cmVxdWVzdHNfcGVyX3NlY29uZBgNIAEoARIiChpmYWlsZWRfcmVxdWVzdHNf", + "cGVyX3NlY29uZBgOIAEoARIgChhjbGllbnRfcG9sbHNfcGVyX3JlcXVlc3QY", + "DyABKAESIAoYc2VydmVyX3BvbGxzX3Blcl9yZXF1ZXN0GBAgASgBEiIKGnNl", + "cnZlcl9xdWVyaWVzX3Blcl9jcHVfc2VjGBEgASgBEiIKGmNsaWVudF9xdWVy", + "aWVzX3Blcl9jcHVfc2VjGBIgASgBIoMDCg5TY2VuYXJpb1Jlc3VsdBIoCghz", + "Y2VuYXJpbxgBIAEoCzIWLmdycGMudGVzdGluZy5TY2VuYXJpbxIuCglsYXRl", + "bmNpZXMYAiABKAsyGy5ncnBjLnRlc3RpbmcuSGlzdG9ncmFtRGF0YRIvCgxj", + "bGllbnRfc3RhdHMYAyADKAsyGS5ncnBjLnRlc3RpbmcuQ2xpZW50U3RhdHMS", + "LwoMc2VydmVyX3N0YXRzGAQgAygLMhkuZ3JwYy50ZXN0aW5nLlNlcnZlclN0", + "YXRzEhQKDHNlcnZlcl9jb3JlcxgFIAMoBRI0CgdzdW1tYXJ5GAYgASgLMiMu", + "Z3JwYy50ZXN0aW5nLlNjZW5hcmlvUmVzdWx0U3VtbWFyeRIWCg5jbGllbnRf", + "c3VjY2VzcxgHIAMoCBIWCg5zZXJ2ZXJfc3VjY2VzcxgIIAMoCBI5Cg9yZXF1", + "ZXN0X3Jlc3VsdHMYCSADKAsyIC5ncnBjLnRlc3RpbmcuUmVxdWVzdFJlc3Vs", + "dENvdW50KlYKCkNsaWVudFR5cGUSDwoLU1lOQ19DTElFTlQQABIQCgxBU1lO", + "Q19DTElFTlQQARIQCgxPVEhFUl9DTElFTlQQAhITCg9DQUxMQkFDS19DTElF", + "TlQQAypwCgpTZXJ2ZXJUeXBlEg8KC1NZTkNfU0VSVkVSEAASEAoMQVNZTkNf", + "U0VSVkVSEAESGAoUQVNZTkNfR0VORVJJQ19TRVJWRVIQAhIQCgxPVEhFUl9T", + "RVJWRVIQAxITCg9DQUxMQkFDS19TRVJWRVIQBCpyCgdScGNUeXBlEgkKBVVO", + "QVJZEAASDQoJU1RSRUFNSU5HEAESGQoVU1RSRUFNSU5HX0ZST01fQ0xJRU5U", + "EAISGQoVU1RSRUFNSU5HX0ZST01fU0VSVkVSEAMSFwoTU1RSRUFNSU5HX0JP", + "VEhfV0FZUxAEYgZwcm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.PoissonParams), global::Grpc.Testing.PoissonParams.Parser, new[]{ "OfferedLoad" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClosedLoopParams), global::Grpc.Testing.ClosedLoopParams.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson" }, new[]{ "Load" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride", "CredType" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ChannelArg), global::Grpc.Testing.ChannelArg.Parser, new[]{ "Name", "StrValue", "IntValue" }, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi", "ChannelArgs", "ThreadsPerCq", "MessagesPerStream", "UseCoalesceApi", "MedianLatencyCollectionIntervalMillis", "ClientProcesses" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList", "OtherServerApi", "ThreadsPerCq", "ResourceQuotaSize", "ChannelArgs", "ServerProcesses" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerArgs), global::Grpc.Testing.ServerArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreRequest), global::Grpc.Testing.CoreRequest.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreResponse), global::Grpc.Testing.CoreResponse.Parser, new[]{ "Cores" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Void), global::Grpc.Testing.Void.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenario), global::Grpc.Testing.Scenario.Parser, new[]{ "Name", "ClientConfig", "NumClients", "ServerConfig", "NumServers", "WarmupSeconds", "BenchmarkSeconds", "SpawnLocalWorkerCount" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenarios), global::Grpc.Testing.Scenarios.Parser, new[]{ "Scenarios_" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResultSummary), global::Grpc.Testing.ScenarioResultSummary.Parser, new[]{ "Qps", "QpsPerServerCore", "ServerSystemTime", "ServerUserTime", "ClientSystemTime", "ClientUserTime", "Latency50", "Latency90", "Latency95", "Latency99", "Latency999", "ServerCpuUsage", "SuccessfulRequestsPerSecond", "FailedRequestsPerSecond", "ClientPollsPerRequest", "ServerPollsPerRequest", "ServerQueriesPerCpuSec", "ClientQueriesPerCpuSec" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResult), global::Grpc.Testing.ScenarioResult.Parser, new[]{ "Scenario", "Latencies", "ClientStats", "ServerStats", "ServerCores", "Summary", "ClientSuccess", "ServerSuccess", "RequestResults" }, null, null, null, null) + })); + } + #endregion + + } + #region Enums + public enum ClientType { + /// + /// Many languages support a basic distinction between using + /// sync or async client, and this allows the specification + /// + [pbr::OriginalName("SYNC_CLIENT")] SyncClient = 0, + [pbr::OriginalName("ASYNC_CLIENT")] AsyncClient = 1, + /// + /// used for some language-specific variants + /// + [pbr::OriginalName("OTHER_CLIENT")] OtherClient = 2, + [pbr::OriginalName("CALLBACK_CLIENT")] CallbackClient = 3, + } + + public enum ServerType { + [pbr::OriginalName("SYNC_SERVER")] SyncServer = 0, + [pbr::OriginalName("ASYNC_SERVER")] AsyncServer = 1, + [pbr::OriginalName("ASYNC_GENERIC_SERVER")] AsyncGenericServer = 2, + /// + /// used for some language-specific variants + /// + [pbr::OriginalName("OTHER_SERVER")] OtherServer = 3, + [pbr::OriginalName("CALLBACK_SERVER")] CallbackServer = 4, + } + + public enum RpcType { + [pbr::OriginalName("UNARY")] Unary = 0, + [pbr::OriginalName("STREAMING")] Streaming = 1, + [pbr::OriginalName("STREAMING_FROM_CLIENT")] StreamingFromClient = 2, + [pbr::OriginalName("STREAMING_FROM_SERVER")] StreamingFromServer = 3, + [pbr::OriginalName("STREAMING_BOTH_WAYS")] StreamingBothWays = 4, + } + + #endregion + + #region Messages + /// + /// Parameters of poisson process distribution, which is a good representation + /// of activity coming in from independent identical stationary sources. + /// + public sealed partial class PoissonParams : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PoissonParams()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public PoissonParams() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public PoissonParams(PoissonParams other) : this() { + offeredLoad_ = other.offeredLoad_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public PoissonParams Clone() { + return new PoissonParams(this); + } + + /// Field number for the "offered_load" field. + public const int OfferedLoadFieldNumber = 1; + private double offeredLoad_; + /// + /// The rate of arrivals (a.k.a. lambda parameter of the exp distribution). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double OfferedLoad { + get { return offeredLoad_; } + set { + offeredLoad_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as PoissonParams); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(PoissonParams other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OfferedLoad, other.OfferedLoad)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (OfferedLoad != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OfferedLoad); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (OfferedLoad != 0D) { + output.WriteRawTag(9); + output.WriteDouble(OfferedLoad); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (OfferedLoad != 0D) { + output.WriteRawTag(9); + output.WriteDouble(OfferedLoad); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (OfferedLoad != 0D) { + size += 1 + 8; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(PoissonParams other) { + if (other == null) { + return; + } + if (other.OfferedLoad != 0D) { + OfferedLoad = other.OfferedLoad; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 9: { + OfferedLoad = input.ReadDouble(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 9: { + OfferedLoad = input.ReadDouble(); + break; + } + } + } + } + #endif + + } + + /// + /// Once an RPC finishes, immediately start a new one. + /// No configuration parameters needed. + /// + public sealed partial class ClosedLoopParams : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ClosedLoopParams()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClosedLoopParams() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClosedLoopParams(ClosedLoopParams other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClosedLoopParams Clone() { + return new ClosedLoopParams(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ClosedLoopParams); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ClosedLoopParams other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ClosedLoopParams other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + } + } + } + #endif + + } + + public sealed partial class LoadParams : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new LoadParams()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadParams() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadParams(LoadParams other) : this() { + switch (other.LoadCase) { + case LoadOneofCase.ClosedLoop: + ClosedLoop = other.ClosedLoop.Clone(); + break; + case LoadOneofCase.Poisson: + Poisson = other.Poisson.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadParams Clone() { + return new LoadParams(this); + } + + /// Field number for the "closed_loop" field. + public const int ClosedLoopFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ClosedLoopParams ClosedLoop { + get { return loadCase_ == LoadOneofCase.ClosedLoop ? (global::Grpc.Testing.ClosedLoopParams) load_ : null; } + set { + load_ = value; + loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.ClosedLoop; + } + } + + /// Field number for the "poisson" field. + public const int PoissonFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.PoissonParams Poisson { + get { return loadCase_ == LoadOneofCase.Poisson ? (global::Grpc.Testing.PoissonParams) load_ : null; } + set { + load_ = value; + loadCase_ = value == null ? LoadOneofCase.None : LoadOneofCase.Poisson; + } + } + + private object load_; + /// Enum of possible cases for the "load" oneof. + public enum LoadOneofCase { + None = 0, + ClosedLoop = 1, + Poisson = 2, + } + private LoadOneofCase loadCase_ = LoadOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadOneofCase LoadCase { + get { return loadCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearLoad() { + loadCase_ = LoadOneofCase.None; + load_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as LoadParams); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(LoadParams other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(ClosedLoop, other.ClosedLoop)) return false; + if (!object.Equals(Poisson, other.Poisson)) return false; + if (LoadCase != other.LoadCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (loadCase_ == LoadOneofCase.ClosedLoop) hash ^= ClosedLoop.GetHashCode(); + if (loadCase_ == LoadOneofCase.Poisson) hash ^= Poisson.GetHashCode(); + hash ^= (int) loadCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (loadCase_ == LoadOneofCase.ClosedLoop) { + output.WriteRawTag(10); + output.WriteMessage(ClosedLoop); + } + if (loadCase_ == LoadOneofCase.Poisson) { + output.WriteRawTag(18); + output.WriteMessage(Poisson); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (loadCase_ == LoadOneofCase.ClosedLoop) { + output.WriteRawTag(10); + output.WriteMessage(ClosedLoop); + } + if (loadCase_ == LoadOneofCase.Poisson) { + output.WriteRawTag(18); + output.WriteMessage(Poisson); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (loadCase_ == LoadOneofCase.ClosedLoop) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ClosedLoop); + } + if (loadCase_ == LoadOneofCase.Poisson) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Poisson); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(LoadParams other) { + if (other == null) { + return; + } + switch (other.LoadCase) { + case LoadOneofCase.ClosedLoop: + if (ClosedLoop == null) { + ClosedLoop = new global::Grpc.Testing.ClosedLoopParams(); + } + ClosedLoop.MergeFrom(other.ClosedLoop); + break; + case LoadOneofCase.Poisson: + if (Poisson == null) { + Poisson = new global::Grpc.Testing.PoissonParams(); + } + Poisson.MergeFrom(other.Poisson); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + global::Grpc.Testing.ClosedLoopParams subBuilder = new global::Grpc.Testing.ClosedLoopParams(); + if (loadCase_ == LoadOneofCase.ClosedLoop) { + subBuilder.MergeFrom(ClosedLoop); + } + input.ReadMessage(subBuilder); + ClosedLoop = subBuilder; + break; + } + case 18: { + global::Grpc.Testing.PoissonParams subBuilder = new global::Grpc.Testing.PoissonParams(); + if (loadCase_ == LoadOneofCase.Poisson) { + subBuilder.MergeFrom(Poisson); + } + input.ReadMessage(subBuilder); + Poisson = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + global::Grpc.Testing.ClosedLoopParams subBuilder = new global::Grpc.Testing.ClosedLoopParams(); + if (loadCase_ == LoadOneofCase.ClosedLoop) { + subBuilder.MergeFrom(ClosedLoop); + } + input.ReadMessage(subBuilder); + ClosedLoop = subBuilder; + break; + } + case 18: { + global::Grpc.Testing.PoissonParams subBuilder = new global::Grpc.Testing.PoissonParams(); + if (loadCase_ == LoadOneofCase.Poisson) { + subBuilder.MergeFrom(Poisson); + } + input.ReadMessage(subBuilder); + Poisson = subBuilder; + break; + } + } + } + } + #endif + + } + + /// + /// presence of SecurityParams implies use of TLS + /// + public sealed partial class SecurityParams : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SecurityParams()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SecurityParams() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SecurityParams(SecurityParams other) : this() { + useTestCa_ = other.useTestCa_; + serverHostOverride_ = other.serverHostOverride_; + credType_ = other.credType_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SecurityParams Clone() { + return new SecurityParams(this); + } + + /// Field number for the "use_test_ca" field. + public const int UseTestCaFieldNumber = 1; + private bool useTestCa_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool UseTestCa { + get { return useTestCa_; } + set { + useTestCa_ = value; + } + } + + /// Field number for the "server_host_override" field. + public const int ServerHostOverrideFieldNumber = 2; + private string serverHostOverride_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ServerHostOverride { + get { return serverHostOverride_; } + set { + serverHostOverride_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "cred_type" field. + public const int CredTypeFieldNumber = 3; + private string credType_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string CredType { + get { return credType_; } + set { + credType_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as SecurityParams); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(SecurityParams other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (UseTestCa != other.UseTestCa) return false; + if (ServerHostOverride != other.ServerHostOverride) return false; + if (CredType != other.CredType) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (UseTestCa != false) hash ^= UseTestCa.GetHashCode(); + if (ServerHostOverride.Length != 0) hash ^= ServerHostOverride.GetHashCode(); + if (CredType.Length != 0) hash ^= CredType.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (UseTestCa != false) { + output.WriteRawTag(8); + output.WriteBool(UseTestCa); + } + if (ServerHostOverride.Length != 0) { + output.WriteRawTag(18); + output.WriteString(ServerHostOverride); + } + if (CredType.Length != 0) { + output.WriteRawTag(26); + output.WriteString(CredType); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (UseTestCa != false) { + output.WriteRawTag(8); + output.WriteBool(UseTestCa); + } + if (ServerHostOverride.Length != 0) { + output.WriteRawTag(18); + output.WriteString(ServerHostOverride); + } + if (CredType.Length != 0) { + output.WriteRawTag(26); + output.WriteString(CredType); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (UseTestCa != false) { + size += 1 + 1; + } + if (ServerHostOverride.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ServerHostOverride); + } + if (CredType.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(CredType); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(SecurityParams other) { + if (other == null) { + return; + } + if (other.UseTestCa != false) { + UseTestCa = other.UseTestCa; + } + if (other.ServerHostOverride.Length != 0) { + ServerHostOverride = other.ServerHostOverride; + } + if (other.CredType.Length != 0) { + CredType = other.CredType; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + UseTestCa = input.ReadBool(); + break; + } + case 18: { + ServerHostOverride = input.ReadString(); + break; + } + case 26: { + CredType = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + UseTestCa = input.ReadBool(); + break; + } + case 18: { + ServerHostOverride = input.ReadString(); + break; + } + case 26: { + CredType = input.ReadString(); + break; + } + } + } + } + #endif + + } + + public sealed partial class ChannelArg : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ChannelArg()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ChannelArg() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ChannelArg(ChannelArg other) : this() { + name_ = other.name_; + switch (other.ValueCase) { + case ValueOneofCase.StrValue: + StrValue = other.StrValue; + break; + case ValueOneofCase.IntValue: + IntValue = other.IntValue; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ChannelArg Clone() { + return new ChannelArg(this); + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 1; + private string name_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "str_value" field. + public const int StrValueFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string StrValue { + get { return valueCase_ == ValueOneofCase.StrValue ? (string) value_ : ""; } + set { + value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + valueCase_ = ValueOneofCase.StrValue; + } + } + + /// Field number for the "int_value" field. + public const int IntValueFieldNumber = 3; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int IntValue { + get { return valueCase_ == ValueOneofCase.IntValue ? (int) value_ : 0; } + set { + value_ = value; + valueCase_ = ValueOneofCase.IntValue; + } + } + + private object value_; + /// Enum of possible cases for the "value" oneof. + public enum ValueOneofCase { + None = 0, + StrValue = 2, + IntValue = 3, + } + private ValueOneofCase valueCase_ = ValueOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ValueOneofCase ValueCase { + get { return valueCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearValue() { + valueCase_ = ValueOneofCase.None; + value_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ChannelArg); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ChannelArg other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Name != other.Name) return false; + if (StrValue != other.StrValue) return false; + if (IntValue != other.IntValue) return false; + if (ValueCase != other.ValueCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (valueCase_ == ValueOneofCase.StrValue) hash ^= StrValue.GetHashCode(); + if (valueCase_ == ValueOneofCase.IntValue) hash ^= IntValue.GetHashCode(); + hash ^= (int) valueCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (valueCase_ == ValueOneofCase.StrValue) { + output.WriteRawTag(18); + output.WriteString(StrValue); + } + if (valueCase_ == ValueOneofCase.IntValue) { + output.WriteRawTag(24); + output.WriteInt32(IntValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (valueCase_ == ValueOneofCase.StrValue) { + output.WriteRawTag(18); + output.WriteString(StrValue); + } + if (valueCase_ == ValueOneofCase.IntValue) { + output.WriteRawTag(24); + output.WriteInt32(IntValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + if (valueCase_ == ValueOneofCase.StrValue) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(StrValue); + } + if (valueCase_ == ValueOneofCase.IntValue) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntValue); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ChannelArg other) { + if (other == null) { + return; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + switch (other.ValueCase) { + case ValueOneofCase.StrValue: + StrValue = other.StrValue; + break; + case ValueOneofCase.IntValue: + IntValue = other.IntValue; + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + StrValue = input.ReadString(); + break; + } + case 24: { + IntValue = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + StrValue = input.ReadString(); + break; + } + case 24: { + IntValue = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class ClientConfig : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ClientConfig()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientConfig() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientConfig(ClientConfig other) : this() { + serverTargets_ = other.serverTargets_.Clone(); + clientType_ = other.clientType_; + securityParams_ = other.securityParams_ != null ? other.securityParams_.Clone() : null; + outstandingRpcsPerChannel_ = other.outstandingRpcsPerChannel_; + clientChannels_ = other.clientChannels_; + asyncClientThreads_ = other.asyncClientThreads_; + rpcType_ = other.rpcType_; + loadParams_ = other.loadParams_ != null ? other.loadParams_.Clone() : null; + payloadConfig_ = other.payloadConfig_ != null ? other.payloadConfig_.Clone() : null; + histogramParams_ = other.histogramParams_ != null ? other.histogramParams_.Clone() : null; + coreList_ = other.coreList_.Clone(); + coreLimit_ = other.coreLimit_; + otherClientApi_ = other.otherClientApi_; + channelArgs_ = other.channelArgs_.Clone(); + threadsPerCq_ = other.threadsPerCq_; + messagesPerStream_ = other.messagesPerStream_; + useCoalesceApi_ = other.useCoalesceApi_; + medianLatencyCollectionIntervalMillis_ = other.medianLatencyCollectionIntervalMillis_; + clientProcesses_ = other.clientProcesses_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientConfig Clone() { + return new ClientConfig(this); + } + + /// Field number for the "server_targets" field. + public const int ServerTargetsFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_serverTargets_codec + = pb::FieldCodec.ForString(10); + private readonly pbc::RepeatedField serverTargets_ = new pbc::RepeatedField(); + /// + /// List of targets to connect to. At least one target needs to be specified. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField ServerTargets { + get { return serverTargets_; } + } + + /// Field number for the "client_type" field. + public const int ClientTypeFieldNumber = 2; + private global::Grpc.Testing.ClientType clientType_ = global::Grpc.Testing.ClientType.SyncClient; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ClientType ClientType { + get { return clientType_; } + set { + clientType_ = value; + } + } + + /// Field number for the "security_params" field. + public const int SecurityParamsFieldNumber = 3; + private global::Grpc.Testing.SecurityParams securityParams_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.SecurityParams SecurityParams { + get { return securityParams_; } + set { + securityParams_ = value; + } + } + + /// Field number for the "outstanding_rpcs_per_channel" field. + public const int OutstandingRpcsPerChannelFieldNumber = 4; + private int outstandingRpcsPerChannel_; + /// + /// How many concurrent RPCs to start for each channel. + /// For synchronous client, use a separate thread for each outstanding RPC. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int OutstandingRpcsPerChannel { + get { return outstandingRpcsPerChannel_; } + set { + outstandingRpcsPerChannel_ = value; + } + } + + /// Field number for the "client_channels" field. + public const int ClientChannelsFieldNumber = 5; + private int clientChannels_; + /// + /// Number of independent client channels to create. + /// i-th channel will connect to server_target[i % server_targets.size()] + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ClientChannels { + get { return clientChannels_; } + set { + clientChannels_ = value; + } + } + + /// Field number for the "async_client_threads" field. + public const int AsyncClientThreadsFieldNumber = 7; + private int asyncClientThreads_; + /// + /// Only for async client. Number of threads to use to start/manage RPCs. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int AsyncClientThreads { + get { return asyncClientThreads_; } + set { + asyncClientThreads_ = value; + } + } + + /// Field number for the "rpc_type" field. + public const int RpcTypeFieldNumber = 8; + private global::Grpc.Testing.RpcType rpcType_ = global::Grpc.Testing.RpcType.Unary; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.RpcType RpcType { + get { return rpcType_; } + set { + rpcType_ = value; + } + } + + /// Field number for the "load_params" field. + public const int LoadParamsFieldNumber = 10; + private global::Grpc.Testing.LoadParams loadParams_; + /// + /// The requested load for the entire client (aggregated over all the threads). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.LoadParams LoadParams { + get { return loadParams_; } + set { + loadParams_ = value; + } + } + + /// Field number for the "payload_config" field. + public const int PayloadConfigFieldNumber = 11; + private global::Grpc.Testing.PayloadConfig payloadConfig_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.PayloadConfig PayloadConfig { + get { return payloadConfig_; } + set { + payloadConfig_ = value; + } + } + + /// Field number for the "histogram_params" field. + public const int HistogramParamsFieldNumber = 12; + private global::Grpc.Testing.HistogramParams histogramParams_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.HistogramParams HistogramParams { + get { return histogramParams_; } + set { + histogramParams_ = value; + } + } + + /// Field number for the "core_list" field. + public const int CoreListFieldNumber = 13; + private static readonly pb::FieldCodec _repeated_coreList_codec + = pb::FieldCodec.ForInt32(106); + private readonly pbc::RepeatedField coreList_ = new pbc::RepeatedField(); + /// + /// Specify the cores we should run the client on, if desired + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField CoreList { + get { return coreList_; } + } + + /// Field number for the "core_limit" field. + public const int CoreLimitFieldNumber = 14; + private int coreLimit_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CoreLimit { + get { return coreLimit_; } + set { + coreLimit_ = value; + } + } + + /// Field number for the "other_client_api" field. + public const int OtherClientApiFieldNumber = 15; + private string otherClientApi_ = ""; + /// + /// If we use an OTHER_CLIENT client_type, this string gives more detail + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string OtherClientApi { + get { return otherClientApi_; } + set { + otherClientApi_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "channel_args" field. + public const int ChannelArgsFieldNumber = 16; + private static readonly pb::FieldCodec _repeated_channelArgs_codec + = pb::FieldCodec.ForMessage(130, global::Grpc.Testing.ChannelArg.Parser); + private readonly pbc::RepeatedField channelArgs_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField ChannelArgs { + get { return channelArgs_; } + } + + /// Field number for the "threads_per_cq" field. + public const int ThreadsPerCqFieldNumber = 17; + private int threadsPerCq_; + /// + /// Number of threads that share each completion queue + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ThreadsPerCq { + get { return threadsPerCq_; } + set { + threadsPerCq_ = value; + } + } + + /// Field number for the "messages_per_stream" field. + public const int MessagesPerStreamFieldNumber = 18; + private int messagesPerStream_; + /// + /// Number of messages on a stream before it gets finished/restarted + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int MessagesPerStream { + get { return messagesPerStream_; } + set { + messagesPerStream_ = value; + } + } + + /// Field number for the "use_coalesce_api" field. + public const int UseCoalesceApiFieldNumber = 19; + private bool useCoalesceApi_; + /// + /// Use coalescing API when possible. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool UseCoalesceApi { + get { return useCoalesceApi_; } + set { + useCoalesceApi_ = value; + } + } + + /// Field number for the "median_latency_collection_interval_millis" field. + public const int MedianLatencyCollectionIntervalMillisFieldNumber = 20; + private int medianLatencyCollectionIntervalMillis_; + /// + /// If 0, disabled. Else, specifies the period between gathering latency + /// medians in milliseconds. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int MedianLatencyCollectionIntervalMillis { + get { return medianLatencyCollectionIntervalMillis_; } + set { + medianLatencyCollectionIntervalMillis_ = value; + } + } + + /// Field number for the "client_processes" field. + public const int ClientProcessesFieldNumber = 21; + private int clientProcesses_; + /// + /// Number of client processes. 0 indicates no restriction. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ClientProcesses { + get { return clientProcesses_; } + set { + clientProcesses_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ClientConfig); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ClientConfig other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!serverTargets_.Equals(other.serverTargets_)) return false; + if (ClientType != other.ClientType) return false; + if (!object.Equals(SecurityParams, other.SecurityParams)) return false; + if (OutstandingRpcsPerChannel != other.OutstandingRpcsPerChannel) return false; + if (ClientChannels != other.ClientChannels) return false; + if (AsyncClientThreads != other.AsyncClientThreads) return false; + if (RpcType != other.RpcType) return false; + if (!object.Equals(LoadParams, other.LoadParams)) return false; + if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false; + if (!object.Equals(HistogramParams, other.HistogramParams)) return false; + if(!coreList_.Equals(other.coreList_)) return false; + if (CoreLimit != other.CoreLimit) return false; + if (OtherClientApi != other.OtherClientApi) return false; + if(!channelArgs_.Equals(other.channelArgs_)) return false; + if (ThreadsPerCq != other.ThreadsPerCq) return false; + if (MessagesPerStream != other.MessagesPerStream) return false; + if (UseCoalesceApi != other.UseCoalesceApi) return false; + if (MedianLatencyCollectionIntervalMillis != other.MedianLatencyCollectionIntervalMillis) return false; + if (ClientProcesses != other.ClientProcesses) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + hash ^= serverTargets_.GetHashCode(); + if (ClientType != global::Grpc.Testing.ClientType.SyncClient) hash ^= ClientType.GetHashCode(); + if (securityParams_ != null) hash ^= SecurityParams.GetHashCode(); + if (OutstandingRpcsPerChannel != 0) hash ^= OutstandingRpcsPerChannel.GetHashCode(); + if (ClientChannels != 0) hash ^= ClientChannels.GetHashCode(); + if (AsyncClientThreads != 0) hash ^= AsyncClientThreads.GetHashCode(); + if (RpcType != global::Grpc.Testing.RpcType.Unary) hash ^= RpcType.GetHashCode(); + if (loadParams_ != null) hash ^= LoadParams.GetHashCode(); + if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode(); + if (histogramParams_ != null) hash ^= HistogramParams.GetHashCode(); + hash ^= coreList_.GetHashCode(); + if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode(); + if (OtherClientApi.Length != 0) hash ^= OtherClientApi.GetHashCode(); + hash ^= channelArgs_.GetHashCode(); + if (ThreadsPerCq != 0) hash ^= ThreadsPerCq.GetHashCode(); + if (MessagesPerStream != 0) hash ^= MessagesPerStream.GetHashCode(); + if (UseCoalesceApi != false) hash ^= UseCoalesceApi.GetHashCode(); + if (MedianLatencyCollectionIntervalMillis != 0) hash ^= MedianLatencyCollectionIntervalMillis.GetHashCode(); + if (ClientProcesses != 0) hash ^= ClientProcesses.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + serverTargets_.WriteTo(output, _repeated_serverTargets_codec); + if (ClientType != global::Grpc.Testing.ClientType.SyncClient) { + output.WriteRawTag(16); + output.WriteEnum((int) ClientType); + } + if (securityParams_ != null) { + output.WriteRawTag(26); + output.WriteMessage(SecurityParams); + } + if (OutstandingRpcsPerChannel != 0) { + output.WriteRawTag(32); + output.WriteInt32(OutstandingRpcsPerChannel); + } + if (ClientChannels != 0) { + output.WriteRawTag(40); + output.WriteInt32(ClientChannels); + } + if (AsyncClientThreads != 0) { + output.WriteRawTag(56); + output.WriteInt32(AsyncClientThreads); + } + if (RpcType != global::Grpc.Testing.RpcType.Unary) { + output.WriteRawTag(64); + output.WriteEnum((int) RpcType); + } + if (loadParams_ != null) { + output.WriteRawTag(82); + output.WriteMessage(LoadParams); + } + if (payloadConfig_ != null) { + output.WriteRawTag(90); + output.WriteMessage(PayloadConfig); + } + if (histogramParams_ != null) { + output.WriteRawTag(98); + output.WriteMessage(HistogramParams); + } + coreList_.WriteTo(output, _repeated_coreList_codec); + if (CoreLimit != 0) { + output.WriteRawTag(112); + output.WriteInt32(CoreLimit); + } + if (OtherClientApi.Length != 0) { + output.WriteRawTag(122); + output.WriteString(OtherClientApi); + } + channelArgs_.WriteTo(output, _repeated_channelArgs_codec); + if (ThreadsPerCq != 0) { + output.WriteRawTag(136, 1); + output.WriteInt32(ThreadsPerCq); + } + if (MessagesPerStream != 0) { + output.WriteRawTag(144, 1); + output.WriteInt32(MessagesPerStream); + } + if (UseCoalesceApi != false) { + output.WriteRawTag(152, 1); + output.WriteBool(UseCoalesceApi); + } + if (MedianLatencyCollectionIntervalMillis != 0) { + output.WriteRawTag(160, 1); + output.WriteInt32(MedianLatencyCollectionIntervalMillis); + } + if (ClientProcesses != 0) { + output.WriteRawTag(168, 1); + output.WriteInt32(ClientProcesses); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + serverTargets_.WriteTo(ref output, _repeated_serverTargets_codec); + if (ClientType != global::Grpc.Testing.ClientType.SyncClient) { + output.WriteRawTag(16); + output.WriteEnum((int) ClientType); + } + if (securityParams_ != null) { + output.WriteRawTag(26); + output.WriteMessage(SecurityParams); + } + if (OutstandingRpcsPerChannel != 0) { + output.WriteRawTag(32); + output.WriteInt32(OutstandingRpcsPerChannel); + } + if (ClientChannels != 0) { + output.WriteRawTag(40); + output.WriteInt32(ClientChannels); + } + if (AsyncClientThreads != 0) { + output.WriteRawTag(56); + output.WriteInt32(AsyncClientThreads); + } + if (RpcType != global::Grpc.Testing.RpcType.Unary) { + output.WriteRawTag(64); + output.WriteEnum((int) RpcType); + } + if (loadParams_ != null) { + output.WriteRawTag(82); + output.WriteMessage(LoadParams); + } + if (payloadConfig_ != null) { + output.WriteRawTag(90); + output.WriteMessage(PayloadConfig); + } + if (histogramParams_ != null) { + output.WriteRawTag(98); + output.WriteMessage(HistogramParams); + } + coreList_.WriteTo(ref output, _repeated_coreList_codec); + if (CoreLimit != 0) { + output.WriteRawTag(112); + output.WriteInt32(CoreLimit); + } + if (OtherClientApi.Length != 0) { + output.WriteRawTag(122); + output.WriteString(OtherClientApi); + } + channelArgs_.WriteTo(ref output, _repeated_channelArgs_codec); + if (ThreadsPerCq != 0) { + output.WriteRawTag(136, 1); + output.WriteInt32(ThreadsPerCq); + } + if (MessagesPerStream != 0) { + output.WriteRawTag(144, 1); + output.WriteInt32(MessagesPerStream); + } + if (UseCoalesceApi != false) { + output.WriteRawTag(152, 1); + output.WriteBool(UseCoalesceApi); + } + if (MedianLatencyCollectionIntervalMillis != 0) { + output.WriteRawTag(160, 1); + output.WriteInt32(MedianLatencyCollectionIntervalMillis); + } + if (ClientProcesses != 0) { + output.WriteRawTag(168, 1); + output.WriteInt32(ClientProcesses); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + size += serverTargets_.CalculateSize(_repeated_serverTargets_codec); + if (ClientType != global::Grpc.Testing.ClientType.SyncClient) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ClientType); + } + if (securityParams_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(SecurityParams); + } + if (OutstandingRpcsPerChannel != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(OutstandingRpcsPerChannel); + } + if (ClientChannels != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ClientChannels); + } + if (AsyncClientThreads != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(AsyncClientThreads); + } + if (RpcType != global::Grpc.Testing.RpcType.Unary) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RpcType); + } + if (loadParams_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(LoadParams); + } + if (payloadConfig_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig); + } + if (histogramParams_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(HistogramParams); + } + size += coreList_.CalculateSize(_repeated_coreList_codec); + if (CoreLimit != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(CoreLimit); + } + if (OtherClientApi.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherClientApi); + } + size += channelArgs_.CalculateSize(_repeated_channelArgs_codec); + if (ThreadsPerCq != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(ThreadsPerCq); + } + if (MessagesPerStream != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(MessagesPerStream); + } + if (UseCoalesceApi != false) { + size += 2 + 1; + } + if (MedianLatencyCollectionIntervalMillis != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(MedianLatencyCollectionIntervalMillis); + } + if (ClientProcesses != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(ClientProcesses); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ClientConfig other) { + if (other == null) { + return; + } + serverTargets_.Add(other.serverTargets_); + if (other.ClientType != global::Grpc.Testing.ClientType.SyncClient) { + ClientType = other.ClientType; + } + if (other.securityParams_ != null) { + if (securityParams_ == null) { + SecurityParams = new global::Grpc.Testing.SecurityParams(); + } + SecurityParams.MergeFrom(other.SecurityParams); + } + if (other.OutstandingRpcsPerChannel != 0) { + OutstandingRpcsPerChannel = other.OutstandingRpcsPerChannel; + } + if (other.ClientChannels != 0) { + ClientChannels = other.ClientChannels; + } + if (other.AsyncClientThreads != 0) { + AsyncClientThreads = other.AsyncClientThreads; + } + if (other.RpcType != global::Grpc.Testing.RpcType.Unary) { + RpcType = other.RpcType; + } + if (other.loadParams_ != null) { + if (loadParams_ == null) { + LoadParams = new global::Grpc.Testing.LoadParams(); + } + LoadParams.MergeFrom(other.LoadParams); + } + if (other.payloadConfig_ != null) { + if (payloadConfig_ == null) { + PayloadConfig = new global::Grpc.Testing.PayloadConfig(); + } + PayloadConfig.MergeFrom(other.PayloadConfig); + } + if (other.histogramParams_ != null) { + if (histogramParams_ == null) { + HistogramParams = new global::Grpc.Testing.HistogramParams(); + } + HistogramParams.MergeFrom(other.HistogramParams); + } + coreList_.Add(other.coreList_); + if (other.CoreLimit != 0) { + CoreLimit = other.CoreLimit; + } + if (other.OtherClientApi.Length != 0) { + OtherClientApi = other.OtherClientApi; + } + channelArgs_.Add(other.channelArgs_); + if (other.ThreadsPerCq != 0) { + ThreadsPerCq = other.ThreadsPerCq; + } + if (other.MessagesPerStream != 0) { + MessagesPerStream = other.MessagesPerStream; + } + if (other.UseCoalesceApi != false) { + UseCoalesceApi = other.UseCoalesceApi; + } + if (other.MedianLatencyCollectionIntervalMillis != 0) { + MedianLatencyCollectionIntervalMillis = other.MedianLatencyCollectionIntervalMillis; + } + if (other.ClientProcesses != 0) { + ClientProcesses = other.ClientProcesses; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + serverTargets_.AddEntriesFrom(input, _repeated_serverTargets_codec); + break; + } + case 16: { + ClientType = (global::Grpc.Testing.ClientType) input.ReadEnum(); + break; + } + case 26: { + if (securityParams_ == null) { + SecurityParams = new global::Grpc.Testing.SecurityParams(); + } + input.ReadMessage(SecurityParams); + break; + } + case 32: { + OutstandingRpcsPerChannel = input.ReadInt32(); + break; + } + case 40: { + ClientChannels = input.ReadInt32(); + break; + } + case 56: { + AsyncClientThreads = input.ReadInt32(); + break; + } + case 64: { + RpcType = (global::Grpc.Testing.RpcType) input.ReadEnum(); + break; + } + case 82: { + if (loadParams_ == null) { + LoadParams = new global::Grpc.Testing.LoadParams(); + } + input.ReadMessage(LoadParams); + break; + } + case 90: { + if (payloadConfig_ == null) { + PayloadConfig = new global::Grpc.Testing.PayloadConfig(); + } + input.ReadMessage(PayloadConfig); + break; + } + case 98: { + if (histogramParams_ == null) { + HistogramParams = new global::Grpc.Testing.HistogramParams(); + } + input.ReadMessage(HistogramParams); + break; + } + case 106: + case 104: { + coreList_.AddEntriesFrom(input, _repeated_coreList_codec); + break; + } + case 112: { + CoreLimit = input.ReadInt32(); + break; + } + case 122: { + OtherClientApi = input.ReadString(); + break; + } + case 130: { + channelArgs_.AddEntriesFrom(input, _repeated_channelArgs_codec); + break; + } + case 136: { + ThreadsPerCq = input.ReadInt32(); + break; + } + case 144: { + MessagesPerStream = input.ReadInt32(); + break; + } + case 152: { + UseCoalesceApi = input.ReadBool(); + break; + } + case 160: { + MedianLatencyCollectionIntervalMillis = input.ReadInt32(); + break; + } + case 168: { + ClientProcesses = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + serverTargets_.AddEntriesFrom(ref input, _repeated_serverTargets_codec); + break; + } + case 16: { + ClientType = (global::Grpc.Testing.ClientType) input.ReadEnum(); + break; + } + case 26: { + if (securityParams_ == null) { + SecurityParams = new global::Grpc.Testing.SecurityParams(); + } + input.ReadMessage(SecurityParams); + break; + } + case 32: { + OutstandingRpcsPerChannel = input.ReadInt32(); + break; + } + case 40: { + ClientChannels = input.ReadInt32(); + break; + } + case 56: { + AsyncClientThreads = input.ReadInt32(); + break; + } + case 64: { + RpcType = (global::Grpc.Testing.RpcType) input.ReadEnum(); + break; + } + case 82: { + if (loadParams_ == null) { + LoadParams = new global::Grpc.Testing.LoadParams(); + } + input.ReadMessage(LoadParams); + break; + } + case 90: { + if (payloadConfig_ == null) { + PayloadConfig = new global::Grpc.Testing.PayloadConfig(); + } + input.ReadMessage(PayloadConfig); + break; + } + case 98: { + if (histogramParams_ == null) { + HistogramParams = new global::Grpc.Testing.HistogramParams(); + } + input.ReadMessage(HistogramParams); + break; + } + case 106: + case 104: { + coreList_.AddEntriesFrom(ref input, _repeated_coreList_codec); + break; + } + case 112: { + CoreLimit = input.ReadInt32(); + break; + } + case 122: { + OtherClientApi = input.ReadString(); + break; + } + case 130: { + channelArgs_.AddEntriesFrom(ref input, _repeated_channelArgs_codec); + break; + } + case 136: { + ThreadsPerCq = input.ReadInt32(); + break; + } + case 144: { + MessagesPerStream = input.ReadInt32(); + break; + } + case 152: { + UseCoalesceApi = input.ReadBool(); + break; + } + case 160: { + MedianLatencyCollectionIntervalMillis = input.ReadInt32(); + break; + } + case 168: { + ClientProcesses = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class ClientStatus : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ClientStatus()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[6]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientStatus() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientStatus(ClientStatus other) : this() { + stats_ = other.stats_ != null ? other.stats_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientStatus Clone() { + return new ClientStatus(this); + } + + /// Field number for the "stats" field. + public const int StatsFieldNumber = 1; + private global::Grpc.Testing.ClientStats stats_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ClientStats Stats { + get { return stats_; } + set { + stats_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ClientStatus); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ClientStatus other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Stats, other.Stats)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (stats_ != null) hash ^= Stats.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (stats_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Stats); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (stats_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Stats); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (stats_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ClientStatus other) { + if (other == null) { + return; + } + if (other.stats_ != null) { + if (stats_ == null) { + Stats = new global::Grpc.Testing.ClientStats(); + } + Stats.MergeFrom(other.Stats); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (stats_ == null) { + Stats = new global::Grpc.Testing.ClientStats(); + } + input.ReadMessage(Stats); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (stats_ == null) { + Stats = new global::Grpc.Testing.ClientStats(); + } + input.ReadMessage(Stats); + break; + } + } + } + } + #endif + + } + + /// + /// Request current stats + /// + public sealed partial class Mark : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Mark()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[7]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Mark() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Mark(Mark other) : this() { + reset_ = other.reset_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Mark Clone() { + return new Mark(this); + } + + /// Field number for the "reset" field. + public const int ResetFieldNumber = 1; + private bool reset_; + /// + /// if true, the stats will be reset after taking their snapshot. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Reset { + get { return reset_; } + set { + reset_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Mark); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Mark other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Reset != other.Reset) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Reset != false) hash ^= Reset.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Reset != false) { + output.WriteRawTag(8); + output.WriteBool(Reset); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Reset != false) { + output.WriteRawTag(8); + output.WriteBool(Reset); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Reset != false) { + size += 1 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Mark other) { + if (other == null) { + return; + } + if (other.Reset != false) { + Reset = other.Reset; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Reset = input.ReadBool(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Reset = input.ReadBool(); + break; + } + } + } + } + #endif + + } + + public sealed partial class ClientArgs : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ClientArgs()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[8]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientArgs() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientArgs(ClientArgs other) : this() { + switch (other.ArgtypeCase) { + case ArgtypeOneofCase.Setup: + Setup = other.Setup.Clone(); + break; + case ArgtypeOneofCase.Mark: + Mark = other.Mark.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientArgs Clone() { + return new ClientArgs(this); + } + + /// Field number for the "setup" field. + public const int SetupFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ClientConfig Setup { + get { return argtypeCase_ == ArgtypeOneofCase.Setup ? (global::Grpc.Testing.ClientConfig) argtype_ : null; } + set { + argtype_ = value; + argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Setup; + } + } + + /// Field number for the "mark" field. + public const int MarkFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.Mark Mark { + get { return argtypeCase_ == ArgtypeOneofCase.Mark ? (global::Grpc.Testing.Mark) argtype_ : null; } + set { + argtype_ = value; + argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Mark; + } + } + + private object argtype_; + /// Enum of possible cases for the "argtype" oneof. + public enum ArgtypeOneofCase { + None = 0, + Setup = 1, + Mark = 2, + } + private ArgtypeOneofCase argtypeCase_ = ArgtypeOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ArgtypeOneofCase ArgtypeCase { + get { return argtypeCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearArgtype() { + argtypeCase_ = ArgtypeOneofCase.None; + argtype_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ClientArgs); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ClientArgs other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Setup, other.Setup)) return false; + if (!object.Equals(Mark, other.Mark)) return false; + if (ArgtypeCase != other.ArgtypeCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode(); + if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode(); + hash ^= (int) argtypeCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (argtypeCase_ == ArgtypeOneofCase.Setup) { + output.WriteRawTag(10); + output.WriteMessage(Setup); + } + if (argtypeCase_ == ArgtypeOneofCase.Mark) { + output.WriteRawTag(18); + output.WriteMessage(Mark); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (argtypeCase_ == ArgtypeOneofCase.Setup) { + output.WriteRawTag(10); + output.WriteMessage(Setup); + } + if (argtypeCase_ == ArgtypeOneofCase.Mark) { + output.WriteRawTag(18); + output.WriteMessage(Mark); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (argtypeCase_ == ArgtypeOneofCase.Setup) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Setup); + } + if (argtypeCase_ == ArgtypeOneofCase.Mark) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ClientArgs other) { + if (other == null) { + return; + } + switch (other.ArgtypeCase) { + case ArgtypeOneofCase.Setup: + if (Setup == null) { + Setup = new global::Grpc.Testing.ClientConfig(); + } + Setup.MergeFrom(other.Setup); + break; + case ArgtypeOneofCase.Mark: + if (Mark == null) { + Mark = new global::Grpc.Testing.Mark(); + } + Mark.MergeFrom(other.Mark); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + global::Grpc.Testing.ClientConfig subBuilder = new global::Grpc.Testing.ClientConfig(); + if (argtypeCase_ == ArgtypeOneofCase.Setup) { + subBuilder.MergeFrom(Setup); + } + input.ReadMessage(subBuilder); + Setup = subBuilder; + break; + } + case 18: { + global::Grpc.Testing.Mark subBuilder = new global::Grpc.Testing.Mark(); + if (argtypeCase_ == ArgtypeOneofCase.Mark) { + subBuilder.MergeFrom(Mark); + } + input.ReadMessage(subBuilder); + Mark = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + global::Grpc.Testing.ClientConfig subBuilder = new global::Grpc.Testing.ClientConfig(); + if (argtypeCase_ == ArgtypeOneofCase.Setup) { + subBuilder.MergeFrom(Setup); + } + input.ReadMessage(subBuilder); + Setup = subBuilder; + break; + } + case 18: { + global::Grpc.Testing.Mark subBuilder = new global::Grpc.Testing.Mark(); + if (argtypeCase_ == ArgtypeOneofCase.Mark) { + subBuilder.MergeFrom(Mark); + } + input.ReadMessage(subBuilder); + Mark = subBuilder; + break; + } + } + } + } + #endif + + } + + public sealed partial class ServerConfig : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServerConfig()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[9]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerConfig() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerConfig(ServerConfig other) : this() { + serverType_ = other.serverType_; + securityParams_ = other.securityParams_ != null ? other.securityParams_.Clone() : null; + port_ = other.port_; + asyncServerThreads_ = other.asyncServerThreads_; + coreLimit_ = other.coreLimit_; + payloadConfig_ = other.payloadConfig_ != null ? other.payloadConfig_.Clone() : null; + coreList_ = other.coreList_.Clone(); + otherServerApi_ = other.otherServerApi_; + threadsPerCq_ = other.threadsPerCq_; + resourceQuotaSize_ = other.resourceQuotaSize_; + channelArgs_ = other.channelArgs_.Clone(); + serverProcesses_ = other.serverProcesses_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerConfig Clone() { + return new ServerConfig(this); + } + + /// Field number for the "server_type" field. + public const int ServerTypeFieldNumber = 1; + private global::Grpc.Testing.ServerType serverType_ = global::Grpc.Testing.ServerType.SyncServer; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ServerType ServerType { + get { return serverType_; } + set { + serverType_ = value; + } + } + + /// Field number for the "security_params" field. + public const int SecurityParamsFieldNumber = 2; + private global::Grpc.Testing.SecurityParams securityParams_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.SecurityParams SecurityParams { + get { return securityParams_; } + set { + securityParams_ = value; + } + } + + /// Field number for the "port" field. + public const int PortFieldNumber = 4; + private int port_; + /// + /// Port on which to listen. Zero means pick unused port. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int Port { + get { return port_; } + set { + port_ = value; + } + } + + /// Field number for the "async_server_threads" field. + public const int AsyncServerThreadsFieldNumber = 7; + private int asyncServerThreads_; + /// + /// Only for async server. Number of threads used to serve the requests. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int AsyncServerThreads { + get { return asyncServerThreads_; } + set { + asyncServerThreads_ = value; + } + } + + /// Field number for the "core_limit" field. + public const int CoreLimitFieldNumber = 8; + private int coreLimit_; + /// + /// Specify the number of cores to limit server to, if desired + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CoreLimit { + get { return coreLimit_; } + set { + coreLimit_ = value; + } + } + + /// Field number for the "payload_config" field. + public const int PayloadConfigFieldNumber = 9; + private global::Grpc.Testing.PayloadConfig payloadConfig_; + /// + /// payload config, used in generic server. + /// Note this must NOT be used in proto (non-generic) servers. For proto servers, + /// 'response sizes' must be configured from the 'response_size' field of the + /// 'SimpleRequest' objects in RPC requests. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.PayloadConfig PayloadConfig { + get { return payloadConfig_; } + set { + payloadConfig_ = value; + } + } + + /// Field number for the "core_list" field. + public const int CoreListFieldNumber = 10; + private static readonly pb::FieldCodec _repeated_coreList_codec + = pb::FieldCodec.ForInt32(82); + private readonly pbc::RepeatedField coreList_ = new pbc::RepeatedField(); + /// + /// Specify the cores we should run the server on, if desired + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField CoreList { + get { return coreList_; } + } + + /// Field number for the "other_server_api" field. + public const int OtherServerApiFieldNumber = 11; + private string otherServerApi_ = ""; + /// + /// If we use an OTHER_SERVER client_type, this string gives more detail + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string OtherServerApi { + get { return otherServerApi_; } + set { + otherServerApi_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "threads_per_cq" field. + public const int ThreadsPerCqFieldNumber = 12; + private int threadsPerCq_; + /// + /// Number of threads that share each completion queue + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ThreadsPerCq { + get { return threadsPerCq_; } + set { + threadsPerCq_ = value; + } + } + + /// Field number for the "resource_quota_size" field. + public const int ResourceQuotaSizeFieldNumber = 1001; + private int resourceQuotaSize_; + /// + /// Buffer pool size (no buffer pool specified if unset) + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ResourceQuotaSize { + get { return resourceQuotaSize_; } + set { + resourceQuotaSize_ = value; + } + } + + /// Field number for the "channel_args" field. + public const int ChannelArgsFieldNumber = 1002; + private static readonly pb::FieldCodec _repeated_channelArgs_codec + = pb::FieldCodec.ForMessage(8018, global::Grpc.Testing.ChannelArg.Parser); + private readonly pbc::RepeatedField channelArgs_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField ChannelArgs { + get { return channelArgs_; } + } + + /// Field number for the "server_processes" field. + public const int ServerProcessesFieldNumber = 21; + private int serverProcesses_; + /// + /// Number of server processes. 0 indicates no restriction. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ServerProcesses { + get { return serverProcesses_; } + set { + serverProcesses_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ServerConfig); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ServerConfig other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ServerType != other.ServerType) return false; + if (!object.Equals(SecurityParams, other.SecurityParams)) return false; + if (Port != other.Port) return false; + if (AsyncServerThreads != other.AsyncServerThreads) return false; + if (CoreLimit != other.CoreLimit) return false; + if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false; + if(!coreList_.Equals(other.coreList_)) return false; + if (OtherServerApi != other.OtherServerApi) return false; + if (ThreadsPerCq != other.ThreadsPerCq) return false; + if (ResourceQuotaSize != other.ResourceQuotaSize) return false; + if(!channelArgs_.Equals(other.channelArgs_)) return false; + if (ServerProcesses != other.ServerProcesses) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (ServerType != global::Grpc.Testing.ServerType.SyncServer) hash ^= ServerType.GetHashCode(); + if (securityParams_ != null) hash ^= SecurityParams.GetHashCode(); + if (Port != 0) hash ^= Port.GetHashCode(); + if (AsyncServerThreads != 0) hash ^= AsyncServerThreads.GetHashCode(); + if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode(); + if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode(); + hash ^= coreList_.GetHashCode(); + if (OtherServerApi.Length != 0) hash ^= OtherServerApi.GetHashCode(); + if (ThreadsPerCq != 0) hash ^= ThreadsPerCq.GetHashCode(); + if (ResourceQuotaSize != 0) hash ^= ResourceQuotaSize.GetHashCode(); + hash ^= channelArgs_.GetHashCode(); + if (ServerProcesses != 0) hash ^= ServerProcesses.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (ServerType != global::Grpc.Testing.ServerType.SyncServer) { + output.WriteRawTag(8); + output.WriteEnum((int) ServerType); + } + if (securityParams_ != null) { + output.WriteRawTag(18); + output.WriteMessage(SecurityParams); + } + if (Port != 0) { + output.WriteRawTag(32); + output.WriteInt32(Port); + } + if (AsyncServerThreads != 0) { + output.WriteRawTag(56); + output.WriteInt32(AsyncServerThreads); + } + if (CoreLimit != 0) { + output.WriteRawTag(64); + output.WriteInt32(CoreLimit); + } + if (payloadConfig_ != null) { + output.WriteRawTag(74); + output.WriteMessage(PayloadConfig); + } + coreList_.WriteTo(output, _repeated_coreList_codec); + if (OtherServerApi.Length != 0) { + output.WriteRawTag(90); + output.WriteString(OtherServerApi); + } + if (ThreadsPerCq != 0) { + output.WriteRawTag(96); + output.WriteInt32(ThreadsPerCq); + } + if (ServerProcesses != 0) { + output.WriteRawTag(168, 1); + output.WriteInt32(ServerProcesses); + } + if (ResourceQuotaSize != 0) { + output.WriteRawTag(200, 62); + output.WriteInt32(ResourceQuotaSize); + } + channelArgs_.WriteTo(output, _repeated_channelArgs_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (ServerType != global::Grpc.Testing.ServerType.SyncServer) { + output.WriteRawTag(8); + output.WriteEnum((int) ServerType); + } + if (securityParams_ != null) { + output.WriteRawTag(18); + output.WriteMessage(SecurityParams); + } + if (Port != 0) { + output.WriteRawTag(32); + output.WriteInt32(Port); + } + if (AsyncServerThreads != 0) { + output.WriteRawTag(56); + output.WriteInt32(AsyncServerThreads); + } + if (CoreLimit != 0) { + output.WriteRawTag(64); + output.WriteInt32(CoreLimit); + } + if (payloadConfig_ != null) { + output.WriteRawTag(74); + output.WriteMessage(PayloadConfig); + } + coreList_.WriteTo(ref output, _repeated_coreList_codec); + if (OtherServerApi.Length != 0) { + output.WriteRawTag(90); + output.WriteString(OtherServerApi); + } + if (ThreadsPerCq != 0) { + output.WriteRawTag(96); + output.WriteInt32(ThreadsPerCq); + } + if (ServerProcesses != 0) { + output.WriteRawTag(168, 1); + output.WriteInt32(ServerProcesses); + } + if (ResourceQuotaSize != 0) { + output.WriteRawTag(200, 62); + output.WriteInt32(ResourceQuotaSize); + } + channelArgs_.WriteTo(ref output, _repeated_channelArgs_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (ServerType != global::Grpc.Testing.ServerType.SyncServer) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ServerType); + } + if (securityParams_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(SecurityParams); + } + if (Port != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Port); + } + if (AsyncServerThreads != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(AsyncServerThreads); + } + if (CoreLimit != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(CoreLimit); + } + if (payloadConfig_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(PayloadConfig); + } + size += coreList_.CalculateSize(_repeated_coreList_codec); + if (OtherServerApi.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherServerApi); + } + if (ThreadsPerCq != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ThreadsPerCq); + } + if (ResourceQuotaSize != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(ResourceQuotaSize); + } + size += channelArgs_.CalculateSize(_repeated_channelArgs_codec); + if (ServerProcesses != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(ServerProcesses); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ServerConfig other) { + if (other == null) { + return; + } + if (other.ServerType != global::Grpc.Testing.ServerType.SyncServer) { + ServerType = other.ServerType; + } + if (other.securityParams_ != null) { + if (securityParams_ == null) { + SecurityParams = new global::Grpc.Testing.SecurityParams(); + } + SecurityParams.MergeFrom(other.SecurityParams); + } + if (other.Port != 0) { + Port = other.Port; + } + if (other.AsyncServerThreads != 0) { + AsyncServerThreads = other.AsyncServerThreads; + } + if (other.CoreLimit != 0) { + CoreLimit = other.CoreLimit; + } + if (other.payloadConfig_ != null) { + if (payloadConfig_ == null) { + PayloadConfig = new global::Grpc.Testing.PayloadConfig(); + } + PayloadConfig.MergeFrom(other.PayloadConfig); + } + coreList_.Add(other.coreList_); + if (other.OtherServerApi.Length != 0) { + OtherServerApi = other.OtherServerApi; + } + if (other.ThreadsPerCq != 0) { + ThreadsPerCq = other.ThreadsPerCq; + } + if (other.ResourceQuotaSize != 0) { + ResourceQuotaSize = other.ResourceQuotaSize; + } + channelArgs_.Add(other.channelArgs_); + if (other.ServerProcesses != 0) { + ServerProcesses = other.ServerProcesses; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + ServerType = (global::Grpc.Testing.ServerType) input.ReadEnum(); + break; + } + case 18: { + if (securityParams_ == null) { + SecurityParams = new global::Grpc.Testing.SecurityParams(); + } + input.ReadMessage(SecurityParams); + break; + } + case 32: { + Port = input.ReadInt32(); + break; + } + case 56: { + AsyncServerThreads = input.ReadInt32(); + break; + } + case 64: { + CoreLimit = input.ReadInt32(); + break; + } + case 74: { + if (payloadConfig_ == null) { + PayloadConfig = new global::Grpc.Testing.PayloadConfig(); + } + input.ReadMessage(PayloadConfig); + break; + } + case 82: + case 80: { + coreList_.AddEntriesFrom(input, _repeated_coreList_codec); + break; + } + case 90: { + OtherServerApi = input.ReadString(); + break; + } + case 96: { + ThreadsPerCq = input.ReadInt32(); + break; + } + case 168: { + ServerProcesses = input.ReadInt32(); + break; + } + case 8008: { + ResourceQuotaSize = input.ReadInt32(); + break; + } + case 8018: { + channelArgs_.AddEntriesFrom(input, _repeated_channelArgs_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + ServerType = (global::Grpc.Testing.ServerType) input.ReadEnum(); + break; + } + case 18: { + if (securityParams_ == null) { + SecurityParams = new global::Grpc.Testing.SecurityParams(); + } + input.ReadMessage(SecurityParams); + break; + } + case 32: { + Port = input.ReadInt32(); + break; + } + case 56: { + AsyncServerThreads = input.ReadInt32(); + break; + } + case 64: { + CoreLimit = input.ReadInt32(); + break; + } + case 74: { + if (payloadConfig_ == null) { + PayloadConfig = new global::Grpc.Testing.PayloadConfig(); + } + input.ReadMessage(PayloadConfig); + break; + } + case 82: + case 80: { + coreList_.AddEntriesFrom(ref input, _repeated_coreList_codec); + break; + } + case 90: { + OtherServerApi = input.ReadString(); + break; + } + case 96: { + ThreadsPerCq = input.ReadInt32(); + break; + } + case 168: { + ServerProcesses = input.ReadInt32(); + break; + } + case 8008: { + ResourceQuotaSize = input.ReadInt32(); + break; + } + case 8018: { + channelArgs_.AddEntriesFrom(ref input, _repeated_channelArgs_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class ServerArgs : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServerArgs()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[10]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerArgs() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerArgs(ServerArgs other) : this() { + switch (other.ArgtypeCase) { + case ArgtypeOneofCase.Setup: + Setup = other.Setup.Clone(); + break; + case ArgtypeOneofCase.Mark: + Mark = other.Mark.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerArgs Clone() { + return new ServerArgs(this); + } + + /// Field number for the "setup" field. + public const int SetupFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ServerConfig Setup { + get { return argtypeCase_ == ArgtypeOneofCase.Setup ? (global::Grpc.Testing.ServerConfig) argtype_ : null; } + set { + argtype_ = value; + argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Setup; + } + } + + /// Field number for the "mark" field. + public const int MarkFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.Mark Mark { + get { return argtypeCase_ == ArgtypeOneofCase.Mark ? (global::Grpc.Testing.Mark) argtype_ : null; } + set { + argtype_ = value; + argtypeCase_ = value == null ? ArgtypeOneofCase.None : ArgtypeOneofCase.Mark; + } + } + + private object argtype_; + /// Enum of possible cases for the "argtype" oneof. + public enum ArgtypeOneofCase { + None = 0, + Setup = 1, + Mark = 2, + } + private ArgtypeOneofCase argtypeCase_ = ArgtypeOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ArgtypeOneofCase ArgtypeCase { + get { return argtypeCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearArgtype() { + argtypeCase_ = ArgtypeOneofCase.None; + argtype_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ServerArgs); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ServerArgs other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Setup, other.Setup)) return false; + if (!object.Equals(Mark, other.Mark)) return false; + if (ArgtypeCase != other.ArgtypeCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode(); + if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode(); + hash ^= (int) argtypeCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (argtypeCase_ == ArgtypeOneofCase.Setup) { + output.WriteRawTag(10); + output.WriteMessage(Setup); + } + if (argtypeCase_ == ArgtypeOneofCase.Mark) { + output.WriteRawTag(18); + output.WriteMessage(Mark); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (argtypeCase_ == ArgtypeOneofCase.Setup) { + output.WriteRawTag(10); + output.WriteMessage(Setup); + } + if (argtypeCase_ == ArgtypeOneofCase.Mark) { + output.WriteRawTag(18); + output.WriteMessage(Mark); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (argtypeCase_ == ArgtypeOneofCase.Setup) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Setup); + } + if (argtypeCase_ == ArgtypeOneofCase.Mark) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ServerArgs other) { + if (other == null) { + return; + } + switch (other.ArgtypeCase) { + case ArgtypeOneofCase.Setup: + if (Setup == null) { + Setup = new global::Grpc.Testing.ServerConfig(); + } + Setup.MergeFrom(other.Setup); + break; + case ArgtypeOneofCase.Mark: + if (Mark == null) { + Mark = new global::Grpc.Testing.Mark(); + } + Mark.MergeFrom(other.Mark); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + global::Grpc.Testing.ServerConfig subBuilder = new global::Grpc.Testing.ServerConfig(); + if (argtypeCase_ == ArgtypeOneofCase.Setup) { + subBuilder.MergeFrom(Setup); + } + input.ReadMessage(subBuilder); + Setup = subBuilder; + break; + } + case 18: { + global::Grpc.Testing.Mark subBuilder = new global::Grpc.Testing.Mark(); + if (argtypeCase_ == ArgtypeOneofCase.Mark) { + subBuilder.MergeFrom(Mark); + } + input.ReadMessage(subBuilder); + Mark = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + global::Grpc.Testing.ServerConfig subBuilder = new global::Grpc.Testing.ServerConfig(); + if (argtypeCase_ == ArgtypeOneofCase.Setup) { + subBuilder.MergeFrom(Setup); + } + input.ReadMessage(subBuilder); + Setup = subBuilder; + break; + } + case 18: { + global::Grpc.Testing.Mark subBuilder = new global::Grpc.Testing.Mark(); + if (argtypeCase_ == ArgtypeOneofCase.Mark) { + subBuilder.MergeFrom(Mark); + } + input.ReadMessage(subBuilder); + Mark = subBuilder; + break; + } + } + } + } + #endif + + } + + public sealed partial class ServerStatus : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServerStatus()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[11]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerStatus() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerStatus(ServerStatus other) : this() { + stats_ = other.stats_ != null ? other.stats_.Clone() : null; + port_ = other.port_; + cores_ = other.cores_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerStatus Clone() { + return new ServerStatus(this); + } + + /// Field number for the "stats" field. + public const int StatsFieldNumber = 1; + private global::Grpc.Testing.ServerStats stats_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ServerStats Stats { + get { return stats_; } + set { + stats_ = value; + } + } + + /// Field number for the "port" field. + public const int PortFieldNumber = 2; + private int port_; + /// + /// the port bound by the server + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int Port { + get { return port_; } + set { + port_ = value; + } + } + + /// Field number for the "cores" field. + public const int CoresFieldNumber = 3; + private int cores_; + /// + /// Number of cores available to the server + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int Cores { + get { return cores_; } + set { + cores_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ServerStatus); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ServerStatus other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Stats, other.Stats)) return false; + if (Port != other.Port) return false; + if (Cores != other.Cores) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (stats_ != null) hash ^= Stats.GetHashCode(); + if (Port != 0) hash ^= Port.GetHashCode(); + if (Cores != 0) hash ^= Cores.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (stats_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Stats); + } + if (Port != 0) { + output.WriteRawTag(16); + output.WriteInt32(Port); + } + if (Cores != 0) { + output.WriteRawTag(24); + output.WriteInt32(Cores); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (stats_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Stats); + } + if (Port != 0) { + output.WriteRawTag(16); + output.WriteInt32(Port); + } + if (Cores != 0) { + output.WriteRawTag(24); + output.WriteInt32(Cores); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (stats_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats); + } + if (Port != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Port); + } + if (Cores != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cores); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ServerStatus other) { + if (other == null) { + return; + } + if (other.stats_ != null) { + if (stats_ == null) { + Stats = new global::Grpc.Testing.ServerStats(); + } + Stats.MergeFrom(other.Stats); + } + if (other.Port != 0) { + Port = other.Port; + } + if (other.Cores != 0) { + Cores = other.Cores; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (stats_ == null) { + Stats = new global::Grpc.Testing.ServerStats(); + } + input.ReadMessage(Stats); + break; + } + case 16: { + Port = input.ReadInt32(); + break; + } + case 24: { + Cores = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (stats_ == null) { + Stats = new global::Grpc.Testing.ServerStats(); + } + input.ReadMessage(Stats); + break; + } + case 16: { + Port = input.ReadInt32(); + break; + } + case 24: { + Cores = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class CoreRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CoreRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[12]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CoreRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CoreRequest(CoreRequest other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CoreRequest Clone() { + return new CoreRequest(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as CoreRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(CoreRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(CoreRequest other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + } + } + } + #endif + + } + + public sealed partial class CoreResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CoreResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[13]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CoreResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CoreResponse(CoreResponse other) : this() { + cores_ = other.cores_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CoreResponse Clone() { + return new CoreResponse(this); + } + + /// Field number for the "cores" field. + public const int CoresFieldNumber = 1; + private int cores_; + /// + /// Number of cores available on the server + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int Cores { + get { return cores_; } + set { + cores_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as CoreResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(CoreResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Cores != other.Cores) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Cores != 0) hash ^= Cores.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Cores != 0) { + output.WriteRawTag(8); + output.WriteInt32(Cores); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Cores != 0) { + output.WriteRawTag(8); + output.WriteInt32(Cores); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Cores != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cores); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(CoreResponse other) { + if (other == null) { + return; + } + if (other.Cores != 0) { + Cores = other.Cores; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Cores = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Cores = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class Void : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Void()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[14]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Void() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Void(Void other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Void Clone() { + return new Void(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Void); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Void other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Void other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + } + } + } + #endif + + } + + /// + /// A single performance scenario: input to qps_json_driver + /// + public sealed partial class Scenario : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Scenario()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[15]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Scenario() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Scenario(Scenario other) : this() { + name_ = other.name_; + clientConfig_ = other.clientConfig_ != null ? other.clientConfig_.Clone() : null; + numClients_ = other.numClients_; + serverConfig_ = other.serverConfig_ != null ? other.serverConfig_.Clone() : null; + numServers_ = other.numServers_; + warmupSeconds_ = other.warmupSeconds_; + benchmarkSeconds_ = other.benchmarkSeconds_; + spawnLocalWorkerCount_ = other.spawnLocalWorkerCount_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Scenario Clone() { + return new Scenario(this); + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 1; + private string name_ = ""; + /// + /// Human readable name for this scenario + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "client_config" field. + public const int ClientConfigFieldNumber = 2; + private global::Grpc.Testing.ClientConfig clientConfig_; + /// + /// Client configuration + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ClientConfig ClientConfig { + get { return clientConfig_; } + set { + clientConfig_ = value; + } + } + + /// Field number for the "num_clients" field. + public const int NumClientsFieldNumber = 3; + private int numClients_; + /// + /// Number of clients to start for the test + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int NumClients { + get { return numClients_; } + set { + numClients_ = value; + } + } + + /// Field number for the "server_config" field. + public const int ServerConfigFieldNumber = 4; + private global::Grpc.Testing.ServerConfig serverConfig_; + /// + /// Server configuration + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ServerConfig ServerConfig { + get { return serverConfig_; } + set { + serverConfig_ = value; + } + } + + /// Field number for the "num_servers" field. + public const int NumServersFieldNumber = 5; + private int numServers_; + /// + /// Number of servers to start for the test + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int NumServers { + get { return numServers_; } + set { + numServers_ = value; + } + } + + /// Field number for the "warmup_seconds" field. + public const int WarmupSecondsFieldNumber = 6; + private int warmupSeconds_; + /// + /// Warmup period, in seconds + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int WarmupSeconds { + get { return warmupSeconds_; } + set { + warmupSeconds_ = value; + } + } + + /// Field number for the "benchmark_seconds" field. + public const int BenchmarkSecondsFieldNumber = 7; + private int benchmarkSeconds_; + /// + /// Benchmark time, in seconds + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int BenchmarkSeconds { + get { return benchmarkSeconds_; } + set { + benchmarkSeconds_ = value; + } + } + + /// Field number for the "spawn_local_worker_count" field. + public const int SpawnLocalWorkerCountFieldNumber = 8; + private int spawnLocalWorkerCount_; + /// + /// Number of workers to spawn locally (usually zero) + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int SpawnLocalWorkerCount { + get { return spawnLocalWorkerCount_; } + set { + spawnLocalWorkerCount_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Scenario); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Scenario other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Name != other.Name) return false; + if (!object.Equals(ClientConfig, other.ClientConfig)) return false; + if (NumClients != other.NumClients) return false; + if (!object.Equals(ServerConfig, other.ServerConfig)) return false; + if (NumServers != other.NumServers) return false; + if (WarmupSeconds != other.WarmupSeconds) return false; + if (BenchmarkSeconds != other.BenchmarkSeconds) return false; + if (SpawnLocalWorkerCount != other.SpawnLocalWorkerCount) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (clientConfig_ != null) hash ^= ClientConfig.GetHashCode(); + if (NumClients != 0) hash ^= NumClients.GetHashCode(); + if (serverConfig_ != null) hash ^= ServerConfig.GetHashCode(); + if (NumServers != 0) hash ^= NumServers.GetHashCode(); + if (WarmupSeconds != 0) hash ^= WarmupSeconds.GetHashCode(); + if (BenchmarkSeconds != 0) hash ^= BenchmarkSeconds.GetHashCode(); + if (SpawnLocalWorkerCount != 0) hash ^= SpawnLocalWorkerCount.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (clientConfig_ != null) { + output.WriteRawTag(18); + output.WriteMessage(ClientConfig); + } + if (NumClients != 0) { + output.WriteRawTag(24); + output.WriteInt32(NumClients); + } + if (serverConfig_ != null) { + output.WriteRawTag(34); + output.WriteMessage(ServerConfig); + } + if (NumServers != 0) { + output.WriteRawTag(40); + output.WriteInt32(NumServers); + } + if (WarmupSeconds != 0) { + output.WriteRawTag(48); + output.WriteInt32(WarmupSeconds); + } + if (BenchmarkSeconds != 0) { + output.WriteRawTag(56); + output.WriteInt32(BenchmarkSeconds); + } + if (SpawnLocalWorkerCount != 0) { + output.WriteRawTag(64); + output.WriteInt32(SpawnLocalWorkerCount); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (clientConfig_ != null) { + output.WriteRawTag(18); + output.WriteMessage(ClientConfig); + } + if (NumClients != 0) { + output.WriteRawTag(24); + output.WriteInt32(NumClients); + } + if (serverConfig_ != null) { + output.WriteRawTag(34); + output.WriteMessage(ServerConfig); + } + if (NumServers != 0) { + output.WriteRawTag(40); + output.WriteInt32(NumServers); + } + if (WarmupSeconds != 0) { + output.WriteRawTag(48); + output.WriteInt32(WarmupSeconds); + } + if (BenchmarkSeconds != 0) { + output.WriteRawTag(56); + output.WriteInt32(BenchmarkSeconds); + } + if (SpawnLocalWorkerCount != 0) { + output.WriteRawTag(64); + output.WriteInt32(SpawnLocalWorkerCount); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + if (clientConfig_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ClientConfig); + } + if (NumClients != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(NumClients); + } + if (serverConfig_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ServerConfig); + } + if (NumServers != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(NumServers); + } + if (WarmupSeconds != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(WarmupSeconds); + } + if (BenchmarkSeconds != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(BenchmarkSeconds); + } + if (SpawnLocalWorkerCount != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(SpawnLocalWorkerCount); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Scenario other) { + if (other == null) { + return; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + if (other.clientConfig_ != null) { + if (clientConfig_ == null) { + ClientConfig = new global::Grpc.Testing.ClientConfig(); + } + ClientConfig.MergeFrom(other.ClientConfig); + } + if (other.NumClients != 0) { + NumClients = other.NumClients; + } + if (other.serverConfig_ != null) { + if (serverConfig_ == null) { + ServerConfig = new global::Grpc.Testing.ServerConfig(); + } + ServerConfig.MergeFrom(other.ServerConfig); + } + if (other.NumServers != 0) { + NumServers = other.NumServers; + } + if (other.WarmupSeconds != 0) { + WarmupSeconds = other.WarmupSeconds; + } + if (other.BenchmarkSeconds != 0) { + BenchmarkSeconds = other.BenchmarkSeconds; + } + if (other.SpawnLocalWorkerCount != 0) { + SpawnLocalWorkerCount = other.SpawnLocalWorkerCount; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + if (clientConfig_ == null) { + ClientConfig = new global::Grpc.Testing.ClientConfig(); + } + input.ReadMessage(ClientConfig); + break; + } + case 24: { + NumClients = input.ReadInt32(); + break; + } + case 34: { + if (serverConfig_ == null) { + ServerConfig = new global::Grpc.Testing.ServerConfig(); + } + input.ReadMessage(ServerConfig); + break; + } + case 40: { + NumServers = input.ReadInt32(); + break; + } + case 48: { + WarmupSeconds = input.ReadInt32(); + break; + } + case 56: { + BenchmarkSeconds = input.ReadInt32(); + break; + } + case 64: { + SpawnLocalWorkerCount = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 18: { + if (clientConfig_ == null) { + ClientConfig = new global::Grpc.Testing.ClientConfig(); + } + input.ReadMessage(ClientConfig); + break; + } + case 24: { + NumClients = input.ReadInt32(); + break; + } + case 34: { + if (serverConfig_ == null) { + ServerConfig = new global::Grpc.Testing.ServerConfig(); + } + input.ReadMessage(ServerConfig); + break; + } + case 40: { + NumServers = input.ReadInt32(); + break; + } + case 48: { + WarmupSeconds = input.ReadInt32(); + break; + } + case 56: { + BenchmarkSeconds = input.ReadInt32(); + break; + } + case 64: { + SpawnLocalWorkerCount = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// A set of scenarios to be run with qps_json_driver + /// + public sealed partial class Scenarios : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Scenarios()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[16]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Scenarios() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Scenarios(Scenarios other) : this() { + scenarios_ = other.scenarios_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Scenarios Clone() { + return new Scenarios(this); + } + + /// Field number for the "scenarios" field. + public const int Scenarios_FieldNumber = 1; + private static readonly pb::FieldCodec _repeated_scenarios_codec + = pb::FieldCodec.ForMessage(10, global::Grpc.Testing.Scenario.Parser); + private readonly pbc::RepeatedField scenarios_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Scenarios_ { + get { return scenarios_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Scenarios); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Scenarios other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!scenarios_.Equals(other.scenarios_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + hash ^= scenarios_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + scenarios_.WriteTo(output, _repeated_scenarios_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + scenarios_.WriteTo(ref output, _repeated_scenarios_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + size += scenarios_.CalculateSize(_repeated_scenarios_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Scenarios other) { + if (other == null) { + return; + } + scenarios_.Add(other.scenarios_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + scenarios_.AddEntriesFrom(input, _repeated_scenarios_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + scenarios_.AddEntriesFrom(ref input, _repeated_scenarios_codec); + break; + } + } + } + } + #endif + + } + + /// + /// Basic summary that can be computed from ClientStats and ServerStats + /// once the scenario has finished. + /// + public sealed partial class ScenarioResultSummary : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ScenarioResultSummary()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[17]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ScenarioResultSummary() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ScenarioResultSummary(ScenarioResultSummary other) : this() { + qps_ = other.qps_; + qpsPerServerCore_ = other.qpsPerServerCore_; + serverSystemTime_ = other.serverSystemTime_; + serverUserTime_ = other.serverUserTime_; + clientSystemTime_ = other.clientSystemTime_; + clientUserTime_ = other.clientUserTime_; + latency50_ = other.latency50_; + latency90_ = other.latency90_; + latency95_ = other.latency95_; + latency99_ = other.latency99_; + latency999_ = other.latency999_; + serverCpuUsage_ = other.serverCpuUsage_; + successfulRequestsPerSecond_ = other.successfulRequestsPerSecond_; + failedRequestsPerSecond_ = other.failedRequestsPerSecond_; + clientPollsPerRequest_ = other.clientPollsPerRequest_; + serverPollsPerRequest_ = other.serverPollsPerRequest_; + serverQueriesPerCpuSec_ = other.serverQueriesPerCpuSec_; + clientQueriesPerCpuSec_ = other.clientQueriesPerCpuSec_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ScenarioResultSummary Clone() { + return new ScenarioResultSummary(this); + } + + /// Field number for the "qps" field. + public const int QpsFieldNumber = 1; + private double qps_; + /// + /// Total number of operations per second over all clients. What is counted as 1 'operation' depends on the benchmark scenarios: + /// For unary benchmarks, an operation is processing of a single unary RPC. + /// For streaming benchmarks, an operation is processing of a single ping pong of request and response. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double Qps { + get { return qps_; } + set { + qps_ = value; + } + } + + /// Field number for the "qps_per_server_core" field. + public const int QpsPerServerCoreFieldNumber = 2; + private double qpsPerServerCore_; + /// + /// QPS per server core. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double QpsPerServerCore { + get { return qpsPerServerCore_; } + set { + qpsPerServerCore_ = value; + } + } + + /// Field number for the "server_system_time" field. + public const int ServerSystemTimeFieldNumber = 3; + private double serverSystemTime_; + /// + /// The total server cpu load based on system time across all server processes, expressed as percentage of a single cpu core. + /// For example, 85 implies 85% of a cpu core, 125 implies 125% of a cpu core. Since we are accumulating the cpu load across all the server + /// processes, the value could > 100 when there are multiple servers or a single server using multiple threads and cores. + /// Same explanation for the total client cpu load below. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double ServerSystemTime { + get { return serverSystemTime_; } + set { + serverSystemTime_ = value; + } + } + + /// Field number for the "server_user_time" field. + public const int ServerUserTimeFieldNumber = 4; + private double serverUserTime_; + /// + /// The total server cpu load based on user time across all server processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%) + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double ServerUserTime { + get { return serverUserTime_; } + set { + serverUserTime_ = value; + } + } + + /// Field number for the "client_system_time" field. + public const int ClientSystemTimeFieldNumber = 5; + private double clientSystemTime_; + /// + /// The total client cpu load based on system time across all client processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%) + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double ClientSystemTime { + get { return clientSystemTime_; } + set { + clientSystemTime_ = value; + } + } + + /// Field number for the "client_user_time" field. + public const int ClientUserTimeFieldNumber = 6; + private double clientUserTime_; + /// + /// The total client cpu load based on user time across all client processes, expressed as percentage of a single cpu core. (85 => 85%, 125 => 125%) + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double ClientUserTime { + get { return clientUserTime_; } + set { + clientUserTime_ = value; + } + } + + /// Field number for the "latency_50" field. + public const int Latency50FieldNumber = 7; + private double latency50_; + /// + /// X% latency percentiles (in nanoseconds) + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double Latency50 { + get { return latency50_; } + set { + latency50_ = value; + } + } + + /// Field number for the "latency_90" field. + public const int Latency90FieldNumber = 8; + private double latency90_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double Latency90 { + get { return latency90_; } + set { + latency90_ = value; + } + } + + /// Field number for the "latency_95" field. + public const int Latency95FieldNumber = 9; + private double latency95_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double Latency95 { + get { return latency95_; } + set { + latency95_ = value; + } + } + + /// Field number for the "latency_99" field. + public const int Latency99FieldNumber = 10; + private double latency99_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double Latency99 { + get { return latency99_; } + set { + latency99_ = value; + } + } + + /// Field number for the "latency_999" field. + public const int Latency999FieldNumber = 11; + private double latency999_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double Latency999 { + get { return latency999_; } + set { + latency999_ = value; + } + } + + /// Field number for the "server_cpu_usage" field. + public const int ServerCpuUsageFieldNumber = 12; + private double serverCpuUsage_; + /// + /// server cpu usage percentage + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double ServerCpuUsage { + get { return serverCpuUsage_; } + set { + serverCpuUsage_ = value; + } + } + + /// Field number for the "successful_requests_per_second" field. + public const int SuccessfulRequestsPerSecondFieldNumber = 13; + private double successfulRequestsPerSecond_; + /// + /// Number of requests that succeeded/failed + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double SuccessfulRequestsPerSecond { + get { return successfulRequestsPerSecond_; } + set { + successfulRequestsPerSecond_ = value; + } + } + + /// Field number for the "failed_requests_per_second" field. + public const int FailedRequestsPerSecondFieldNumber = 14; + private double failedRequestsPerSecond_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double FailedRequestsPerSecond { + get { return failedRequestsPerSecond_; } + set { + failedRequestsPerSecond_ = value; + } + } + + /// Field number for the "client_polls_per_request" field. + public const int ClientPollsPerRequestFieldNumber = 15; + private double clientPollsPerRequest_; + /// + /// Number of polls called inside completion queue per request + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double ClientPollsPerRequest { + get { return clientPollsPerRequest_; } + set { + clientPollsPerRequest_ = value; + } + } + + /// Field number for the "server_polls_per_request" field. + public const int ServerPollsPerRequestFieldNumber = 16; + private double serverPollsPerRequest_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double ServerPollsPerRequest { + get { return serverPollsPerRequest_; } + set { + serverPollsPerRequest_ = value; + } + } + + /// Field number for the "server_queries_per_cpu_sec" field. + public const int ServerQueriesPerCpuSecFieldNumber = 17; + private double serverQueriesPerCpuSec_; + /// + /// Queries per CPU-sec over all servers or clients + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double ServerQueriesPerCpuSec { + get { return serverQueriesPerCpuSec_; } + set { + serverQueriesPerCpuSec_ = value; + } + } + + /// Field number for the "client_queries_per_cpu_sec" field. + public const int ClientQueriesPerCpuSecFieldNumber = 18; + private double clientQueriesPerCpuSec_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double ClientQueriesPerCpuSec { + get { return clientQueriesPerCpuSec_; } + set { + clientQueriesPerCpuSec_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ScenarioResultSummary); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ScenarioResultSummary other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Qps, other.Qps)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(QpsPerServerCore, other.QpsPerServerCore)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerSystemTime, other.ServerSystemTime)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerUserTime, other.ServerUserTime)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientSystemTime, other.ClientSystemTime)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientUserTime, other.ClientUserTime)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency50, other.Latency50)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency90, other.Latency90)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency95, other.Latency95)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency99, other.Latency99)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency999, other.Latency999)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerCpuUsage, other.ServerCpuUsage)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(SuccessfulRequestsPerSecond, other.SuccessfulRequestsPerSecond)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(FailedRequestsPerSecond, other.FailedRequestsPerSecond)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientPollsPerRequest, other.ClientPollsPerRequest)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerPollsPerRequest, other.ServerPollsPerRequest)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerQueriesPerCpuSec, other.ServerQueriesPerCpuSec)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientQueriesPerCpuSec, other.ClientQueriesPerCpuSec)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Qps != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Qps); + if (QpsPerServerCore != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(QpsPerServerCore); + if (ServerSystemTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerSystemTime); + if (ServerUserTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerUserTime); + if (ClientSystemTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientSystemTime); + if (ClientUserTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientUserTime); + if (Latency50 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency50); + if (Latency90 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency90); + if (Latency95 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency95); + if (Latency99 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency99); + if (Latency999 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency999); + if (ServerCpuUsage != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerCpuUsage); + if (SuccessfulRequestsPerSecond != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(SuccessfulRequestsPerSecond); + if (FailedRequestsPerSecond != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(FailedRequestsPerSecond); + if (ClientPollsPerRequest != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientPollsPerRequest); + if (ServerPollsPerRequest != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerPollsPerRequest); + if (ServerQueriesPerCpuSec != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerQueriesPerCpuSec); + if (ClientQueriesPerCpuSec != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientQueriesPerCpuSec); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Qps != 0D) { + output.WriteRawTag(9); + output.WriteDouble(Qps); + } + if (QpsPerServerCore != 0D) { + output.WriteRawTag(17); + output.WriteDouble(QpsPerServerCore); + } + if (ServerSystemTime != 0D) { + output.WriteRawTag(25); + output.WriteDouble(ServerSystemTime); + } + if (ServerUserTime != 0D) { + output.WriteRawTag(33); + output.WriteDouble(ServerUserTime); + } + if (ClientSystemTime != 0D) { + output.WriteRawTag(41); + output.WriteDouble(ClientSystemTime); + } + if (ClientUserTime != 0D) { + output.WriteRawTag(49); + output.WriteDouble(ClientUserTime); + } + if (Latency50 != 0D) { + output.WriteRawTag(57); + output.WriteDouble(Latency50); + } + if (Latency90 != 0D) { + output.WriteRawTag(65); + output.WriteDouble(Latency90); + } + if (Latency95 != 0D) { + output.WriteRawTag(73); + output.WriteDouble(Latency95); + } + if (Latency99 != 0D) { + output.WriteRawTag(81); + output.WriteDouble(Latency99); + } + if (Latency999 != 0D) { + output.WriteRawTag(89); + output.WriteDouble(Latency999); + } + if (ServerCpuUsage != 0D) { + output.WriteRawTag(97); + output.WriteDouble(ServerCpuUsage); + } + if (SuccessfulRequestsPerSecond != 0D) { + output.WriteRawTag(105); + output.WriteDouble(SuccessfulRequestsPerSecond); + } + if (FailedRequestsPerSecond != 0D) { + output.WriteRawTag(113); + output.WriteDouble(FailedRequestsPerSecond); + } + if (ClientPollsPerRequest != 0D) { + output.WriteRawTag(121); + output.WriteDouble(ClientPollsPerRequest); + } + if (ServerPollsPerRequest != 0D) { + output.WriteRawTag(129, 1); + output.WriteDouble(ServerPollsPerRequest); + } + if (ServerQueriesPerCpuSec != 0D) { + output.WriteRawTag(137, 1); + output.WriteDouble(ServerQueriesPerCpuSec); + } + if (ClientQueriesPerCpuSec != 0D) { + output.WriteRawTag(145, 1); + output.WriteDouble(ClientQueriesPerCpuSec); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Qps != 0D) { + output.WriteRawTag(9); + output.WriteDouble(Qps); + } + if (QpsPerServerCore != 0D) { + output.WriteRawTag(17); + output.WriteDouble(QpsPerServerCore); + } + if (ServerSystemTime != 0D) { + output.WriteRawTag(25); + output.WriteDouble(ServerSystemTime); + } + if (ServerUserTime != 0D) { + output.WriteRawTag(33); + output.WriteDouble(ServerUserTime); + } + if (ClientSystemTime != 0D) { + output.WriteRawTag(41); + output.WriteDouble(ClientSystemTime); + } + if (ClientUserTime != 0D) { + output.WriteRawTag(49); + output.WriteDouble(ClientUserTime); + } + if (Latency50 != 0D) { + output.WriteRawTag(57); + output.WriteDouble(Latency50); + } + if (Latency90 != 0D) { + output.WriteRawTag(65); + output.WriteDouble(Latency90); + } + if (Latency95 != 0D) { + output.WriteRawTag(73); + output.WriteDouble(Latency95); + } + if (Latency99 != 0D) { + output.WriteRawTag(81); + output.WriteDouble(Latency99); + } + if (Latency999 != 0D) { + output.WriteRawTag(89); + output.WriteDouble(Latency999); + } + if (ServerCpuUsage != 0D) { + output.WriteRawTag(97); + output.WriteDouble(ServerCpuUsage); + } + if (SuccessfulRequestsPerSecond != 0D) { + output.WriteRawTag(105); + output.WriteDouble(SuccessfulRequestsPerSecond); + } + if (FailedRequestsPerSecond != 0D) { + output.WriteRawTag(113); + output.WriteDouble(FailedRequestsPerSecond); + } + if (ClientPollsPerRequest != 0D) { + output.WriteRawTag(121); + output.WriteDouble(ClientPollsPerRequest); + } + if (ServerPollsPerRequest != 0D) { + output.WriteRawTag(129, 1); + output.WriteDouble(ServerPollsPerRequest); + } + if (ServerQueriesPerCpuSec != 0D) { + output.WriteRawTag(137, 1); + output.WriteDouble(ServerQueriesPerCpuSec); + } + if (ClientQueriesPerCpuSec != 0D) { + output.WriteRawTag(145, 1); + output.WriteDouble(ClientQueriesPerCpuSec); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Qps != 0D) { + size += 1 + 8; + } + if (QpsPerServerCore != 0D) { + size += 1 + 8; + } + if (ServerSystemTime != 0D) { + size += 1 + 8; + } + if (ServerUserTime != 0D) { + size += 1 + 8; + } + if (ClientSystemTime != 0D) { + size += 1 + 8; + } + if (ClientUserTime != 0D) { + size += 1 + 8; + } + if (Latency50 != 0D) { + size += 1 + 8; + } + if (Latency90 != 0D) { + size += 1 + 8; + } + if (Latency95 != 0D) { + size += 1 + 8; + } + if (Latency99 != 0D) { + size += 1 + 8; + } + if (Latency999 != 0D) { + size += 1 + 8; + } + if (ServerCpuUsage != 0D) { + size += 1 + 8; + } + if (SuccessfulRequestsPerSecond != 0D) { + size += 1 + 8; + } + if (FailedRequestsPerSecond != 0D) { + size += 1 + 8; + } + if (ClientPollsPerRequest != 0D) { + size += 1 + 8; + } + if (ServerPollsPerRequest != 0D) { + size += 2 + 8; + } + if (ServerQueriesPerCpuSec != 0D) { + size += 2 + 8; + } + if (ClientQueriesPerCpuSec != 0D) { + size += 2 + 8; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ScenarioResultSummary other) { + if (other == null) { + return; + } + if (other.Qps != 0D) { + Qps = other.Qps; + } + if (other.QpsPerServerCore != 0D) { + QpsPerServerCore = other.QpsPerServerCore; + } + if (other.ServerSystemTime != 0D) { + ServerSystemTime = other.ServerSystemTime; + } + if (other.ServerUserTime != 0D) { + ServerUserTime = other.ServerUserTime; + } + if (other.ClientSystemTime != 0D) { + ClientSystemTime = other.ClientSystemTime; + } + if (other.ClientUserTime != 0D) { + ClientUserTime = other.ClientUserTime; + } + if (other.Latency50 != 0D) { + Latency50 = other.Latency50; + } + if (other.Latency90 != 0D) { + Latency90 = other.Latency90; + } + if (other.Latency95 != 0D) { + Latency95 = other.Latency95; + } + if (other.Latency99 != 0D) { + Latency99 = other.Latency99; + } + if (other.Latency999 != 0D) { + Latency999 = other.Latency999; + } + if (other.ServerCpuUsage != 0D) { + ServerCpuUsage = other.ServerCpuUsage; + } + if (other.SuccessfulRequestsPerSecond != 0D) { + SuccessfulRequestsPerSecond = other.SuccessfulRequestsPerSecond; + } + if (other.FailedRequestsPerSecond != 0D) { + FailedRequestsPerSecond = other.FailedRequestsPerSecond; + } + if (other.ClientPollsPerRequest != 0D) { + ClientPollsPerRequest = other.ClientPollsPerRequest; + } + if (other.ServerPollsPerRequest != 0D) { + ServerPollsPerRequest = other.ServerPollsPerRequest; + } + if (other.ServerQueriesPerCpuSec != 0D) { + ServerQueriesPerCpuSec = other.ServerQueriesPerCpuSec; + } + if (other.ClientQueriesPerCpuSec != 0D) { + ClientQueriesPerCpuSec = other.ClientQueriesPerCpuSec; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 9: { + Qps = input.ReadDouble(); + break; + } + case 17: { + QpsPerServerCore = input.ReadDouble(); + break; + } + case 25: { + ServerSystemTime = input.ReadDouble(); + break; + } + case 33: { + ServerUserTime = input.ReadDouble(); + break; + } + case 41: { + ClientSystemTime = input.ReadDouble(); + break; + } + case 49: { + ClientUserTime = input.ReadDouble(); + break; + } + case 57: { + Latency50 = input.ReadDouble(); + break; + } + case 65: { + Latency90 = input.ReadDouble(); + break; + } + case 73: { + Latency95 = input.ReadDouble(); + break; + } + case 81: { + Latency99 = input.ReadDouble(); + break; + } + case 89: { + Latency999 = input.ReadDouble(); + break; + } + case 97: { + ServerCpuUsage = input.ReadDouble(); + break; + } + case 105: { + SuccessfulRequestsPerSecond = input.ReadDouble(); + break; + } + case 113: { + FailedRequestsPerSecond = input.ReadDouble(); + break; + } + case 121: { + ClientPollsPerRequest = input.ReadDouble(); + break; + } + case 129: { + ServerPollsPerRequest = input.ReadDouble(); + break; + } + case 137: { + ServerQueriesPerCpuSec = input.ReadDouble(); + break; + } + case 145: { + ClientQueriesPerCpuSec = input.ReadDouble(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 9: { + Qps = input.ReadDouble(); + break; + } + case 17: { + QpsPerServerCore = input.ReadDouble(); + break; + } + case 25: { + ServerSystemTime = input.ReadDouble(); + break; + } + case 33: { + ServerUserTime = input.ReadDouble(); + break; + } + case 41: { + ClientSystemTime = input.ReadDouble(); + break; + } + case 49: { + ClientUserTime = input.ReadDouble(); + break; + } + case 57: { + Latency50 = input.ReadDouble(); + break; + } + case 65: { + Latency90 = input.ReadDouble(); + break; + } + case 73: { + Latency95 = input.ReadDouble(); + break; + } + case 81: { + Latency99 = input.ReadDouble(); + break; + } + case 89: { + Latency999 = input.ReadDouble(); + break; + } + case 97: { + ServerCpuUsage = input.ReadDouble(); + break; + } + case 105: { + SuccessfulRequestsPerSecond = input.ReadDouble(); + break; + } + case 113: { + FailedRequestsPerSecond = input.ReadDouble(); + break; + } + case 121: { + ClientPollsPerRequest = input.ReadDouble(); + break; + } + case 129: { + ServerPollsPerRequest = input.ReadDouble(); + break; + } + case 137: { + ServerQueriesPerCpuSec = input.ReadDouble(); + break; + } + case 145: { + ClientQueriesPerCpuSec = input.ReadDouble(); + break; + } + } + } + } + #endif + + } + + /// + /// Results of a single benchmark scenario. + /// + public sealed partial class ScenarioResult : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ScenarioResult()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ControlReflection.Descriptor.MessageTypes[18]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ScenarioResult() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ScenarioResult(ScenarioResult other) : this() { + scenario_ = other.scenario_ != null ? other.scenario_.Clone() : null; + latencies_ = other.latencies_ != null ? other.latencies_.Clone() : null; + clientStats_ = other.clientStats_.Clone(); + serverStats_ = other.serverStats_.Clone(); + serverCores_ = other.serverCores_.Clone(); + summary_ = other.summary_ != null ? other.summary_.Clone() : null; + clientSuccess_ = other.clientSuccess_.Clone(); + serverSuccess_ = other.serverSuccess_.Clone(); + requestResults_ = other.requestResults_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ScenarioResult Clone() { + return new ScenarioResult(this); + } + + /// Field number for the "scenario" field. + public const int ScenarioFieldNumber = 1; + private global::Grpc.Testing.Scenario scenario_; + /// + /// Inputs used to run the scenario. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.Scenario Scenario { + get { return scenario_; } + set { + scenario_ = value; + } + } + + /// Field number for the "latencies" field. + public const int LatenciesFieldNumber = 2; + private global::Grpc.Testing.HistogramData latencies_; + /// + /// Histograms from all clients merged into one histogram. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.HistogramData Latencies { + get { return latencies_; } + set { + latencies_ = value; + } + } + + /// Field number for the "client_stats" field. + public const int ClientStatsFieldNumber = 3; + private static readonly pb::FieldCodec _repeated_clientStats_codec + = pb::FieldCodec.ForMessage(26, global::Grpc.Testing.ClientStats.Parser); + private readonly pbc::RepeatedField clientStats_ = new pbc::RepeatedField(); + /// + /// Client stats for each client + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField ClientStats { + get { return clientStats_; } + } + + /// Field number for the "server_stats" field. + public const int ServerStatsFieldNumber = 4; + private static readonly pb::FieldCodec _repeated_serverStats_codec + = pb::FieldCodec.ForMessage(34, global::Grpc.Testing.ServerStats.Parser); + private readonly pbc::RepeatedField serverStats_ = new pbc::RepeatedField(); + /// + /// Server stats for each server + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField ServerStats { + get { return serverStats_; } + } + + /// Field number for the "server_cores" field. + public const int ServerCoresFieldNumber = 5; + private static readonly pb::FieldCodec _repeated_serverCores_codec + = pb::FieldCodec.ForInt32(42); + private readonly pbc::RepeatedField serverCores_ = new pbc::RepeatedField(); + /// + /// Number of cores available to each server + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField ServerCores { + get { return serverCores_; } + } + + /// Field number for the "summary" field. + public const int SummaryFieldNumber = 6; + private global::Grpc.Testing.ScenarioResultSummary summary_; + /// + /// An after-the-fact computed summary + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ScenarioResultSummary Summary { + get { return summary_; } + set { + summary_ = value; + } + } + + /// Field number for the "client_success" field. + public const int ClientSuccessFieldNumber = 7; + private static readonly pb::FieldCodec _repeated_clientSuccess_codec + = pb::FieldCodec.ForBool(58); + private readonly pbc::RepeatedField clientSuccess_ = new pbc::RepeatedField(); + /// + /// Information on success or failure of each worker + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField ClientSuccess { + get { return clientSuccess_; } + } + + /// Field number for the "server_success" field. + public const int ServerSuccessFieldNumber = 8; + private static readonly pb::FieldCodec _repeated_serverSuccess_codec + = pb::FieldCodec.ForBool(66); + private readonly pbc::RepeatedField serverSuccess_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField ServerSuccess { + get { return serverSuccess_; } + } + + /// Field number for the "request_results" field. + public const int RequestResultsFieldNumber = 9; + private static readonly pb::FieldCodec _repeated_requestResults_codec + = pb::FieldCodec.ForMessage(74, global::Grpc.Testing.RequestResultCount.Parser); + private readonly pbc::RepeatedField requestResults_ = new pbc::RepeatedField(); + /// + /// Number of failed requests (one row per status code seen) + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField RequestResults { + get { return requestResults_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ScenarioResult); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ScenarioResult other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Scenario, other.Scenario)) return false; + if (!object.Equals(Latencies, other.Latencies)) return false; + if(!clientStats_.Equals(other.clientStats_)) return false; + if(!serverStats_.Equals(other.serverStats_)) return false; + if(!serverCores_.Equals(other.serverCores_)) return false; + if (!object.Equals(Summary, other.Summary)) return false; + if(!clientSuccess_.Equals(other.clientSuccess_)) return false; + if(!serverSuccess_.Equals(other.serverSuccess_)) return false; + if(!requestResults_.Equals(other.requestResults_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (scenario_ != null) hash ^= Scenario.GetHashCode(); + if (latencies_ != null) hash ^= Latencies.GetHashCode(); + hash ^= clientStats_.GetHashCode(); + hash ^= serverStats_.GetHashCode(); + hash ^= serverCores_.GetHashCode(); + if (summary_ != null) hash ^= Summary.GetHashCode(); + hash ^= clientSuccess_.GetHashCode(); + hash ^= serverSuccess_.GetHashCode(); + hash ^= requestResults_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (scenario_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Scenario); + } + if (latencies_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Latencies); + } + clientStats_.WriteTo(output, _repeated_clientStats_codec); + serverStats_.WriteTo(output, _repeated_serverStats_codec); + serverCores_.WriteTo(output, _repeated_serverCores_codec); + if (summary_ != null) { + output.WriteRawTag(50); + output.WriteMessage(Summary); + } + clientSuccess_.WriteTo(output, _repeated_clientSuccess_codec); + serverSuccess_.WriteTo(output, _repeated_serverSuccess_codec); + requestResults_.WriteTo(output, _repeated_requestResults_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (scenario_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Scenario); + } + if (latencies_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Latencies); + } + clientStats_.WriteTo(ref output, _repeated_clientStats_codec); + serverStats_.WriteTo(ref output, _repeated_serverStats_codec); + serverCores_.WriteTo(ref output, _repeated_serverCores_codec); + if (summary_ != null) { + output.WriteRawTag(50); + output.WriteMessage(Summary); + } + clientSuccess_.WriteTo(ref output, _repeated_clientSuccess_codec); + serverSuccess_.WriteTo(ref output, _repeated_serverSuccess_codec); + requestResults_.WriteTo(ref output, _repeated_requestResults_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (scenario_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Scenario); + } + if (latencies_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Latencies); + } + size += clientStats_.CalculateSize(_repeated_clientStats_codec); + size += serverStats_.CalculateSize(_repeated_serverStats_codec); + size += serverCores_.CalculateSize(_repeated_serverCores_codec); + if (summary_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Summary); + } + size += clientSuccess_.CalculateSize(_repeated_clientSuccess_codec); + size += serverSuccess_.CalculateSize(_repeated_serverSuccess_codec); + size += requestResults_.CalculateSize(_repeated_requestResults_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ScenarioResult other) { + if (other == null) { + return; + } + if (other.scenario_ != null) { + if (scenario_ == null) { + Scenario = new global::Grpc.Testing.Scenario(); + } + Scenario.MergeFrom(other.Scenario); + } + if (other.latencies_ != null) { + if (latencies_ == null) { + Latencies = new global::Grpc.Testing.HistogramData(); + } + Latencies.MergeFrom(other.Latencies); + } + clientStats_.Add(other.clientStats_); + serverStats_.Add(other.serverStats_); + serverCores_.Add(other.serverCores_); + if (other.summary_ != null) { + if (summary_ == null) { + Summary = new global::Grpc.Testing.ScenarioResultSummary(); + } + Summary.MergeFrom(other.Summary); + } + clientSuccess_.Add(other.clientSuccess_); + serverSuccess_.Add(other.serverSuccess_); + requestResults_.Add(other.requestResults_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (scenario_ == null) { + Scenario = new global::Grpc.Testing.Scenario(); + } + input.ReadMessage(Scenario); + break; + } + case 18: { + if (latencies_ == null) { + Latencies = new global::Grpc.Testing.HistogramData(); + } + input.ReadMessage(Latencies); + break; + } + case 26: { + clientStats_.AddEntriesFrom(input, _repeated_clientStats_codec); + break; + } + case 34: { + serverStats_.AddEntriesFrom(input, _repeated_serverStats_codec); + break; + } + case 42: + case 40: { + serverCores_.AddEntriesFrom(input, _repeated_serverCores_codec); + break; + } + case 50: { + if (summary_ == null) { + Summary = new global::Grpc.Testing.ScenarioResultSummary(); + } + input.ReadMessage(Summary); + break; + } + case 58: + case 56: { + clientSuccess_.AddEntriesFrom(input, _repeated_clientSuccess_codec); + break; + } + case 66: + case 64: { + serverSuccess_.AddEntriesFrom(input, _repeated_serverSuccess_codec); + break; + } + case 74: { + requestResults_.AddEntriesFrom(input, _repeated_requestResults_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (scenario_ == null) { + Scenario = new global::Grpc.Testing.Scenario(); + } + input.ReadMessage(Scenario); + break; + } + case 18: { + if (latencies_ == null) { + Latencies = new global::Grpc.Testing.HistogramData(); + } + input.ReadMessage(Latencies); + break; + } + case 26: { + clientStats_.AddEntriesFrom(ref input, _repeated_clientStats_codec); + break; + } + case 34: { + serverStats_.AddEntriesFrom(ref input, _repeated_serverStats_codec); + break; + } + case 42: + case 40: { + serverCores_.AddEntriesFrom(ref input, _repeated_serverCores_codec); + break; + } + case 50: { + if (summary_ == null) { + Summary = new global::Grpc.Testing.ScenarioResultSummary(); + } + input.ReadMessage(Summary); + break; + } + case 58: + case 56: { + clientSuccess_.AddEntriesFrom(ref input, _repeated_clientSuccess_codec); + break; + } + case 66: + case 64: { + serverSuccess_.AddEntriesFrom(ref input, _repeated_serverSuccess_codec); + break; + } + case 74: { + requestResults_.AddEntriesFrom(ref input, _repeated_requestResults_codec); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.IntegrationTesting/ControlExtensions.cs b/src/csharp/Grpc.IntegrationTesting/ControlExtensions.cs new file mode 100644 index 00000000..67f5faed --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/ControlExtensions.cs @@ -0,0 +1,43 @@ +#region Copyright notice and license + +// Copyright 2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using Grpc.Core; +using Grpc.Testing; + +namespace Grpc.IntegrationTesting +{ + /// + /// Helpers for Control.cs + /// + public static class ControlExtensions + { + public static ChannelOption ToChannelOption(this ChannelArg channelArgument) + { + switch (channelArgument.ValueCase) + { + case ChannelArg.ValueOneofCase.StrValue: + return new ChannelOption(channelArgument.Name, channelArgument.StrValue); + case ChannelArg.ValueOneofCase.IntValue: + return new ChannelOption(channelArgument.Name, channelArgument.IntValue); + default: + throw new ArgumentException("Unsupported channel argument value."); + } + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/CoreStats/Stats.cs b/src/csharp/Grpc.IntegrationTesting/CoreStats/Stats.cs new file mode 100644 index 00000000..2f877f15 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/CoreStats/Stats.cs @@ -0,0 +1,941 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: grpc/core/stats.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Core { + + /// Holder for reflection information generated from grpc/core/stats.proto + public static partial class StatsReflection { + + #region Descriptor + /// File descriptor for grpc/core/stats.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static StatsReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "ChVncnBjL2NvcmUvc3RhdHMucHJvdG8SCWdycGMuY29yZSImCgZCdWNrZXQS", + "DQoFc3RhcnQYASABKAESDQoFY291bnQYAiABKAQiLwoJSGlzdG9ncmFtEiIK", + "B2J1Y2tldHMYASADKAsyES5ncnBjLmNvcmUuQnVja2V0IlsKBk1ldHJpYxIM", + "CgRuYW1lGAEgASgJEg8KBWNvdW50GAogASgESAASKQoJaGlzdG9ncmFtGAsg", + "ASgLMhQuZ3JwYy5jb3JlLkhpc3RvZ3JhbUgAQgcKBXZhbHVlIisKBVN0YXRz", + "EiIKB21ldHJpY3MYASADKAsyES5ncnBjLmNvcmUuTWV0cmljYgZwcm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Core.Bucket), global::Grpc.Core.Bucket.Parser, new[]{ "Start", "Count" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Core.Histogram), global::Grpc.Core.Histogram.Parser, new[]{ "Buckets" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Core.Metric), global::Grpc.Core.Metric.Parser, new[]{ "Name", "Count", "Histogram" }, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Core.Stats), global::Grpc.Core.Stats.Parser, new[]{ "Metrics" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class Bucket : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Bucket()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Core.StatsReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Bucket() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Bucket(Bucket other) : this() { + start_ = other.start_; + count_ = other.count_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Bucket Clone() { + return new Bucket(this); + } + + /// Field number for the "start" field. + public const int StartFieldNumber = 1; + private double start_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double Start { + get { return start_; } + set { + start_ = value; + } + } + + /// Field number for the "count" field. + public const int CountFieldNumber = 2; + private ulong count_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ulong Count { + get { return count_; } + set { + count_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Bucket); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Bucket other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Start, other.Start)) return false; + if (Count != other.Count) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Start != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Start); + if (Count != 0UL) hash ^= Count.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Start != 0D) { + output.WriteRawTag(9); + output.WriteDouble(Start); + } + if (Count != 0UL) { + output.WriteRawTag(16); + output.WriteUInt64(Count); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Start != 0D) { + output.WriteRawTag(9); + output.WriteDouble(Start); + } + if (Count != 0UL) { + output.WriteRawTag(16); + output.WriteUInt64(Count); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Start != 0D) { + size += 1 + 8; + } + if (Count != 0UL) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Count); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Bucket other) { + if (other == null) { + return; + } + if (other.Start != 0D) { + Start = other.Start; + } + if (other.Count != 0UL) { + Count = other.Count; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 9: { + Start = input.ReadDouble(); + break; + } + case 16: { + Count = input.ReadUInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 9: { + Start = input.ReadDouble(); + break; + } + case 16: { + Count = input.ReadUInt64(); + break; + } + } + } + } + #endif + + } + + public sealed partial class Histogram : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Histogram()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Core.StatsReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Histogram() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Histogram(Histogram other) : this() { + buckets_ = other.buckets_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Histogram Clone() { + return new Histogram(this); + } + + /// Field number for the "buckets" field. + public const int BucketsFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_buckets_codec + = pb::FieldCodec.ForMessage(10, global::Grpc.Core.Bucket.Parser); + private readonly pbc::RepeatedField buckets_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Buckets { + get { return buckets_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Histogram); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Histogram other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!buckets_.Equals(other.buckets_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + hash ^= buckets_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + buckets_.WriteTo(output, _repeated_buckets_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + buckets_.WriteTo(ref output, _repeated_buckets_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + size += buckets_.CalculateSize(_repeated_buckets_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Histogram other) { + if (other == null) { + return; + } + buckets_.Add(other.buckets_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + buckets_.AddEntriesFrom(input, _repeated_buckets_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + buckets_.AddEntriesFrom(ref input, _repeated_buckets_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class Metric : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Metric()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Core.StatsReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Metric() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Metric(Metric other) : this() { + name_ = other.name_; + switch (other.ValueCase) { + case ValueOneofCase.Count: + Count = other.Count; + break; + case ValueOneofCase.Histogram: + Histogram = other.Histogram.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Metric Clone() { + return new Metric(this); + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 1; + private string name_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "count" field. + public const int CountFieldNumber = 10; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ulong Count { + get { return valueCase_ == ValueOneofCase.Count ? (ulong) value_ : 0UL; } + set { + value_ = value; + valueCase_ = ValueOneofCase.Count; + } + } + + /// Field number for the "histogram" field. + public const int HistogramFieldNumber = 11; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Core.Histogram Histogram { + get { return valueCase_ == ValueOneofCase.Histogram ? (global::Grpc.Core.Histogram) value_ : null; } + set { + value_ = value; + valueCase_ = value == null ? ValueOneofCase.None : ValueOneofCase.Histogram; + } + } + + private object value_; + /// Enum of possible cases for the "value" oneof. + public enum ValueOneofCase { + None = 0, + Count = 10, + Histogram = 11, + } + private ValueOneofCase valueCase_ = ValueOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ValueOneofCase ValueCase { + get { return valueCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearValue() { + valueCase_ = ValueOneofCase.None; + value_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Metric); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Metric other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Name != other.Name) return false; + if (Count != other.Count) return false; + if (!object.Equals(Histogram, other.Histogram)) return false; + if (ValueCase != other.ValueCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (valueCase_ == ValueOneofCase.Count) hash ^= Count.GetHashCode(); + if (valueCase_ == ValueOneofCase.Histogram) hash ^= Histogram.GetHashCode(); + hash ^= (int) valueCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (valueCase_ == ValueOneofCase.Count) { + output.WriteRawTag(80); + output.WriteUInt64(Count); + } + if (valueCase_ == ValueOneofCase.Histogram) { + output.WriteRawTag(90); + output.WriteMessage(Histogram); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (valueCase_ == ValueOneofCase.Count) { + output.WriteRawTag(80); + output.WriteUInt64(Count); + } + if (valueCase_ == ValueOneofCase.Histogram) { + output.WriteRawTag(90); + output.WriteMessage(Histogram); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + if (valueCase_ == ValueOneofCase.Count) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Count); + } + if (valueCase_ == ValueOneofCase.Histogram) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Histogram); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Metric other) { + if (other == null) { + return; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + switch (other.ValueCase) { + case ValueOneofCase.Count: + Count = other.Count; + break; + case ValueOneofCase.Histogram: + if (Histogram == null) { + Histogram = new global::Grpc.Core.Histogram(); + } + Histogram.MergeFrom(other.Histogram); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 80: { + Count = input.ReadUInt64(); + break; + } + case 90: { + global::Grpc.Core.Histogram subBuilder = new global::Grpc.Core.Histogram(); + if (valueCase_ == ValueOneofCase.Histogram) { + subBuilder.MergeFrom(Histogram); + } + input.ReadMessage(subBuilder); + Histogram = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 80: { + Count = input.ReadUInt64(); + break; + } + case 90: { + global::Grpc.Core.Histogram subBuilder = new global::Grpc.Core.Histogram(); + if (valueCase_ == ValueOneofCase.Histogram) { + subBuilder.MergeFrom(Histogram); + } + input.ReadMessage(subBuilder); + Histogram = subBuilder; + break; + } + } + } + } + #endif + + } + + public sealed partial class Stats : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Stats()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Core.StatsReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Stats() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Stats(Stats other) : this() { + metrics_ = other.metrics_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Stats Clone() { + return new Stats(this); + } + + /// Field number for the "metrics" field. + public const int MetricsFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_metrics_codec + = pb::FieldCodec.ForMessage(10, global::Grpc.Core.Metric.Parser); + private readonly pbc::RepeatedField metrics_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Metrics { + get { return metrics_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Stats); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Stats other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!metrics_.Equals(other.metrics_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + hash ^= metrics_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + metrics_.WriteTo(output, _repeated_metrics_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + metrics_.WriteTo(ref output, _repeated_metrics_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + size += metrics_.CalculateSize(_repeated_metrics_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Stats other) { + if (other == null) { + return; + } + metrics_.Add(other.metrics_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + metrics_.AddEntriesFrom(input, _repeated_metrics_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + metrics_.AddEntriesFrom(ref input, _repeated_metrics_codec); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.IntegrationTesting/CustomErrorDetailsTest.cs b/src/csharp/Grpc.IntegrationTesting/CustomErrorDetailsTest.cs new file mode 100644 index 00000000..5d22d77a --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/CustomErrorDetailsTest.cs @@ -0,0 +1,129 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Google.Protobuf; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Testing; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + /// + /// Shows how to attach custom error details as a binary trailer. + /// + public class CustomErrorDetailsTest + { + const string DebugInfoTrailerName = "debug-info-bin"; + const string ExceptionDetail = "Exception thrown on purpose."; + const string Host = "localhost"; + Server server; + Channel channel; + TestService.TestServiceClient client; + + [OneTimeSetUp] + public void Init() + { + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { TestService.BindService(new CustomErrorDetailsTestServiceImpl()) }, + Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } + }; + server.Start(); + + channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure); + client = new TestService.TestServiceClient(channel); + } + + [OneTimeTearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public async Task ErrorDetailsFromCallObject() + { + var call = client.UnaryCallAsync(new SimpleRequest { ResponseSize = 10 }); + + try + { + await call.ResponseAsync; + Assert.Fail(); + } + catch (RpcException e) + { + Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode); + var debugInfo = GetDebugInfo(call.GetTrailers()); + Assert.AreEqual(debugInfo.Detail, ExceptionDetail); + Assert.IsNotEmpty(debugInfo.StackEntries); + } + } + + [Test] + public async Task ErrorDetailsFromRpcException() + { + try + { + await client.UnaryCallAsync(new SimpleRequest { ResponseSize = 10 }); + Assert.Fail(); + } + catch (RpcException e) + { + Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode); + var debugInfo = GetDebugInfo(e.Trailers); + Assert.AreEqual(debugInfo.Detail, ExceptionDetail); + Assert.IsNotEmpty(debugInfo.StackEntries); + } + } + + private static DebugInfo GetDebugInfo(Metadata trailers) + { + var entry = trailers.First((e) => e.Key == DebugInfoTrailerName); + return DebugInfo.Parser.ParseFrom(entry.ValueBytes); + } + + private class CustomErrorDetailsTestServiceImpl : TestService.TestServiceBase + { + public override Task UnaryCall(SimpleRequest request, ServerCallContext context) + { + try + { + throw new ArgumentException(ExceptionDetail); + } + catch (Exception e) + { + // Fill debug info with some structured details about the failure. + var debugInfo = new DebugInfo(); + debugInfo.Detail = e.Message; + debugInfo.StackEntries.AddRange(e.StackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.None)); + context.ResponseTrailers.Add(DebugInfoTrailerName, debugInfo.ToByteArray()); + throw new RpcException(new Status(StatusCode.Unknown, "The handler threw exception.")); + } + } + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs b/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs new file mode 100644 index 00000000..f68680b3 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs @@ -0,0 +1,2134 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/echo_messages.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Testing { + + /// Holder for reflection information generated from src/proto/grpc/testing/echo_messages.proto + public static partial class EchoMessagesReflection { + + #region Descriptor + /// File descriptor for src/proto/grpc/testing/echo_messages.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static EchoMessagesReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CipzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2VjaG9fbWVzc2FnZXMucHJvdG8S", + "DGdycGMudGVzdGluZyIyCglEZWJ1Z0luZm8SFQoNc3RhY2tfZW50cmllcxgB", + "IAMoCRIOCgZkZXRhaWwYAiABKAkiUAoLRXJyb3JTdGF0dXMSDAoEY29kZRgB", + "IAEoBRIVCg1lcnJvcl9tZXNzYWdlGAIgASgJEhwKFGJpbmFyeV9lcnJvcl9k", + "ZXRhaWxzGAMgASgJIssECg1SZXF1ZXN0UGFyYW1zEhUKDWVjaG9fZGVhZGxp", + "bmUYASABKAgSHgoWY2xpZW50X2NhbmNlbF9hZnRlcl91cxgCIAEoBRIeChZz", + "ZXJ2ZXJfY2FuY2VsX2FmdGVyX3VzGAMgASgFEhUKDWVjaG9fbWV0YWRhdGEY", + "BCABKAgSGgoSY2hlY2tfYXV0aF9jb250ZXh0GAUgASgIEh8KF3Jlc3BvbnNl", + "X21lc3NhZ2VfbGVuZ3RoGAYgASgFEhEKCWVjaG9fcGVlchgHIAEoCBIgChhl", + "eHBlY3RlZF9jbGllbnRfaWRlbnRpdHkYCCABKAkSHAoUc2tpcF9jYW5jZWxs", + "ZWRfY2hlY2sYCSABKAgSKAogZXhwZWN0ZWRfdHJhbnNwb3J0X3NlY3VyaXR5", + "X3R5cGUYCiABKAkSKwoKZGVidWdfaW5mbxgLIAEoCzIXLmdycGMudGVzdGlu", + "Zy5EZWJ1Z0luZm8SEgoKc2VydmVyX2RpZRgMIAEoCBIcChRiaW5hcnlfZXJy", + "b3JfZGV0YWlscxgNIAEoCRIxCg5leHBlY3RlZF9lcnJvchgOIAEoCzIZLmdy", + "cGMudGVzdGluZy5FcnJvclN0YXR1cxIXCg9zZXJ2ZXJfc2xlZXBfdXMYDyAB", + "KAUSGwoTYmFja2VuZF9jaGFubmVsX2lkeBgQIAEoBRIfChdlY2hvX21ldGFk", + "YXRhX2luaXRpYWxseRgRIAEoCBIpCiFzZXJ2ZXJfbm90aWZ5X2NsaWVudF93", + "aGVuX3N0YXJ0ZWQYEiABKAgiSgoLRWNob1JlcXVlc3QSDwoHbWVzc2FnZRgB", + "IAEoCRIqCgVwYXJhbRgCIAEoCzIbLmdycGMudGVzdGluZy5SZXF1ZXN0UGFy", + "YW1zIkYKDlJlc3BvbnNlUGFyYW1zEhgKEHJlcXVlc3RfZGVhZGxpbmUYASAB", + "KAMSDAoEaG9zdBgCIAEoCRIMCgRwZWVyGAMgASgJIkwKDEVjaG9SZXNwb25z", + "ZRIPCgdtZXNzYWdlGAEgASgJEisKBXBhcmFtGAIgASgLMhwuZ3JwYy50ZXN0", + "aW5nLlJlc3BvbnNlUGFyYW1zQgP4AQFiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.DebugInfo), global::Grpc.Testing.DebugInfo.Parser, new[]{ "StackEntries", "Detail" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ErrorStatus), global::Grpc.Testing.ErrorStatus.Parser, new[]{ "Code", "ErrorMessage", "BinaryErrorDetails" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.RequestParams), global::Grpc.Testing.RequestParams.Parser, new[]{ "EchoDeadline", "ClientCancelAfterUs", "ServerCancelAfterUs", "EchoMetadata", "CheckAuthContext", "ResponseMessageLength", "EchoPeer", "ExpectedClientIdentity", "SkipCancelledCheck", "ExpectedTransportSecurityType", "DebugInfo", "ServerDie", "BinaryErrorDetails", "ExpectedError", "ServerSleepUs", "BackendChannelIdx", "EchoMetadataInitially", "ServerNotifyClientWhenStarted" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EchoRequest), global::Grpc.Testing.EchoRequest.Parser, new[]{ "Message", "Param" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ResponseParams), global::Grpc.Testing.ResponseParams.Parser, new[]{ "RequestDeadline", "Host", "Peer" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EchoResponse), global::Grpc.Testing.EchoResponse.Parser, new[]{ "Message", "Param" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + /// + /// Message to be echoed back serialized in trailer. + /// + public sealed partial class DebugInfo : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DebugInfo()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.EchoMessagesReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public DebugInfo() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public DebugInfo(DebugInfo other) : this() { + stackEntries_ = other.stackEntries_.Clone(); + detail_ = other.detail_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public DebugInfo Clone() { + return new DebugInfo(this); + } + + /// Field number for the "stack_entries" field. + public const int StackEntriesFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_stackEntries_codec + = pb::FieldCodec.ForString(10); + private readonly pbc::RepeatedField stackEntries_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField StackEntries { + get { return stackEntries_; } + } + + /// Field number for the "detail" field. + public const int DetailFieldNumber = 2; + private string detail_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Detail { + get { return detail_; } + set { + detail_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as DebugInfo); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(DebugInfo other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!stackEntries_.Equals(other.stackEntries_)) return false; + if (Detail != other.Detail) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + hash ^= stackEntries_.GetHashCode(); + if (Detail.Length != 0) hash ^= Detail.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + stackEntries_.WriteTo(output, _repeated_stackEntries_codec); + if (Detail.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Detail); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + stackEntries_.WriteTo(ref output, _repeated_stackEntries_codec); + if (Detail.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Detail); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + size += stackEntries_.CalculateSize(_repeated_stackEntries_codec); + if (Detail.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Detail); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(DebugInfo other) { + if (other == null) { + return; + } + stackEntries_.Add(other.stackEntries_); + if (other.Detail.Length != 0) { + Detail = other.Detail; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + stackEntries_.AddEntriesFrom(input, _repeated_stackEntries_codec); + break; + } + case 18: { + Detail = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + stackEntries_.AddEntriesFrom(ref input, _repeated_stackEntries_codec); + break; + } + case 18: { + Detail = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// Error status client expects to see. + /// + public sealed partial class ErrorStatus : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ErrorStatus()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.EchoMessagesReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ErrorStatus() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ErrorStatus(ErrorStatus other) : this() { + code_ = other.code_; + errorMessage_ = other.errorMessage_; + binaryErrorDetails_ = other.binaryErrorDetails_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ErrorStatus Clone() { + return new ErrorStatus(this); + } + + /// Field number for the "code" field. + public const int CodeFieldNumber = 1; + private int code_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int Code { + get { return code_; } + set { + code_ = value; + } + } + + /// Field number for the "error_message" field. + public const int ErrorMessageFieldNumber = 2; + private string errorMessage_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ErrorMessage { + get { return errorMessage_; } + set { + errorMessage_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "binary_error_details" field. + public const int BinaryErrorDetailsFieldNumber = 3; + private string binaryErrorDetails_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string BinaryErrorDetails { + get { return binaryErrorDetails_; } + set { + binaryErrorDetails_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ErrorStatus); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ErrorStatus other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Code != other.Code) return false; + if (ErrorMessage != other.ErrorMessage) return false; + if (BinaryErrorDetails != other.BinaryErrorDetails) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Code != 0) hash ^= Code.GetHashCode(); + if (ErrorMessage.Length != 0) hash ^= ErrorMessage.GetHashCode(); + if (BinaryErrorDetails.Length != 0) hash ^= BinaryErrorDetails.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Code != 0) { + output.WriteRawTag(8); + output.WriteInt32(Code); + } + if (ErrorMessage.Length != 0) { + output.WriteRawTag(18); + output.WriteString(ErrorMessage); + } + if (BinaryErrorDetails.Length != 0) { + output.WriteRawTag(26); + output.WriteString(BinaryErrorDetails); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Code != 0) { + output.WriteRawTag(8); + output.WriteInt32(Code); + } + if (ErrorMessage.Length != 0) { + output.WriteRawTag(18); + output.WriteString(ErrorMessage); + } + if (BinaryErrorDetails.Length != 0) { + output.WriteRawTag(26); + output.WriteString(BinaryErrorDetails); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Code != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Code); + } + if (ErrorMessage.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ErrorMessage); + } + if (BinaryErrorDetails.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(BinaryErrorDetails); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ErrorStatus other) { + if (other == null) { + return; + } + if (other.Code != 0) { + Code = other.Code; + } + if (other.ErrorMessage.Length != 0) { + ErrorMessage = other.ErrorMessage; + } + if (other.BinaryErrorDetails.Length != 0) { + BinaryErrorDetails = other.BinaryErrorDetails; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Code = input.ReadInt32(); + break; + } + case 18: { + ErrorMessage = input.ReadString(); + break; + } + case 26: { + BinaryErrorDetails = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Code = input.ReadInt32(); + break; + } + case 18: { + ErrorMessage = input.ReadString(); + break; + } + case 26: { + BinaryErrorDetails = input.ReadString(); + break; + } + } + } + } + #endif + + } + + public sealed partial class RequestParams : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RequestParams()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.EchoMessagesReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RequestParams() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RequestParams(RequestParams other) : this() { + echoDeadline_ = other.echoDeadline_; + clientCancelAfterUs_ = other.clientCancelAfterUs_; + serverCancelAfterUs_ = other.serverCancelAfterUs_; + echoMetadata_ = other.echoMetadata_; + checkAuthContext_ = other.checkAuthContext_; + responseMessageLength_ = other.responseMessageLength_; + echoPeer_ = other.echoPeer_; + expectedClientIdentity_ = other.expectedClientIdentity_; + skipCancelledCheck_ = other.skipCancelledCheck_; + expectedTransportSecurityType_ = other.expectedTransportSecurityType_; + debugInfo_ = other.debugInfo_ != null ? other.debugInfo_.Clone() : null; + serverDie_ = other.serverDie_; + binaryErrorDetails_ = other.binaryErrorDetails_; + expectedError_ = other.expectedError_ != null ? other.expectedError_.Clone() : null; + serverSleepUs_ = other.serverSleepUs_; + backendChannelIdx_ = other.backendChannelIdx_; + echoMetadataInitially_ = other.echoMetadataInitially_; + serverNotifyClientWhenStarted_ = other.serverNotifyClientWhenStarted_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RequestParams Clone() { + return new RequestParams(this); + } + + /// Field number for the "echo_deadline" field. + public const int EchoDeadlineFieldNumber = 1; + private bool echoDeadline_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool EchoDeadline { + get { return echoDeadline_; } + set { + echoDeadline_ = value; + } + } + + /// Field number for the "client_cancel_after_us" field. + public const int ClientCancelAfterUsFieldNumber = 2; + private int clientCancelAfterUs_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ClientCancelAfterUs { + get { return clientCancelAfterUs_; } + set { + clientCancelAfterUs_ = value; + } + } + + /// Field number for the "server_cancel_after_us" field. + public const int ServerCancelAfterUsFieldNumber = 3; + private int serverCancelAfterUs_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ServerCancelAfterUs { + get { return serverCancelAfterUs_; } + set { + serverCancelAfterUs_ = value; + } + } + + /// Field number for the "echo_metadata" field. + public const int EchoMetadataFieldNumber = 4; + private bool echoMetadata_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool EchoMetadata { + get { return echoMetadata_; } + set { + echoMetadata_ = value; + } + } + + /// Field number for the "check_auth_context" field. + public const int CheckAuthContextFieldNumber = 5; + private bool checkAuthContext_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool CheckAuthContext { + get { return checkAuthContext_; } + set { + checkAuthContext_ = value; + } + } + + /// Field number for the "response_message_length" field. + public const int ResponseMessageLengthFieldNumber = 6; + private int responseMessageLength_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ResponseMessageLength { + get { return responseMessageLength_; } + set { + responseMessageLength_ = value; + } + } + + /// Field number for the "echo_peer" field. + public const int EchoPeerFieldNumber = 7; + private bool echoPeer_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool EchoPeer { + get { return echoPeer_; } + set { + echoPeer_ = value; + } + } + + /// Field number for the "expected_client_identity" field. + public const int ExpectedClientIdentityFieldNumber = 8; + private string expectedClientIdentity_ = ""; + /// + /// will force check_auth_context. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ExpectedClientIdentity { + get { return expectedClientIdentity_; } + set { + expectedClientIdentity_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "skip_cancelled_check" field. + public const int SkipCancelledCheckFieldNumber = 9; + private bool skipCancelledCheck_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool SkipCancelledCheck { + get { return skipCancelledCheck_; } + set { + skipCancelledCheck_ = value; + } + } + + /// Field number for the "expected_transport_security_type" field. + public const int ExpectedTransportSecurityTypeFieldNumber = 10; + private string expectedTransportSecurityType_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ExpectedTransportSecurityType { + get { return expectedTransportSecurityType_; } + set { + expectedTransportSecurityType_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "debug_info" field. + public const int DebugInfoFieldNumber = 11; + private global::Grpc.Testing.DebugInfo debugInfo_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.DebugInfo DebugInfo { + get { return debugInfo_; } + set { + debugInfo_ = value; + } + } + + /// Field number for the "server_die" field. + public const int ServerDieFieldNumber = 12; + private bool serverDie_; + /// + /// Server should not see a request with this set. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool ServerDie { + get { return serverDie_; } + set { + serverDie_ = value; + } + } + + /// Field number for the "binary_error_details" field. + public const int BinaryErrorDetailsFieldNumber = 13; + private string binaryErrorDetails_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string BinaryErrorDetails { + get { return binaryErrorDetails_; } + set { + binaryErrorDetails_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "expected_error" field. + public const int ExpectedErrorFieldNumber = 14; + private global::Grpc.Testing.ErrorStatus expectedError_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ErrorStatus ExpectedError { + get { return expectedError_; } + set { + expectedError_ = value; + } + } + + /// Field number for the "server_sleep_us" field. + public const int ServerSleepUsFieldNumber = 15; + private int serverSleepUs_; + /// + /// sleep when invoking server for deadline tests + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ServerSleepUs { + get { return serverSleepUs_; } + set { + serverSleepUs_ = value; + } + } + + /// Field number for the "backend_channel_idx" field. + public const int BackendChannelIdxFieldNumber = 16; + private int backendChannelIdx_; + /// + /// which backend to send request to + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int BackendChannelIdx { + get { return backendChannelIdx_; } + set { + backendChannelIdx_ = value; + } + } + + /// Field number for the "echo_metadata_initially" field. + public const int EchoMetadataInitiallyFieldNumber = 17; + private bool echoMetadataInitially_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool EchoMetadataInitially { + get { return echoMetadataInitially_; } + set { + echoMetadataInitially_ = value; + } + } + + /// Field number for the "server_notify_client_when_started" field. + public const int ServerNotifyClientWhenStartedFieldNumber = 18; + private bool serverNotifyClientWhenStarted_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool ServerNotifyClientWhenStarted { + get { return serverNotifyClientWhenStarted_; } + set { + serverNotifyClientWhenStarted_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as RequestParams); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(RequestParams other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (EchoDeadline != other.EchoDeadline) return false; + if (ClientCancelAfterUs != other.ClientCancelAfterUs) return false; + if (ServerCancelAfterUs != other.ServerCancelAfterUs) return false; + if (EchoMetadata != other.EchoMetadata) return false; + if (CheckAuthContext != other.CheckAuthContext) return false; + if (ResponseMessageLength != other.ResponseMessageLength) return false; + if (EchoPeer != other.EchoPeer) return false; + if (ExpectedClientIdentity != other.ExpectedClientIdentity) return false; + if (SkipCancelledCheck != other.SkipCancelledCheck) return false; + if (ExpectedTransportSecurityType != other.ExpectedTransportSecurityType) return false; + if (!object.Equals(DebugInfo, other.DebugInfo)) return false; + if (ServerDie != other.ServerDie) return false; + if (BinaryErrorDetails != other.BinaryErrorDetails) return false; + if (!object.Equals(ExpectedError, other.ExpectedError)) return false; + if (ServerSleepUs != other.ServerSleepUs) return false; + if (BackendChannelIdx != other.BackendChannelIdx) return false; + if (EchoMetadataInitially != other.EchoMetadataInitially) return false; + if (ServerNotifyClientWhenStarted != other.ServerNotifyClientWhenStarted) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (EchoDeadline != false) hash ^= EchoDeadline.GetHashCode(); + if (ClientCancelAfterUs != 0) hash ^= ClientCancelAfterUs.GetHashCode(); + if (ServerCancelAfterUs != 0) hash ^= ServerCancelAfterUs.GetHashCode(); + if (EchoMetadata != false) hash ^= EchoMetadata.GetHashCode(); + if (CheckAuthContext != false) hash ^= CheckAuthContext.GetHashCode(); + if (ResponseMessageLength != 0) hash ^= ResponseMessageLength.GetHashCode(); + if (EchoPeer != false) hash ^= EchoPeer.GetHashCode(); + if (ExpectedClientIdentity.Length != 0) hash ^= ExpectedClientIdentity.GetHashCode(); + if (SkipCancelledCheck != false) hash ^= SkipCancelledCheck.GetHashCode(); + if (ExpectedTransportSecurityType.Length != 0) hash ^= ExpectedTransportSecurityType.GetHashCode(); + if (debugInfo_ != null) hash ^= DebugInfo.GetHashCode(); + if (ServerDie != false) hash ^= ServerDie.GetHashCode(); + if (BinaryErrorDetails.Length != 0) hash ^= BinaryErrorDetails.GetHashCode(); + if (expectedError_ != null) hash ^= ExpectedError.GetHashCode(); + if (ServerSleepUs != 0) hash ^= ServerSleepUs.GetHashCode(); + if (BackendChannelIdx != 0) hash ^= BackendChannelIdx.GetHashCode(); + if (EchoMetadataInitially != false) hash ^= EchoMetadataInitially.GetHashCode(); + if (ServerNotifyClientWhenStarted != false) hash ^= ServerNotifyClientWhenStarted.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (EchoDeadline != false) { + output.WriteRawTag(8); + output.WriteBool(EchoDeadline); + } + if (ClientCancelAfterUs != 0) { + output.WriteRawTag(16); + output.WriteInt32(ClientCancelAfterUs); + } + if (ServerCancelAfterUs != 0) { + output.WriteRawTag(24); + output.WriteInt32(ServerCancelAfterUs); + } + if (EchoMetadata != false) { + output.WriteRawTag(32); + output.WriteBool(EchoMetadata); + } + if (CheckAuthContext != false) { + output.WriteRawTag(40); + output.WriteBool(CheckAuthContext); + } + if (ResponseMessageLength != 0) { + output.WriteRawTag(48); + output.WriteInt32(ResponseMessageLength); + } + if (EchoPeer != false) { + output.WriteRawTag(56); + output.WriteBool(EchoPeer); + } + if (ExpectedClientIdentity.Length != 0) { + output.WriteRawTag(66); + output.WriteString(ExpectedClientIdentity); + } + if (SkipCancelledCheck != false) { + output.WriteRawTag(72); + output.WriteBool(SkipCancelledCheck); + } + if (ExpectedTransportSecurityType.Length != 0) { + output.WriteRawTag(82); + output.WriteString(ExpectedTransportSecurityType); + } + if (debugInfo_ != null) { + output.WriteRawTag(90); + output.WriteMessage(DebugInfo); + } + if (ServerDie != false) { + output.WriteRawTag(96); + output.WriteBool(ServerDie); + } + if (BinaryErrorDetails.Length != 0) { + output.WriteRawTag(106); + output.WriteString(BinaryErrorDetails); + } + if (expectedError_ != null) { + output.WriteRawTag(114); + output.WriteMessage(ExpectedError); + } + if (ServerSleepUs != 0) { + output.WriteRawTag(120); + output.WriteInt32(ServerSleepUs); + } + if (BackendChannelIdx != 0) { + output.WriteRawTag(128, 1); + output.WriteInt32(BackendChannelIdx); + } + if (EchoMetadataInitially != false) { + output.WriteRawTag(136, 1); + output.WriteBool(EchoMetadataInitially); + } + if (ServerNotifyClientWhenStarted != false) { + output.WriteRawTag(144, 1); + output.WriteBool(ServerNotifyClientWhenStarted); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (EchoDeadline != false) { + output.WriteRawTag(8); + output.WriteBool(EchoDeadline); + } + if (ClientCancelAfterUs != 0) { + output.WriteRawTag(16); + output.WriteInt32(ClientCancelAfterUs); + } + if (ServerCancelAfterUs != 0) { + output.WriteRawTag(24); + output.WriteInt32(ServerCancelAfterUs); + } + if (EchoMetadata != false) { + output.WriteRawTag(32); + output.WriteBool(EchoMetadata); + } + if (CheckAuthContext != false) { + output.WriteRawTag(40); + output.WriteBool(CheckAuthContext); + } + if (ResponseMessageLength != 0) { + output.WriteRawTag(48); + output.WriteInt32(ResponseMessageLength); + } + if (EchoPeer != false) { + output.WriteRawTag(56); + output.WriteBool(EchoPeer); + } + if (ExpectedClientIdentity.Length != 0) { + output.WriteRawTag(66); + output.WriteString(ExpectedClientIdentity); + } + if (SkipCancelledCheck != false) { + output.WriteRawTag(72); + output.WriteBool(SkipCancelledCheck); + } + if (ExpectedTransportSecurityType.Length != 0) { + output.WriteRawTag(82); + output.WriteString(ExpectedTransportSecurityType); + } + if (debugInfo_ != null) { + output.WriteRawTag(90); + output.WriteMessage(DebugInfo); + } + if (ServerDie != false) { + output.WriteRawTag(96); + output.WriteBool(ServerDie); + } + if (BinaryErrorDetails.Length != 0) { + output.WriteRawTag(106); + output.WriteString(BinaryErrorDetails); + } + if (expectedError_ != null) { + output.WriteRawTag(114); + output.WriteMessage(ExpectedError); + } + if (ServerSleepUs != 0) { + output.WriteRawTag(120); + output.WriteInt32(ServerSleepUs); + } + if (BackendChannelIdx != 0) { + output.WriteRawTag(128, 1); + output.WriteInt32(BackendChannelIdx); + } + if (EchoMetadataInitially != false) { + output.WriteRawTag(136, 1); + output.WriteBool(EchoMetadataInitially); + } + if (ServerNotifyClientWhenStarted != false) { + output.WriteRawTag(144, 1); + output.WriteBool(ServerNotifyClientWhenStarted); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (EchoDeadline != false) { + size += 1 + 1; + } + if (ClientCancelAfterUs != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ClientCancelAfterUs); + } + if (ServerCancelAfterUs != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ServerCancelAfterUs); + } + if (EchoMetadata != false) { + size += 1 + 1; + } + if (CheckAuthContext != false) { + size += 1 + 1; + } + if (ResponseMessageLength != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ResponseMessageLength); + } + if (EchoPeer != false) { + size += 1 + 1; + } + if (ExpectedClientIdentity.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ExpectedClientIdentity); + } + if (SkipCancelledCheck != false) { + size += 1 + 1; + } + if (ExpectedTransportSecurityType.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ExpectedTransportSecurityType); + } + if (debugInfo_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(DebugInfo); + } + if (ServerDie != false) { + size += 1 + 1; + } + if (BinaryErrorDetails.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(BinaryErrorDetails); + } + if (expectedError_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExpectedError); + } + if (ServerSleepUs != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ServerSleepUs); + } + if (BackendChannelIdx != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32Size(BackendChannelIdx); + } + if (EchoMetadataInitially != false) { + size += 2 + 1; + } + if (ServerNotifyClientWhenStarted != false) { + size += 2 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(RequestParams other) { + if (other == null) { + return; + } + if (other.EchoDeadline != false) { + EchoDeadline = other.EchoDeadline; + } + if (other.ClientCancelAfterUs != 0) { + ClientCancelAfterUs = other.ClientCancelAfterUs; + } + if (other.ServerCancelAfterUs != 0) { + ServerCancelAfterUs = other.ServerCancelAfterUs; + } + if (other.EchoMetadata != false) { + EchoMetadata = other.EchoMetadata; + } + if (other.CheckAuthContext != false) { + CheckAuthContext = other.CheckAuthContext; + } + if (other.ResponseMessageLength != 0) { + ResponseMessageLength = other.ResponseMessageLength; + } + if (other.EchoPeer != false) { + EchoPeer = other.EchoPeer; + } + if (other.ExpectedClientIdentity.Length != 0) { + ExpectedClientIdentity = other.ExpectedClientIdentity; + } + if (other.SkipCancelledCheck != false) { + SkipCancelledCheck = other.SkipCancelledCheck; + } + if (other.ExpectedTransportSecurityType.Length != 0) { + ExpectedTransportSecurityType = other.ExpectedTransportSecurityType; + } + if (other.debugInfo_ != null) { + if (debugInfo_ == null) { + DebugInfo = new global::Grpc.Testing.DebugInfo(); + } + DebugInfo.MergeFrom(other.DebugInfo); + } + if (other.ServerDie != false) { + ServerDie = other.ServerDie; + } + if (other.BinaryErrorDetails.Length != 0) { + BinaryErrorDetails = other.BinaryErrorDetails; + } + if (other.expectedError_ != null) { + if (expectedError_ == null) { + ExpectedError = new global::Grpc.Testing.ErrorStatus(); + } + ExpectedError.MergeFrom(other.ExpectedError); + } + if (other.ServerSleepUs != 0) { + ServerSleepUs = other.ServerSleepUs; + } + if (other.BackendChannelIdx != 0) { + BackendChannelIdx = other.BackendChannelIdx; + } + if (other.EchoMetadataInitially != false) { + EchoMetadataInitially = other.EchoMetadataInitially; + } + if (other.ServerNotifyClientWhenStarted != false) { + ServerNotifyClientWhenStarted = other.ServerNotifyClientWhenStarted; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + EchoDeadline = input.ReadBool(); + break; + } + case 16: { + ClientCancelAfterUs = input.ReadInt32(); + break; + } + case 24: { + ServerCancelAfterUs = input.ReadInt32(); + break; + } + case 32: { + EchoMetadata = input.ReadBool(); + break; + } + case 40: { + CheckAuthContext = input.ReadBool(); + break; + } + case 48: { + ResponseMessageLength = input.ReadInt32(); + break; + } + case 56: { + EchoPeer = input.ReadBool(); + break; + } + case 66: { + ExpectedClientIdentity = input.ReadString(); + break; + } + case 72: { + SkipCancelledCheck = input.ReadBool(); + break; + } + case 82: { + ExpectedTransportSecurityType = input.ReadString(); + break; + } + case 90: { + if (debugInfo_ == null) { + DebugInfo = new global::Grpc.Testing.DebugInfo(); + } + input.ReadMessage(DebugInfo); + break; + } + case 96: { + ServerDie = input.ReadBool(); + break; + } + case 106: { + BinaryErrorDetails = input.ReadString(); + break; + } + case 114: { + if (expectedError_ == null) { + ExpectedError = new global::Grpc.Testing.ErrorStatus(); + } + input.ReadMessage(ExpectedError); + break; + } + case 120: { + ServerSleepUs = input.ReadInt32(); + break; + } + case 128: { + BackendChannelIdx = input.ReadInt32(); + break; + } + case 136: { + EchoMetadataInitially = input.ReadBool(); + break; + } + case 144: { + ServerNotifyClientWhenStarted = input.ReadBool(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + EchoDeadline = input.ReadBool(); + break; + } + case 16: { + ClientCancelAfterUs = input.ReadInt32(); + break; + } + case 24: { + ServerCancelAfterUs = input.ReadInt32(); + break; + } + case 32: { + EchoMetadata = input.ReadBool(); + break; + } + case 40: { + CheckAuthContext = input.ReadBool(); + break; + } + case 48: { + ResponseMessageLength = input.ReadInt32(); + break; + } + case 56: { + EchoPeer = input.ReadBool(); + break; + } + case 66: { + ExpectedClientIdentity = input.ReadString(); + break; + } + case 72: { + SkipCancelledCheck = input.ReadBool(); + break; + } + case 82: { + ExpectedTransportSecurityType = input.ReadString(); + break; + } + case 90: { + if (debugInfo_ == null) { + DebugInfo = new global::Grpc.Testing.DebugInfo(); + } + input.ReadMessage(DebugInfo); + break; + } + case 96: { + ServerDie = input.ReadBool(); + break; + } + case 106: { + BinaryErrorDetails = input.ReadString(); + break; + } + case 114: { + if (expectedError_ == null) { + ExpectedError = new global::Grpc.Testing.ErrorStatus(); + } + input.ReadMessage(ExpectedError); + break; + } + case 120: { + ServerSleepUs = input.ReadInt32(); + break; + } + case 128: { + BackendChannelIdx = input.ReadInt32(); + break; + } + case 136: { + EchoMetadataInitially = input.ReadBool(); + break; + } + case 144: { + ServerNotifyClientWhenStarted = input.ReadBool(); + break; + } + } + } + } + #endif + + } + + public sealed partial class EchoRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EchoRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.EchoMessagesReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EchoRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EchoRequest(EchoRequest other) : this() { + message_ = other.message_; + param_ = other.param_ != null ? other.param_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EchoRequest Clone() { + return new EchoRequest(this); + } + + /// Field number for the "message" field. + public const int MessageFieldNumber = 1; + private string message_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Message { + get { return message_; } + set { + message_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "param" field. + public const int ParamFieldNumber = 2; + private global::Grpc.Testing.RequestParams param_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.RequestParams Param { + get { return param_; } + set { + param_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as EchoRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(EchoRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Message != other.Message) return false; + if (!object.Equals(Param, other.Param)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Message.Length != 0) hash ^= Message.GetHashCode(); + if (param_ != null) hash ^= Param.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Message.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Message); + } + if (param_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Param); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Message.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Message); + } + if (param_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Param); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Message.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Message); + } + if (param_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Param); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(EchoRequest other) { + if (other == null) { + return; + } + if (other.Message.Length != 0) { + Message = other.Message; + } + if (other.param_ != null) { + if (param_ == null) { + Param = new global::Grpc.Testing.RequestParams(); + } + Param.MergeFrom(other.Param); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Message = input.ReadString(); + break; + } + case 18: { + if (param_ == null) { + Param = new global::Grpc.Testing.RequestParams(); + } + input.ReadMessage(Param); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Message = input.ReadString(); + break; + } + case 18: { + if (param_ == null) { + Param = new global::Grpc.Testing.RequestParams(); + } + input.ReadMessage(Param); + break; + } + } + } + } + #endif + + } + + public sealed partial class ResponseParams : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ResponseParams()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.EchoMessagesReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ResponseParams() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ResponseParams(ResponseParams other) : this() { + requestDeadline_ = other.requestDeadline_; + host_ = other.host_; + peer_ = other.peer_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ResponseParams Clone() { + return new ResponseParams(this); + } + + /// Field number for the "request_deadline" field. + public const int RequestDeadlineFieldNumber = 1; + private long requestDeadline_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long RequestDeadline { + get { return requestDeadline_; } + set { + requestDeadline_ = value; + } + } + + /// Field number for the "host" field. + public const int HostFieldNumber = 2; + private string host_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Host { + get { return host_; } + set { + host_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "peer" field. + public const int PeerFieldNumber = 3; + private string peer_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Peer { + get { return peer_; } + set { + peer_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ResponseParams); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ResponseParams other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (RequestDeadline != other.RequestDeadline) return false; + if (Host != other.Host) return false; + if (Peer != other.Peer) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (RequestDeadline != 0L) hash ^= RequestDeadline.GetHashCode(); + if (Host.Length != 0) hash ^= Host.GetHashCode(); + if (Peer.Length != 0) hash ^= Peer.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (RequestDeadline != 0L) { + output.WriteRawTag(8); + output.WriteInt64(RequestDeadline); + } + if (Host.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Host); + } + if (Peer.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Peer); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (RequestDeadline != 0L) { + output.WriteRawTag(8); + output.WriteInt64(RequestDeadline); + } + if (Host.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Host); + } + if (Peer.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Peer); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (RequestDeadline != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(RequestDeadline); + } + if (Host.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Host); + } + if (Peer.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Peer); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ResponseParams other) { + if (other == null) { + return; + } + if (other.RequestDeadline != 0L) { + RequestDeadline = other.RequestDeadline; + } + if (other.Host.Length != 0) { + Host = other.Host; + } + if (other.Peer.Length != 0) { + Peer = other.Peer; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + RequestDeadline = input.ReadInt64(); + break; + } + case 18: { + Host = input.ReadString(); + break; + } + case 26: { + Peer = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + RequestDeadline = input.ReadInt64(); + break; + } + case 18: { + Host = input.ReadString(); + break; + } + case 26: { + Peer = input.ReadString(); + break; + } + } + } + } + #endif + + } + + public sealed partial class EchoResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EchoResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.EchoMessagesReflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EchoResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EchoResponse(EchoResponse other) : this() { + message_ = other.message_; + param_ = other.param_ != null ? other.param_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EchoResponse Clone() { + return new EchoResponse(this); + } + + /// Field number for the "message" field. + public const int MessageFieldNumber = 1; + private string message_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Message { + get { return message_; } + set { + message_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "param" field. + public const int ParamFieldNumber = 2; + private global::Grpc.Testing.ResponseParams param_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ResponseParams Param { + get { return param_; } + set { + param_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as EchoResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(EchoResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Message != other.Message) return false; + if (!object.Equals(Param, other.Param)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Message.Length != 0) hash ^= Message.GetHashCode(); + if (param_ != null) hash ^= Param.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Message.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Message); + } + if (param_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Param); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Message.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Message); + } + if (param_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Param); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Message.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Message); + } + if (param_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Param); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(EchoResponse other) { + if (other == null) { + return; + } + if (other.Message.Length != 0) { + Message = other.Message; + } + if (other.param_ != null) { + if (param_ == null) { + Param = new global::Grpc.Testing.ResponseParams(); + } + Param.MergeFrom(other.Param); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Message = input.ReadString(); + break; + } + case 18: { + if (param_ == null) { + Param = new global::Grpc.Testing.ResponseParams(); + } + input.ReadMessage(Param); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Message = input.ReadString(); + break; + } + case 18: { + if (param_ == null) { + Param = new global::Grpc.Testing.ResponseParams(); + } + input.ReadMessage(Param); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.IntegrationTesting/Empty.cs b/src/csharp/Grpc.IntegrationTesting/Empty.cs new file mode 100644 index 00000000..dc1a2e75 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/Empty.cs @@ -0,0 +1,204 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/empty.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Testing { + + /// Holder for reflection information generated from src/proto/grpc/testing/empty.proto + public static partial class EmptyReflection { + + #region Descriptor + /// File descriptor for src/proto/grpc/testing/empty.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static EmptyReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CiJzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2VtcHR5LnByb3RvEgxncnBjLnRl", + "c3RpbmciBwoFRW1wdHliBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Empty), global::Grpc.Testing.Empty.Parser, null, null, null, null, null) + })); + } + #endregion + + } + #region Messages + /// + /// An empty message that you can re-use to avoid defining duplicated empty + /// messages in your project. A typical example is to use it as argument or the + /// return value of a service API. For instance: + /// + /// service Foo { + /// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { }; + /// }; + /// + public sealed partial class Empty : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Empty()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.EmptyReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Empty() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Empty(Empty other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Empty Clone() { + return new Empty(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Empty); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Empty other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Empty other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.IntegrationTesting/EmptyService.cs b/src/csharp/Grpc.IntegrationTesting/EmptyService.cs new file mode 100644 index 00000000..897d708f --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/EmptyService.cs @@ -0,0 +1,38 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/empty_service.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Testing { + + /// Holder for reflection information generated from src/proto/grpc/testing/empty_service.proto + public static partial class EmptyServiceReflection { + + #region Descriptor + /// File descriptor for src/proto/grpc/testing/empty_service.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static EmptyServiceReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CipzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2VtcHR5X3NlcnZpY2UucHJvdG8S", + "DGdycGMudGVzdGluZzIOCgxFbXB0eVNlcnZpY2ViBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, null)); + } + #endregion + + } +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs new file mode 100644 index 00000000..c5e9d438 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs @@ -0,0 +1,101 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/empty_service.proto +// +// Original file comments: +// Copyright 2018 gRPC authors. +// +// 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. +// +#pragma warning disable 0414, 1591 +#region Designer generated code + +using grpc = global::Grpc.Core; + +namespace Grpc.Testing { + /// + /// A service that has zero methods. + /// See https://github.com/grpc/grpc/issues/15574 + /// + public static partial class EmptyService + { + static readonly string __ServiceName = "grpc.testing.EmptyService"; + + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Testing.EmptyServiceReflection.Descriptor.Services[0]; } + } + + /// Base class for server-side implementations of EmptyService + [grpc::BindServiceMethod(typeof(EmptyService), "BindService")] + public abstract partial class EmptyServiceBase + { + } + + /// Client for EmptyService + public partial class EmptyServiceClient : grpc::ClientBase + { + /// Creates a new client for EmptyService + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public EmptyServiceClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for EmptyService that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public EmptyServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected EmptyServiceClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected EmptyServiceClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override EmptyServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new EmptyServiceClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static grpc::ServerServiceDefinition BindService(EmptyServiceBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder().Build(); + } + + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static void BindService(grpc::ServiceBinderBase serviceBinder, EmptyServiceBase serviceImpl) + { + } + + } +} +#endregion diff --git a/src/csharp/Grpc.IntegrationTesting/ExternalDnsClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/ExternalDnsClientServerTest.cs new file mode 100644 index 00000000..1360d250 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/ExternalDnsClientServerTest.cs @@ -0,0 +1,74 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Testing; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + /// + /// Runs interop tests in-process, with that client using a target + /// name that using a target name that triggers interaction with + /// external DNS servers (even though it resolves to the in-proc server). + /// This test is a trimmed-down sibling test to the one in + /// "ExternalDnsWithTracingClientServerTest", and is meant mostly for + /// comparison with that one. + /// + public class ExternalDnsClientServerTest + { + Server server; + Channel channel; + TestService.TestServiceClient client; + + [OneTimeSetUp] + public void Init() + { + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { TestService.BindService(new TestServiceImpl()) }, + Ports = { { "[::1]", ServerPort.PickUnused, ServerCredentials.Insecure } } + }; + server.Start(); + + int port = server.Ports.Single().BoundPort; + channel = new Channel("loopback6.unittest.grpc.io", port, ChannelCredentials.Insecure); + client = new TestService.TestServiceClient(channel); + } + + [OneTimeTearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void EmptyUnary() + { + InteropClient.RunEmptyUnary(client); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/ExternalDnsWithTracingClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/ExternalDnsWithTracingClientServerTest.cs new file mode 100644 index 00000000..6983aeb2 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/ExternalDnsWithTracingClientServerTest.cs @@ -0,0 +1,176 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Logging; +using Grpc.Core.Utils; +using Grpc.Core.Internal; +using Grpc.Testing; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + /// + /// See https://github.com/grpc/grpc/issues/18074, this test is meant to + /// try to trigger the described bug. + /// Runs interop tests in-process, with that client using a target + /// name that using a target name that triggers interaction with + /// external DNS servers (even though it resolves to the in-proc server). + /// + public class ExternalDnsWithTracingClientServerTest + { + Server server; + Channel channel; + TestService.TestServiceClient client; + + [OneTimeSetUp] + public void Init() + { + // We only care about running this test on Windows (see #18074) + // TODO(jtattermusch): We could run it on Linux and Mac as well, + // but there are two issues. + // 1. Due to https://github.com/grpc/grpc/issues/14963, setting the + // enviroment variables actually has no effect on CoreCLR. + // 2. On mono the test with enabled tracing sometimes times out + // due to suspected mono-related issue on shutdown + // See https://github.com/grpc/grpc/issues/18126 + if (PlatformApis.IsWindows) + { + Environment.SetEnvironmentVariable("GRPC_TRACE", "all"); + Environment.SetEnvironmentVariable("GRPC_VERBOSITY", "DEBUG"); + var newLogger = new SocketUsingLogger(GrpcEnvironment.Logger); + GrpcEnvironment.SetLogger(newLogger); + } + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { TestService.BindService(new TestServiceImpl()) }, + Ports = { { "[::1]", ServerPort.PickUnused, ServerCredentials.Insecure } }, + // reduce the number of request call tokens to + // avoid flooding the logs with token-related messages + RequestCallTokensPerCompletionQueue = 3, + }; + server.Start(); + int port = server.Ports.Single().BoundPort; + channel = new Channel("loopback6.unittest.grpc.io", port, ChannelCredentials.Insecure); + client = new TestService.TestServiceClient(channel); + } + + [OneTimeTearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void EmptyUnary() + { + InteropClient.RunEmptyUnary(client); + } + } + + /// + /// Logger which does some socket operation after delegating + /// actual logging to its delegate logger. The main goal is to + /// reset the current thread's WSA error status. + /// The only reason for the delegateLogger is to continue + /// to have this test display debug logs. + /// + internal sealed class SocketUsingLogger : ILogger + { + private ILogger delegateLogger; + + public SocketUsingLogger(ILogger delegateLogger) { + this.delegateLogger = delegateLogger; + } + + public void Debug(string message) + { + MyLog(() => delegateLogger.Debug(message)); + } + + public void Debug(string format, params object[] formatArgs) + { + MyLog(() => delegateLogger.Debug(format, formatArgs)); + } + + public void Error(string message) + { + MyLog(() => delegateLogger.Error(message)); + } + + public void Error(Exception exception, string message) + { + MyLog(() => delegateLogger.Error(exception, message)); + } + + public void Error(string format, params object[] formatArgs) + { + MyLog(() => delegateLogger.Error(format, formatArgs)); + } + + public ILogger ForType() + { + return this; + } + + public void Info(string message) + { + MyLog(() => delegateLogger.Info(message)); + } + + public void Info(string format, params object[] formatArgs) + { + MyLog(() => delegateLogger.Info(format, formatArgs)); + } + + public void Warning(string message) + { + MyLog(() => delegateLogger.Warning(message)); + } + + public void Warning(Exception exception, string message) + { + MyLog(() => delegateLogger.Warning(exception, message)); + } + + public void Warning(string format, params object[] formatArgs) + { + MyLog(() => delegateLogger.Warning(format, formatArgs)); + } + + private void MyLog(Action delegateLog) + { + delegateLog(); + // Create and close a socket, just in order to affect + // the WSA (on Windows) error status of the current thread. + Socket s = new Socket(AddressFamily.InterNetwork, + SocketType.Stream, + ProtocolType.Tcp); + + s.Dispose(); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs b/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs new file mode 100644 index 00000000..c8bcb7a9 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs @@ -0,0 +1,67 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Testing; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + public class GeneratedClientTest + { + TestService.TestServiceClient unimplementedClient = new UnimplementedTestServiceClient(); + + [Test] + public void DefaultMethodStubThrows_UnaryCall() + { + Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.UnaryCall(new SimpleRequest())); + } + + [Test] + public void DefaultMethodStubThrows_ClientStreaming() + { + Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.StreamingInputCall()); + } + + [Test] + public void DefaultMethodStubThrows_ServerStreaming() + { + Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.StreamingOutputCall(new StreamingOutputCallRequest())); + } + + [Test] + public void DefaultMethodStubThrows_DuplexStreaming() + { + Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.FullDuplexCall()); + } + + /// + /// Subclass of the generated client that doesn't override any method stubs. + /// + private class UnimplementedTestServiceClient : TestService.TestServiceClient + { + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/GeneratedServiceBaseTest.cs b/src/csharp/Grpc.IntegrationTesting/GeneratedServiceBaseTest.cs new file mode 100644 index 00000000..adeec056 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/GeneratedServiceBaseTest.cs @@ -0,0 +1,101 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Testing; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + public class GeneratedServiceBaseTest + { + const string Host = "localhost"; + Server server; + Channel channel; + TestService.TestServiceClient client; + + [SetUp] + public void Init() + { + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { TestService.BindService(new UnimplementedTestServiceImpl()) }, + Ports = { { Host, ServerPort.PickUnused, SslServerCredentials.Insecure } } + }; + server.Start(); + channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure); + client = new TestService.TestServiceClient(channel); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void UnimplementedByDefault_Unary() + { + var ex = Assert.Throws(() => client.UnaryCall(new SimpleRequest { })); + Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode); + } + + [Test] + public void UnimplementedByDefault_ClientStreaming() + { + var call = client.StreamingInputCall(); + + var ex = Assert.ThrowsAsync(async () => await call); + Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode); + } + + [Test] + public void UnimplementedByDefault_ServerStreamingCall() + { + var call = client.StreamingOutputCall(new StreamingOutputCallRequest()); + + var ex = Assert.ThrowsAsync(async () => await call.ResponseStream.MoveNext()); + Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode); + } + + [Test] + public void UnimplementedByDefault_DuplexStreamingCall() + { + var call = client.FullDuplexCall(); + + var ex = Assert.ThrowsAsync(async () => await call.ResponseStream.MoveNext()); + Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode); + } + + /// + /// Implementation of TestService that doesn't override any methods. + /// + private class UnimplementedTestServiceImpl : TestService.TestServiceBase + { + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/GenericService.cs b/src/csharp/Grpc.IntegrationTesting/GenericService.cs new file mode 100644 index 00000000..55ff160f --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/GenericService.cs @@ -0,0 +1,56 @@ +#region Copyright notice and license + +// Copyright 2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Google.Protobuf; +using Grpc.Core; +using Grpc.Core.Utils; +using NUnit.Framework; +using Grpc.Testing; + +namespace Grpc.IntegrationTesting +{ + /// + /// Utility methods for defining and calling a service that doesn't use protobufs + /// for serialization/deserialization. + /// + public static class GenericService + { + readonly static Marshaller ByteArrayMarshaller = new Marshaller((b) => b, (b) => b); + + public readonly static Method StreamingCallMethod = new Method( + MethodType.DuplexStreaming, + "grpc.testing.BenchmarkService", + "StreamingCall", + ByteArrayMarshaller, + ByteArrayMarshaller + ); + + public static ServerServiceDefinition BindHandler(DuplexStreamingServerMethod handler) + { + return ServerServiceDefinition.CreateBuilder() + .AddMethod(StreamingCallMethod, handler).Build(); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/Histogram.cs b/src/csharp/Grpc.IntegrationTesting/Histogram.cs new file mode 100644 index 00000000..3c42f23b --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/Histogram.cs @@ -0,0 +1,165 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Google.Protobuf; +using Grpc.Core; +using Grpc.Core.Utils; +using NUnit.Framework; +using Grpc.Testing; + +namespace Grpc.IntegrationTesting +{ + /// + /// Basic implementation of histogram based on grpc/support/histogram.h. + /// + public class Histogram + { + readonly object myLock = new object(); + readonly double multiplier; + readonly double oneOnLogMultiplier; + readonly double maxPossible; + readonly uint[] buckets; + + int count; + double sum; + double sumOfSquares; + double min; + double max; + + public Histogram(double resolution, double maxPossible) + { + GrpcPreconditions.CheckArgument(resolution > 0); + GrpcPreconditions.CheckArgument(maxPossible > 0); + this.maxPossible = maxPossible; + this.multiplier = 1.0 + resolution; + this.oneOnLogMultiplier = 1.0 / Math.Log(1.0 + resolution); + this.buckets = new uint[FindBucket(maxPossible) + 1]; + + ResetUnsafe(); + } + + public void AddObservation(double value) + { + lock (myLock) + { + AddObservationUnsafe(value); + } + } + + /// + /// Gets snapshot of stats and optionally resets the histogram. + /// + public HistogramData GetSnapshot(bool reset = false) + { + lock (myLock) + { + var histogramData = new HistogramData(); + GetSnapshotUnsafe(histogramData, reset); + return histogramData; + } + } + + /// + /// Merges snapshot of stats into mergeTo and optionally resets the histogram. + /// + public void GetSnapshot(HistogramData mergeTo, bool reset) + { + lock (myLock) + { + GetSnapshotUnsafe(mergeTo, reset); + } + } + + /// + /// Finds bucket index to which given observation should go. + /// + private int FindBucket(double value) + { + value = Math.Max(value, 1.0); + value = Math.Min(value, this.maxPossible); + return (int)(Math.Log(value) * oneOnLogMultiplier); + } + + private void AddObservationUnsafe(double value) + { + this.count++; + this.sum += value; + this.sumOfSquares += value * value; + this.min = Math.Min(this.min, value); + this.max = Math.Max(this.max, value); + + this.buckets[FindBucket(value)]++; + } + + private void GetSnapshotUnsafe(HistogramData mergeTo, bool reset) + { + GrpcPreconditions.CheckArgument(mergeTo.Bucket.Count == 0 || mergeTo.Bucket.Count == buckets.Length); + if (mergeTo.Count == 0) + { + mergeTo.MinSeen = min; + mergeTo.MaxSeen = max; + } + else + { + mergeTo.MinSeen = Math.Min(mergeTo.MinSeen, min); + mergeTo.MaxSeen = Math.Max(mergeTo.MaxSeen, max); + } + mergeTo.Count += count; + mergeTo.Sum += sum; + mergeTo.SumOfSquares += sumOfSquares; + + if (mergeTo.Bucket.Count == 0) + { + mergeTo.Bucket.AddRange(buckets); + } + else + { + for (int i = 0; i < buckets.Length; i++) + { + mergeTo.Bucket[i] += buckets[i]; + } + } + + if (reset) + { + ResetUnsafe(); + } + } + + private void ResetUnsafe() + { + this.count = 0; + this.sum = 0; + this.sumOfSquares = 0; + this.min = double.PositiveInfinity; + this.max = double.NegativeInfinity; + for (int i = 0; i < this.buckets.Length; i++) + { + this.buckets[i] = 0; + } + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/HistogramTest.cs b/src/csharp/Grpc.IntegrationTesting/HistogramTest.cs new file mode 100644 index 00000000..9a3cf002 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/HistogramTest.cs @@ -0,0 +1,113 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Testing; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + public class HistogramTest + { + [Test] + public void Simple() + { + var hist = new Histogram(0.01, 60e9); + hist.AddObservation(10000); + hist.AddObservation(10000); + hist.AddObservation(11000); + hist.AddObservation(11000); + + var data = hist.GetSnapshot(); + + Assert.AreEqual(4, data.Count); + Assert.AreEqual(42000.0, data.Sum, 1e-6); + Assert.AreEqual(10000, data.MinSeen); + Assert.AreEqual(11000, data.MaxSeen); + Assert.AreEqual(2.0*10000*10000 + 2.0*11000*11000, data.SumOfSquares, 1e-6); + + // 1.01^925 < 10000 < 1.01^926 + Assert.AreEqual(2, data.Bucket[925]); + Assert.AreEqual(2, data.Bucket[935]); + } + + [Test] + public void ExtremeObservations() + { + var hist = new Histogram(0.01, 60e9); + hist.AddObservation(-0.5); // should be in the first bucket + hist.AddObservation(1e12); // should be in the last bucket + + var data = hist.GetSnapshot(); + Assert.AreEqual(1, data.Bucket[0]); + Assert.AreEqual(1, data.Bucket[data.Bucket.Count - 1]); + } + + [Test] + public void MergeSnapshots() + { + var data = new HistogramData(); + + var hist1 = new Histogram(0.01, 60e9); + hist1.AddObservation(-0.5); // should be in the first bucket + hist1.AddObservation(1e12); // should be in the last bucket + hist1.GetSnapshot(data, false); + + var hist2 = new Histogram(0.01, 60e9); + hist2.AddObservation(10000); + hist2.AddObservation(11000); + hist2.GetSnapshot(data, false); + + Assert.AreEqual(4, data.Count); + Assert.AreEqual(-0.5, data.MinSeen); + Assert.AreEqual(1e12, data.MaxSeen); + Assert.AreEqual(1, data.Bucket[0]); + Assert.AreEqual(1, data.Bucket[925]); + Assert.AreEqual(1, data.Bucket[935]); + Assert.AreEqual(1, data.Bucket[data.Bucket.Count - 1]); + } + + [Test] + public void Reset() + { + var hist = new Histogram(0.01, 60e9); + hist.AddObservation(10000); + hist.AddObservation(11000); + + var data = hist.GetSnapshot(true); // snapshot contains data before reset + Assert.AreEqual(2, data.Count); + Assert.AreEqual(10000, data.MinSeen); + Assert.AreEqual(11000, data.MaxSeen); + + data = hist.GetSnapshot(); // snapshot contains state after reset + Assert.AreEqual(0, data.Count); + Assert.AreEqual(double.PositiveInfinity, data.MinSeen); + Assert.AreEqual(double.NegativeInfinity, data.MaxSeen); + Assert.AreEqual(0, data.Sum); + Assert.AreEqual(0, data.SumOfSquares); + CollectionAssert.AreEqual(new uint[data.Bucket.Count], data.Bucket); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/IClientRunner.cs b/src/csharp/Grpc.IntegrationTesting/IClientRunner.cs new file mode 100644 index 00000000..538ec24e --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/IClientRunner.cs @@ -0,0 +1,52 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Google.Protobuf; +using Grpc.Core; +using Grpc.Core.Utils; +using NUnit.Framework; +using Grpc.Testing; + +namespace Grpc.IntegrationTesting +{ + /// + /// Abstract client runner. + /// + public interface IClientRunner + { + /// + /// Gets stats snapshot. + /// + /// The stats. + ClientStats GetStats(bool reset); + + /// + /// Asynchronously stops the client. + /// + /// Task that finishes when client has come to a full stop. + Task StopAsync(); + } + +} diff --git a/src/csharp/Grpc.IntegrationTesting/IServerRunner.cs b/src/csharp/Grpc.IntegrationTesting/IServerRunner.cs new file mode 100644 index 00000000..4682bf88 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/IServerRunner.cs @@ -0,0 +1,57 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Google.Protobuf; +using Grpc.Core; +using Grpc.Core.Utils; +using NUnit.Framework; +using Grpc.Testing; + +namespace Grpc.IntegrationTesting +{ + /// + /// Abstract server runner. + /// + public interface IServerRunner + { + /// + /// Port on which the server is listening. + /// + int BoundPort { get; } + + /// + /// Gets server stats. + /// + /// The stats. + ServerStats GetStats(bool reset); + + /// + /// Asynchronously stops the server. + /// + /// Task that finishes when server has shutdown. + Task StopAsync(); + } + +} diff --git a/src/csharp/Grpc.IntegrationTesting/InterarrivalTimers.cs b/src/csharp/Grpc.IntegrationTesting/InterarrivalTimers.cs new file mode 100644 index 00000000..cfb0ff9d --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/InterarrivalTimers.cs @@ -0,0 +1,133 @@ +#region Copyright notice and license + +// Copyright 2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Google.Protobuf; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Testing; + +namespace Grpc.IntegrationTesting +{ + public interface IInterarrivalTimer + { + void WaitForNext(); + + Task WaitForNextAsync(); + } + + /// + /// Interarrival timer that doesn't wait at all. + /// + public class ClosedLoopInterarrivalTimer : IInterarrivalTimer + { + public ClosedLoopInterarrivalTimer() + { + } + + public void WaitForNext() + { + // NOP + } + + public Task WaitForNextAsync() + { + return TaskUtils.CompletedTask; + } + } + + /// + /// Interarrival timer that generates Poisson process load. + /// + public class PoissonInterarrivalTimer : IInterarrivalTimer + { + readonly ExponentialDistribution exponentialDistribution; + DateTime? lastEventTime; + + public PoissonInterarrivalTimer(double offeredLoad) + { + this.exponentialDistribution = new ExponentialDistribution(new Random(), offeredLoad); + this.lastEventTime = DateTime.UtcNow; + } + + public void WaitForNext() + { + var waitDuration = GetNextWaitDuration(); + int millisTimeout = (int) Math.Round(waitDuration.TotalMilliseconds); + if (millisTimeout > 0) + { + // TODO(jtattermusch): probably only works well for a relatively low interarrival rate + Thread.Sleep(millisTimeout); + } + } + + public async Task WaitForNextAsync() + { + var waitDuration = GetNextWaitDuration(); + int millisTimeout = (int) Math.Round(waitDuration.TotalMilliseconds); + if (millisTimeout > 0) + { + // TODO(jtattermusch): probably only works well for a relatively low interarrival rate + await Task.Delay(millisTimeout); + } + } + + private TimeSpan GetNextWaitDuration() + { + if (!lastEventTime.HasValue) + { + this.lastEventTime = DateTime.Now; + } + + var origLastEventTime = this.lastEventTime.Value; + this.lastEventTime = origLastEventTime + TimeSpan.FromSeconds(exponentialDistribution.Next()); + return this.lastEventTime.Value - origLastEventTime; + } + + /// + /// Exp generator. + /// + private class ExponentialDistribution + { + readonly Random random; + readonly double lambda; + readonly double lambdaReciprocal; + + public ExponentialDistribution(Random random, double lambda) + { + this.random = random; + this.lambda = lambda; + this.lambdaReciprocal = 1.0 / lambda; + } + + public double Next() + { + double uniform = random.NextDouble(); + // Use 1.0-uni above to avoid NaN if uni is 0 + return lambdaReciprocal * (-Math.Log(1.0 - uniform)); + } + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs new file mode 100644 index 00000000..53cd4562 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs @@ -0,0 +1,744 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +using CommandLine; +using CommandLine.Text; +using Google.Apis.Auth.OAuth2; +using Google.Protobuf; +using Grpc.Auth; +using Grpc.Core; +using Grpc.Core.Logging; +using Grpc.Core.Utils; +using Grpc.Testing; +using Newtonsoft.Json.Linq; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + public class InteropClient + { + private class ClientOptions + { + [Option("server_host", Default = "localhost")] + public string ServerHost { get; set; } + + [Option("server_host_override")] + public string ServerHostOverride { get; set; } + + [Option("server_port", Required = true)] + public int ServerPort { get; set; } + + [Option("test_case", Default = "large_unary")] + public string TestCase { get; set; } + + // Deliberately using nullable bool type to allow --use_tls=true syntax (as opposed to --use_tls) + [Option("use_tls", Default = false)] + public bool? UseTls { get; set; } + + // Deliberately using nullable bool type to allow --use_test_ca=true syntax (as opposed to --use_test_ca) + [Option("use_test_ca", Default = false)] + public bool? UseTestCa { get; set; } + + [Option("default_service_account", Required = false)] + public string DefaultServiceAccount { get; set; } + + [Option("oauth_scope", Required = false)] + public string OAuthScope { get; set; } + + [Option("service_account_key_file", Required = false)] + public string ServiceAccountKeyFile { get; set; } + } + + ClientOptions options; + + private InteropClient(ClientOptions options) + { + this.options = options; + } + + public static void Run(string[] args) + { + GrpcEnvironment.SetLogger(new ConsoleLogger()); + var parserResult = Parser.Default.ParseArguments(args) + .WithNotParsed(errors => Environment.Exit(1)) + .WithParsed(options => + { + var interopClient = new InteropClient(options); + interopClient.Run().Wait(); + }); + } + + private async Task Run() + { + var credentials = await CreateCredentialsAsync(); + + List channelOptions = null; + if (!string.IsNullOrEmpty(options.ServerHostOverride)) + { + channelOptions = new List + { + new ChannelOption(ChannelOptions.SslTargetNameOverride, options.ServerHostOverride) + }; + } + var channel = new Channel(options.ServerHost, options.ServerPort, credentials, channelOptions); + await RunTestCaseAsync(channel, options); + await channel.ShutdownAsync(); + } + + private async Task CreateCredentialsAsync() + { + var credentials = ChannelCredentials.Insecure; + if (options.UseTls.Value) + { + credentials = options.UseTestCa.Value ? TestCredentials.CreateSslCredentials() : new SslCredentials(); + } + + if (options.TestCase == "jwt_token_creds") + { + var googleCredential = await GoogleCredential.GetApplicationDefaultAsync(); + Assert.IsTrue(googleCredential.IsCreateScopedRequired); + credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials()); + } + + if (options.TestCase == "compute_engine_creds") + { + var googleCredential = await GoogleCredential.GetApplicationDefaultAsync(); + Assert.IsFalse(googleCredential.IsCreateScopedRequired); + credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials()); + } + return credentials; + } + + private async Task RunTestCaseAsync(Channel channel, ClientOptions options) + { + var client = new TestService.TestServiceClient(channel); + switch (options.TestCase) + { + case "empty_unary": + RunEmptyUnary(client); + break; + case "large_unary": + RunLargeUnary(client); + break; + case "client_streaming": + await RunClientStreamingAsync(client); + break; + case "server_streaming": + await RunServerStreamingAsync(client); + break; + case "ping_pong": + await RunPingPongAsync(client); + break; + case "empty_stream": + await RunEmptyStreamAsync(client); + break; + case "compute_engine_creds": + RunComputeEngineCreds(client, options.DefaultServiceAccount, options.OAuthScope); + break; + case "jwt_token_creds": + RunJwtTokenCreds(client); + break; + case "oauth2_auth_token": + await RunOAuth2AuthTokenAsync(client, options.OAuthScope); + break; + case "per_rpc_creds": + await RunPerRpcCredsAsync(client, options.OAuthScope); + break; + case "cancel_after_begin": + await RunCancelAfterBeginAsync(client); + break; + case "cancel_after_first_response": + await RunCancelAfterFirstResponseAsync(client); + break; + case "timeout_on_sleeping_server": + await RunTimeoutOnSleepingServerAsync(client); + break; + case "custom_metadata": + await RunCustomMetadataAsync(client); + break; + case "status_code_and_message": + await RunStatusCodeAndMessageAsync(client); + break; + case "unimplemented_service": + RunUnimplementedService(new UnimplementedService.UnimplementedServiceClient(channel)); + break; + case "special_status_message": + await RunSpecialStatusMessageAsync(client); + break; + case "unimplemented_method": + RunUnimplementedMethod(client); + break; + case "client_compressed_unary": + RunClientCompressedUnary(client); + break; + case "client_compressed_streaming": + await RunClientCompressedStreamingAsync(client); + break; + default: + throw new ArgumentException("Unknown test case " + options.TestCase); + } + } + + public static void RunEmptyUnary(TestService.TestServiceClient client) + { + Console.WriteLine("running empty_unary"); + var response = client.EmptyCall(new Empty()); + Assert.IsNotNull(response); + Console.WriteLine("Passed!"); + } + + public static void RunLargeUnary(TestService.TestServiceClient client) + { + Console.WriteLine("running large_unary"); + var request = new SimpleRequest + { + ResponseSize = 314159, + Payload = CreateZerosPayload(271828) + }; + var response = client.UnaryCall(request); + + Assert.AreEqual(314159, response.Payload.Body.Length); + Console.WriteLine("Passed!"); + } + + public static async Task RunClientStreamingAsync(TestService.TestServiceClient client) + { + Console.WriteLine("running client_streaming"); + + var bodySizes = new List { 27182, 8, 1828, 45904 }.Select((size) => new StreamingInputCallRequest { Payload = CreateZerosPayload(size) }); + + using (var call = client.StreamingInputCall()) + { + await call.RequestStream.WriteAllAsync(bodySizes); + + var response = await call.ResponseAsync; + Assert.AreEqual(74922, response.AggregatedPayloadSize); + } + Console.WriteLine("Passed!"); + } + + public static async Task RunServerStreamingAsync(TestService.TestServiceClient client) + { + Console.WriteLine("running server_streaming"); + + var bodySizes = new List { 31415, 9, 2653, 58979 }; + + var request = new StreamingOutputCallRequest + { + ResponseParameters = { bodySizes.Select((size) => new ResponseParameters { Size = size }) } + }; + + using (var call = client.StreamingOutputCall(request)) + { + var responseList = await call.ResponseStream.ToListAsync(); + CollectionAssert.AreEqual(bodySizes, responseList.Select((item) => item.Payload.Body.Length)); + } + Console.WriteLine("Passed!"); + } + + public static async Task RunPingPongAsync(TestService.TestServiceClient client) + { + Console.WriteLine("running ping_pong"); + + using (var call = client.FullDuplexCall()) + { + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest + { + ResponseParameters = { new ResponseParameters { Size = 31415 } }, + Payload = CreateZerosPayload(27182) + }); + + Assert.IsTrue(await call.ResponseStream.MoveNext()); + Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length); + + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest + { + ResponseParameters = { new ResponseParameters { Size = 9 } }, + Payload = CreateZerosPayload(8) + }); + + Assert.IsTrue(await call.ResponseStream.MoveNext()); + Assert.AreEqual(9, call.ResponseStream.Current.Payload.Body.Length); + + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest + { + ResponseParameters = { new ResponseParameters { Size = 2653 } }, + Payload = CreateZerosPayload(1828) + }); + + Assert.IsTrue(await call.ResponseStream.MoveNext()); + Assert.AreEqual(2653, call.ResponseStream.Current.Payload.Body.Length); + + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest + { + ResponseParameters = { new ResponseParameters { Size = 58979 } }, + Payload = CreateZerosPayload(45904) + }); + + Assert.IsTrue(await call.ResponseStream.MoveNext()); + Assert.AreEqual(58979, call.ResponseStream.Current.Payload.Body.Length); + + await call.RequestStream.CompleteAsync(); + + Assert.IsFalse(await call.ResponseStream.MoveNext()); + } + Console.WriteLine("Passed!"); + } + + public static async Task RunEmptyStreamAsync(TestService.TestServiceClient client) + { + Console.WriteLine("running empty_stream"); + using (var call = client.FullDuplexCall()) + { + await call.RequestStream.CompleteAsync(); + + var responseList = await call.ResponseStream.ToListAsync(); + Assert.AreEqual(0, responseList.Count); + } + Console.WriteLine("Passed!"); + } + + public static void RunComputeEngineCreds(TestService.TestServiceClient client, string defaultServiceAccount, string oauthScope) + { + Console.WriteLine("running compute_engine_creds"); + + var request = new SimpleRequest + { + ResponseSize = 314159, + Payload = CreateZerosPayload(271828), + FillUsername = true, + FillOauthScope = true + }; + + // not setting credentials here because they were set on channel already + var response = client.UnaryCall(request); + + Assert.AreEqual(314159, response.Payload.Body.Length); + Assert.False(string.IsNullOrEmpty(response.OauthScope)); + Assert.True(oauthScope.Contains(response.OauthScope)); + Assert.AreEqual(defaultServiceAccount, response.Username); + Console.WriteLine("Passed!"); + } + + public static void RunJwtTokenCreds(TestService.TestServiceClient client) + { + Console.WriteLine("running jwt_token_creds"); + + var request = new SimpleRequest + { + ResponseSize = 314159, + Payload = CreateZerosPayload(271828), + FillUsername = true, + }; + + // not setting credentials here because they were set on channel already + var response = client.UnaryCall(request); + + Assert.AreEqual(314159, response.Payload.Body.Length); + Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username); + Console.WriteLine("Passed!"); + } + + public static async Task RunOAuth2AuthTokenAsync(TestService.TestServiceClient client, string oauthScope) + { + Console.WriteLine("running oauth2_auth_token"); + ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { oauthScope }); + string oauth2Token = await credential.GetAccessTokenForRequestAsync(); + + var credentials = GoogleGrpcCredentials.FromAccessToken(oauth2Token); + var request = new SimpleRequest + { + FillUsername = true, + FillOauthScope = true + }; + + var response = client.UnaryCall(request, new CallOptions(credentials: credentials)); + + Assert.False(string.IsNullOrEmpty(response.OauthScope)); + Assert.True(oauthScope.Contains(response.OauthScope)); + Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username); + Console.WriteLine("Passed!"); + } + + public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client, string oauthScope) + { + Console.WriteLine("running per_rpc_creds"); + ITokenAccess googleCredential = await GoogleCredential.GetApplicationDefaultAsync(); + + var credentials = googleCredential.ToCallCredentials(); + var request = new SimpleRequest + { + FillUsername = true, + }; + + var response = client.UnaryCall(request, new CallOptions(credentials: credentials)); + + Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username); + Console.WriteLine("Passed!"); + } + + public static async Task RunCancelAfterBeginAsync(TestService.TestServiceClient client) + { + Console.WriteLine("running cancel_after_begin"); + + var cts = new CancellationTokenSource(); + using (var call = client.StreamingInputCall(cancellationToken: cts.Token)) + { + // TODO(jtattermusch): we need this to ensure call has been initiated once we cancel it. + await Task.Delay(1000); + cts.Cancel(); + + var ex = Assert.ThrowsAsync(async () => await call.ResponseAsync); + Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode); + } + Console.WriteLine("Passed!"); + } + + public static async Task RunCancelAfterFirstResponseAsync(TestService.TestServiceClient client) + { + Console.WriteLine("running cancel_after_first_response"); + + var cts = new CancellationTokenSource(); + using (var call = client.FullDuplexCall(cancellationToken: cts.Token)) + { + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest + { + ResponseParameters = { new ResponseParameters { Size = 31415 } }, + Payload = CreateZerosPayload(27182) + }); + + Assert.IsTrue(await call.ResponseStream.MoveNext()); + Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length); + + cts.Cancel(); + + try + { + // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock. + await call.ResponseStream.MoveNext(); + Assert.Fail(); + } + catch (RpcException ex) + { + Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode); + } + } + Console.WriteLine("Passed!"); + } + + public static async Task RunTimeoutOnSleepingServerAsync(TestService.TestServiceClient client) + { + Console.WriteLine("running timeout_on_sleeping_server"); + + var deadline = DateTime.UtcNow.AddMilliseconds(1); + using (var call = client.FullDuplexCall(deadline: deadline)) + { + try + { + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest { Payload = CreateZerosPayload(27182) }); + } + catch (InvalidOperationException) + { + // Deadline was reached before write has started. Eat the exception and continue. + } + catch (RpcException) + { + // Deadline was reached before write has started. Eat the exception and continue. + } + + try + { + await call.ResponseStream.MoveNext(); + Assert.Fail(); + } + catch (RpcException ex) + { + Assert.AreEqual(StatusCode.DeadlineExceeded, ex.Status.StatusCode); + } + } + Console.WriteLine("Passed!"); + } + + public static async Task RunCustomMetadataAsync(TestService.TestServiceClient client) + { + Console.WriteLine("running custom_metadata"); + { + // step 1: test unary call + var request = new SimpleRequest + { + ResponseSize = 314159, + Payload = CreateZerosPayload(271828) + }; + + var call = client.UnaryCallAsync(request, headers: CreateTestMetadata()); + await call.ResponseAsync; + + var responseHeaders = await call.ResponseHeadersAsync; + var responseTrailers = call.GetTrailers(); + + Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value); + CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes); + } + + { + // step 2: test full duplex call + var request = new StreamingOutputCallRequest + { + ResponseParameters = { new ResponseParameters { Size = 31415 } }, + Payload = CreateZerosPayload(27182) + }; + + var call = client.FullDuplexCall(headers: CreateTestMetadata()); + + await call.RequestStream.WriteAsync(request); + await call.RequestStream.CompleteAsync(); + await call.ResponseStream.ToListAsync(); + + var responseHeaders = await call.ResponseHeadersAsync; + var responseTrailers = call.GetTrailers(); + + Assert.AreEqual("test_initial_metadata_value", responseHeaders.First((entry) => entry.Key == "x-grpc-test-echo-initial").Value); + CollectionAssert.AreEqual(new byte[] { 0xab, 0xab, 0xab }, responseTrailers.First((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ValueBytes); + } + + Console.WriteLine("Passed!"); + } + + public static async Task RunStatusCodeAndMessageAsync(TestService.TestServiceClient client) + { + Console.WriteLine("running status_code_and_message"); + var echoStatus = new EchoStatus + { + Code = 2, + Message = "test status message" + }; + + { + // step 1: test unary call + var request = new SimpleRequest { ResponseStatus = echoStatus }; + + var e = Assert.Throws(() => client.UnaryCall(request)); + Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode); + Assert.AreEqual(echoStatus.Message, e.Status.Detail); + } + + { + // step 2: test full duplex call + var request = new StreamingOutputCallRequest { ResponseStatus = echoStatus }; + + var call = client.FullDuplexCall(); + await call.RequestStream.WriteAsync(request); + await call.RequestStream.CompleteAsync(); + + try + { + // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock. + await call.ResponseStream.ToListAsync(); + Assert.Fail(); + } + catch (RpcException e) + { + Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode); + Assert.AreEqual(echoStatus.Message, e.Status.Detail); + } + } + + Console.WriteLine("Passed!"); + } + + private static async Task RunSpecialStatusMessageAsync(TestService.TestServiceClient client) + { + Console.WriteLine("running special_status_message"); + + var echoStatus = new EchoStatus + { + Code = 2, + Message = "\t\ntest with whitespace\r\nand Unicode BMP ☺ and non-BMP 😈\t\n" + }; + + try + { + await client.UnaryCallAsync(new SimpleRequest + { + ResponseStatus = echoStatus + }); + Assert.Fail(); + } + catch (RpcException e) + { + Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode); + Assert.AreEqual(echoStatus.Message, e.Status.Detail); + } + + Console.WriteLine("Passed!"); + } + + public static void RunUnimplementedService(UnimplementedService.UnimplementedServiceClient client) + { + Console.WriteLine("running unimplemented_service"); + var e = Assert.Throws(() => client.UnimplementedCall(new Empty())); + + Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode); + Console.WriteLine("Passed!"); + } + + public static void RunUnimplementedMethod(TestService.TestServiceClient client) + { + Console.WriteLine("running unimplemented_method"); + var e = Assert.Throws(() => client.UnimplementedCall(new Empty())); + + Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode); + Console.WriteLine("Passed!"); + } + + public static void RunClientCompressedUnary(TestService.TestServiceClient client) + { + Console.WriteLine("running client_compressed_unary"); + var probeRequest = new SimpleRequest + { + ExpectCompressed = new BoolValue + { + Value = true // lie about compression + }, + ResponseSize = 314159, + Payload = CreateZerosPayload(271828) + }; + var e = Assert.Throws(() => client.UnaryCall(probeRequest, CreateClientCompressionMetadata(false))); + Assert.AreEqual(StatusCode.InvalidArgument, e.Status.StatusCode); + + var compressedRequest = new SimpleRequest + { + ExpectCompressed = new BoolValue + { + Value = true + }, + ResponseSize = 314159, + Payload = CreateZerosPayload(271828) + }; + var response1 = client.UnaryCall(compressedRequest, CreateClientCompressionMetadata(true)); + Assert.AreEqual(314159, response1.Payload.Body.Length); + + var uncompressedRequest = new SimpleRequest + { + ExpectCompressed = new BoolValue + { + Value = false + }, + ResponseSize = 314159, + Payload = CreateZerosPayload(271828) + }; + var response2 = client.UnaryCall(uncompressedRequest, CreateClientCompressionMetadata(false)); + Assert.AreEqual(314159, response2.Payload.Body.Length); + + Console.WriteLine("Passed!"); + } + + public static async Task RunClientCompressedStreamingAsync(TestService.TestServiceClient client) + { + Console.WriteLine("running client_compressed_streaming"); + try + { + var probeCall = client.StreamingInputCall(CreateClientCompressionMetadata(false)); + await probeCall.RequestStream.WriteAsync(new StreamingInputCallRequest + { + ExpectCompressed = new BoolValue + { + Value = true + }, + Payload = CreateZerosPayload(27182) + }); + + // cannot use Assert.ThrowsAsync because it uses Task.Wait and would deadlock. + await probeCall; + Assert.Fail(); + } + catch (RpcException e) + { + Assert.AreEqual(StatusCode.InvalidArgument, e.Status.StatusCode); + } + + var call = client.StreamingInputCall(CreateClientCompressionMetadata(true)); + await call.RequestStream.WriteAsync(new StreamingInputCallRequest + { + ExpectCompressed = new BoolValue + { + Value = true + }, + Payload = CreateZerosPayload(27182) + }); + + call.RequestStream.WriteOptions = new WriteOptions(WriteFlags.NoCompress); + await call.RequestStream.WriteAsync(new StreamingInputCallRequest + { + ExpectCompressed = new BoolValue + { + Value = false + }, + Payload = CreateZerosPayload(45904) + }); + await call.RequestStream.CompleteAsync(); + + var response = await call.ResponseAsync; + Assert.AreEqual(73086, response.AggregatedPayloadSize); + + Console.WriteLine("Passed!"); + } + + private static Payload CreateZerosPayload(int size) + { + return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; + } + + private static Metadata CreateClientCompressionMetadata(bool compressed) + { + var algorithmName = compressed ? "gzip" : "identity"; + return new Metadata + { + { new Metadata.Entry(Metadata.CompressionRequestAlgorithmMetadataKey, algorithmName) } + }; + } + + // extracts the client_email field from service account file used for auth test cases + private static string GetEmailFromServiceAccountFile() + { + string keyFile = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS"); + Assert.IsNotNull(keyFile); + var jobject = JObject.Parse(File.ReadAllText(keyFile)); + string email = jobject.GetValue("client_email").Value(); + Assert.IsTrue(email.Length > 0); // spec requires nonempty client email. + return email; + } + + private static Metadata CreateTestMetadata() + { + return new Metadata + { + {"x-grpc-test-echo-initial", "test_initial_metadata_value"}, + {"x-grpc-test-echo-trailing-bin", new byte[] {0xab, 0xab, 0xab}} + }; + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs new file mode 100644 index 00000000..e0fc259f --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs @@ -0,0 +1,146 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Testing; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + /// + /// Runs interop tests in-process. + /// + public class InteropClientServerTest + { + const string Host = "localhost"; + Server server; + Channel channel; + TestService.TestServiceClient client; + + [OneTimeSetUp] + public void Init() + { + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { TestService.BindService(new TestServiceImpl()) }, + Ports = { { Host, ServerPort.PickUnused, TestCredentials.CreateSslServerCredentials() } } + }; + server.Start(); + + var options = new List + { + new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride) + }; + int port = server.Ports.Single().BoundPort; + channel = new Channel(Host, port, TestCredentials.CreateSslCredentials(), options); + client = new TestService.TestServiceClient(channel); + } + + [OneTimeTearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void EmptyUnary() + { + InteropClient.RunEmptyUnary(client); + } + + [Test] + public void LargeUnary() + { + InteropClient.RunLargeUnary(client); + } + + [Test] + public async Task ClientStreaming() + { + await InteropClient.RunClientStreamingAsync(client); + } + + [Test] + public async Task ServerStreaming() + { + await InteropClient.RunServerStreamingAsync(client); + } + + [Test] + public async Task PingPong() + { + await InteropClient.RunPingPongAsync(client); + } + + [Test] + public async Task EmptyStream() + { + await InteropClient.RunEmptyStreamAsync(client); + } + + [Test] + public async Task CancelAfterBegin() + { + await InteropClient.RunCancelAfterBeginAsync(client); + } + + [Test] + public async Task CancelAfterFirstResponse() + { + await InteropClient.RunCancelAfterFirstResponseAsync(client); + } + + [Test] + public async Task TimeoutOnSleepingServer() + { + await InteropClient.RunTimeoutOnSleepingServerAsync(client); + } + + [Test] + public async Task CustomMetadata() + { + await InteropClient.RunCustomMetadataAsync(client); + } + + [Test] + public async Task StatusCodeAndMessage() + { + await InteropClient.RunStatusCodeAndMessageAsync(client); + } + + [Test] + public void UnimplementedService() + { + InteropClient.RunUnimplementedService(new UnimplementedService.UnimplementedServiceClient(channel)); + } + + [Test] + public void UnimplementedMethod() + { + InteropClient.RunUnimplementedMethod(client); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs new file mode 100644 index 00000000..aca73b15 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs @@ -0,0 +1,90 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +using CommandLine; +using CommandLine.Text; +using Grpc.Core; +using Grpc.Core.Logging; +using Grpc.Core.Utils; +using Grpc.Testing; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + public class InteropServer + { + private class ServerOptions + { + [Option("port", Default = 8070)] + public int Port { get; set; } + + // Deliberately using nullable bool type to allow --use_tls=true syntax (as opposed to --use_tls) + [Option("use_tls", Default = false)] + public bool? UseTls { get; set; } + } + + ServerOptions options; + + private InteropServer(ServerOptions options) + { + this.options = options; + } + + public static void Run(string[] args) + { + GrpcEnvironment.SetLogger(new ConsoleLogger()); + var parserResult = Parser.Default.ParseArguments(args) + .WithNotParsed(errors => Environment.Exit(1)) + .WithParsed(options => + { + var interopServer = new InteropServer(options); + interopServer.Run(); + }); + } + + private void Run() + { + var server = new Server + { + Services = { TestService.BindService(new TestServiceImpl()) } + }; + + string host = "0.0.0.0"; + int port = options.Port; + if (options.UseTls.Value) + { + server.Ports.Add(host, port, TestCredentials.CreateSslServerCredentials()); + } + else + { + server.Ports.Add(host, options.Port, ServerCredentials.Insecure); + } + Console.WriteLine("Running server on " + string.Format("{0}:{1}", host, port)); + server.Start(); + + server.ShutdownTask.Wait(); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/Messages.cs b/src/csharp/Grpc.IntegrationTesting/Messages.cs new file mode 100644 index 00000000..8c051ceb --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/Messages.cs @@ -0,0 +1,5546 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/messages.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Testing { + + /// Holder for reflection information generated from src/proto/grpc/testing/messages.proto + public static partial class MessagesReflection { + + #region Descriptor + /// File descriptor for src/proto/grpc/testing/messages.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static MessagesReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CiVzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL21lc3NhZ2VzLnByb3RvEgxncnBj", + "LnRlc3RpbmciGgoJQm9vbFZhbHVlEg0KBXZhbHVlGAEgASgIIkAKB1BheWxv", + "YWQSJwoEdHlwZRgBIAEoDjIZLmdycGMudGVzdGluZy5QYXlsb2FkVHlwZRIM", + "CgRib2R5GAIgASgMIisKCkVjaG9TdGF0dXMSDAoEY29kZRgBIAEoBRIPCgdt", + "ZXNzYWdlGAIgASgJIoYDCg1TaW1wbGVSZXF1ZXN0EjAKDXJlc3BvbnNlX3R5", + "cGUYASABKA4yGS5ncnBjLnRlc3RpbmcuUGF5bG9hZFR5cGUSFQoNcmVzcG9u", + "c2Vfc2l6ZRgCIAEoBRImCgdwYXlsb2FkGAMgASgLMhUuZ3JwYy50ZXN0aW5n", + "LlBheWxvYWQSFQoNZmlsbF91c2VybmFtZRgEIAEoCBIYChBmaWxsX29hdXRo", + "X3Njb3BlGAUgASgIEjQKE3Jlc3BvbnNlX2NvbXByZXNzZWQYBiABKAsyFy5n", + "cnBjLnRlc3RpbmcuQm9vbFZhbHVlEjEKD3Jlc3BvbnNlX3N0YXR1cxgHIAEo", + "CzIYLmdycGMudGVzdGluZy5FY2hvU3RhdHVzEjIKEWV4cGVjdF9jb21wcmVz", + "c2VkGAggASgLMhcuZ3JwYy50ZXN0aW5nLkJvb2xWYWx1ZRIWCg5maWxsX3Nl", + "cnZlcl9pZBgJIAEoCBIeChZmaWxsX2dycGNsYl9yb3V0ZV90eXBlGAogASgI", + "Ir4BCg5TaW1wbGVSZXNwb25zZRImCgdwYXlsb2FkGAEgASgLMhUuZ3JwYy50", + "ZXN0aW5nLlBheWxvYWQSEAoIdXNlcm5hbWUYAiABKAkSEwoLb2F1dGhfc2Nv", + "cGUYAyABKAkSEQoJc2VydmVyX2lkGAQgASgJEjgKEWdycGNsYl9yb3V0ZV90", + "eXBlGAUgASgOMh0uZ3JwYy50ZXN0aW5nLkdycGNsYlJvdXRlVHlwZRIQCgho", + "b3N0bmFtZRgGIAEoCSJ3ChlTdHJlYW1pbmdJbnB1dENhbGxSZXF1ZXN0EiYK", + "B3BheWxvYWQYASABKAsyFS5ncnBjLnRlc3RpbmcuUGF5bG9hZBIyChFleHBl", + "Y3RfY29tcHJlc3NlZBgCIAEoCzIXLmdycGMudGVzdGluZy5Cb29sVmFsdWUi", + "PQoaU3RyZWFtaW5nSW5wdXRDYWxsUmVzcG9uc2USHwoXYWdncmVnYXRlZF9w", + "YXlsb2FkX3NpemUYASABKAUiZAoSUmVzcG9uc2VQYXJhbWV0ZXJzEgwKBHNp", + "emUYASABKAUSEwoLaW50ZXJ2YWxfdXMYAiABKAUSKwoKY29tcHJlc3NlZBgD", + "IAEoCzIXLmdycGMudGVzdGluZy5Cb29sVmFsdWUi6AEKGlN0cmVhbWluZ091", + "dHB1dENhbGxSZXF1ZXN0EjAKDXJlc3BvbnNlX3R5cGUYASABKA4yGS5ncnBj", + "LnRlc3RpbmcuUGF5bG9hZFR5cGUSPQoTcmVzcG9uc2VfcGFyYW1ldGVycxgC", + "IAMoCzIgLmdycGMudGVzdGluZy5SZXNwb25zZVBhcmFtZXRlcnMSJgoHcGF5", + "bG9hZBgDIAEoCzIVLmdycGMudGVzdGluZy5QYXlsb2FkEjEKD3Jlc3BvbnNl", + "X3N0YXR1cxgHIAEoCzIYLmdycGMudGVzdGluZy5FY2hvU3RhdHVzIkUKG1N0", + "cmVhbWluZ091dHB1dENhbGxSZXNwb25zZRImCgdwYXlsb2FkGAEgASgLMhUu", + "Z3JwYy50ZXN0aW5nLlBheWxvYWQiMwoPUmVjb25uZWN0UGFyYW1zEiAKGG1h", + "eF9yZWNvbm5lY3RfYmFja29mZl9tcxgBIAEoBSIzCg1SZWNvbm5lY3RJbmZv", + "Eg4KBnBhc3NlZBgBIAEoCBISCgpiYWNrb2ZmX21zGAIgAygFIkEKGExvYWRC", + "YWxhbmNlclN0YXRzUmVxdWVzdBIQCghudW1fcnBjcxgBIAEoBRITCgt0aW1l", + "b3V0X3NlYxgCIAEoBSKLBAoZTG9hZEJhbGFuY2VyU3RhdHNSZXNwb25zZRJN", + "CgxycGNzX2J5X3BlZXIYASADKAsyNy5ncnBjLnRlc3RpbmcuTG9hZEJhbGFu", + "Y2VyU3RhdHNSZXNwb25zZS5ScGNzQnlQZWVyRW50cnkSFAoMbnVtX2ZhaWx1", + "cmVzGAIgASgFElEKDnJwY3NfYnlfbWV0aG9kGAMgAygLMjkuZ3JwYy50ZXN0", + "aW5nLkxvYWRCYWxhbmNlclN0YXRzUmVzcG9uc2UuUnBjc0J5TWV0aG9kRW50", + "cnkamQEKClJwY3NCeVBlZXISWAoMcnBjc19ieV9wZWVyGAEgAygLMkIuZ3Jw", + "Yy50ZXN0aW5nLkxvYWRCYWxhbmNlclN0YXRzUmVzcG9uc2UuUnBjc0J5UGVl", + "ci5ScGNzQnlQZWVyRW50cnkaMQoPUnBjc0J5UGVlckVudHJ5EgsKA2tleRgB", + "IAEoCRINCgV2YWx1ZRgCIAEoBToCOAEaMQoPUnBjc0J5UGVlckVudHJ5EgsK", + "A2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoBToCOAEaZwoRUnBjc0J5TWV0aG9k", + "RW50cnkSCwoDa2V5GAEgASgJEkEKBXZhbHVlGAIgASgLMjIuZ3JwYy50ZXN0", + "aW5nLkxvYWRCYWxhbmNlclN0YXRzUmVzcG9uc2UuUnBjc0J5UGVlcjoCOAEi", + "JQojTG9hZEJhbGFuY2VyQWNjdW11bGF0ZWRTdGF0c1JlcXVlc3Qi2AcKJExv", + "YWRCYWxhbmNlckFjY3VtdWxhdGVkU3RhdHNSZXNwb25zZRJ2ChpudW1fcnBj", + "c19zdGFydGVkX2J5X21ldGhvZBgBIAMoCzJOLmdycGMudGVzdGluZy5Mb2Fk", + "QmFsYW5jZXJBY2N1bXVsYXRlZFN0YXRzUmVzcG9uc2UuTnVtUnBjc1N0YXJ0", + "ZWRCeU1ldGhvZEVudHJ5QgIYARJ6ChxudW1fcnBjc19zdWNjZWVkZWRfYnlf", + "bWV0aG9kGAIgAygLMlAuZ3JwYy50ZXN0aW5nLkxvYWRCYWxhbmNlckFjY3Vt", + "dWxhdGVkU3RhdHNSZXNwb25zZS5OdW1ScGNzU3VjY2VlZGVkQnlNZXRob2RF", + "bnRyeUICGAESdAoZbnVtX3JwY3NfZmFpbGVkX2J5X21ldGhvZBgDIAMoCzJN", + "LmdycGMudGVzdGluZy5Mb2FkQmFsYW5jZXJBY2N1bXVsYXRlZFN0YXRzUmVz", + "cG9uc2UuTnVtUnBjc0ZhaWxlZEJ5TWV0aG9kRW50cnlCAhgBEmAKEHN0YXRz", + "X3Blcl9tZXRob2QYBCADKAsyRi5ncnBjLnRlc3RpbmcuTG9hZEJhbGFuY2Vy", + "QWNjdW11bGF0ZWRTdGF0c1Jlc3BvbnNlLlN0YXRzUGVyTWV0aG9kRW50cnka", + "PQobTnVtUnBjc1N0YXJ0ZWRCeU1ldGhvZEVudHJ5EgsKA2tleRgBIAEoCRIN", + "CgV2YWx1ZRgCIAEoBToCOAEaPwodTnVtUnBjc1N1Y2NlZWRlZEJ5TWV0aG9k", + "RW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ARo8ChpOdW1S", + "cGNzRmFpbGVkQnlNZXRob2RFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUY", + "AiABKAU6AjgBGq4BCgtNZXRob2RTdGF0cxIUCgxycGNzX3N0YXJ0ZWQYASAB", + "KAUSWgoGcmVzdWx0GAIgAygLMkouZ3JwYy50ZXN0aW5nLkxvYWRCYWxhbmNl", + "ckFjY3VtdWxhdGVkU3RhdHNSZXNwb25zZS5NZXRob2RTdGF0cy5SZXN1bHRF", + "bnRyeRotCgtSZXN1bHRFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUYAiAB", + "KAU6AjgBGnUKE1N0YXRzUGVyTWV0aG9kRW50cnkSCwoDa2V5GAEgASgJEk0K", + "BXZhbHVlGAIgASgLMj4uZ3JwYy50ZXN0aW5nLkxvYWRCYWxhbmNlckFjY3Vt", + "dWxhdGVkU3RhdHNSZXNwb25zZS5NZXRob2RTdGF0czoCOAEiugIKFkNsaWVu", + "dENvbmZpZ3VyZVJlcXVlc3QSOwoFdHlwZXMYASADKA4yLC5ncnBjLnRlc3Rp", + "bmcuQ2xpZW50Q29uZmlndXJlUmVxdWVzdC5ScGNUeXBlEj8KCG1ldGFkYXRh", + "GAIgAygLMi0uZ3JwYy50ZXN0aW5nLkNsaWVudENvbmZpZ3VyZVJlcXVlc3Qu", + "TWV0YWRhdGESEwoLdGltZW91dF9zZWMYAyABKAUaYgoITWV0YWRhdGESOgoE", + "dHlwZRgBIAEoDjIsLmdycGMudGVzdGluZy5DbGllbnRDb25maWd1cmVSZXF1", + "ZXN0LlJwY1R5cGUSCwoDa2V5GAIgASgJEg0KBXZhbHVlGAMgASgJIikKB1Jw", + "Y1R5cGUSDgoKRU1QVFlfQ0FMTBAAEg4KClVOQVJZX0NBTEwQASIZChdDbGll", + "bnRDb25maWd1cmVSZXNwb25zZSofCgtQYXlsb2FkVHlwZRIQCgxDT01QUkVT", + "U0FCTEUQACpvCg9HcnBjbGJSb3V0ZVR5cGUSHQoZR1JQQ0xCX1JPVVRFX1RZ", + "UEVfVU5LTk9XThAAEh4KGkdSUENMQl9ST1VURV9UWVBFX0ZBTExCQUNLEAES", + "HQoZR1JQQ0xCX1JPVVRFX1RZUEVfQkFDS0VORBACYgZwcm90bzM=")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.PayloadType), typeof(global::Grpc.Testing.GrpclbRouteType), }, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.BoolValue), global::Grpc.Testing.BoolValue.Parser, new[]{ "Value" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Payload), global::Grpc.Testing.Payload.Parser, new[]{ "Type", "Body" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EchoStatus), global::Grpc.Testing.EchoStatus.Parser, new[]{ "Code", "Message" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SimpleRequest), global::Grpc.Testing.SimpleRequest.Parser, new[]{ "ResponseType", "ResponseSize", "Payload", "FillUsername", "FillOauthScope", "ResponseCompressed", "ResponseStatus", "ExpectCompressed", "FillServerId", "FillGrpclbRouteType" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SimpleResponse), global::Grpc.Testing.SimpleResponse.Parser, new[]{ "Payload", "Username", "OauthScope", "ServerId", "GrpclbRouteType", "Hostname" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingInputCallRequest), global::Grpc.Testing.StreamingInputCallRequest.Parser, new[]{ "Payload", "ExpectCompressed" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingInputCallResponse), global::Grpc.Testing.StreamingInputCallResponse.Parser, new[]{ "AggregatedPayloadSize" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ResponseParameters), global::Grpc.Testing.ResponseParameters.Parser, new[]{ "Size", "IntervalUs", "Compressed" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingOutputCallRequest), global::Grpc.Testing.StreamingOutputCallRequest.Parser, new[]{ "ResponseType", "ResponseParameters", "Payload", "ResponseStatus" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.StreamingOutputCallResponse), global::Grpc.Testing.StreamingOutputCallResponse.Parser, new[]{ "Payload" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ReconnectParams), global::Grpc.Testing.ReconnectParams.Parser, new[]{ "MaxReconnectBackoffMs" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ReconnectInfo), global::Grpc.Testing.ReconnectInfo.Parser, new[]{ "Passed", "BackoffMs" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadBalancerStatsRequest), global::Grpc.Testing.LoadBalancerStatsRequest.Parser, new[]{ "NumRpcs", "TimeoutSec" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadBalancerStatsResponse), global::Grpc.Testing.LoadBalancerStatsResponse.Parser, new[]{ "RpcsByPeer", "NumFailures", "RpcsByMethod" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadBalancerStatsResponse.Types.RpcsByPeer), global::Grpc.Testing.LoadBalancerStatsResponse.Types.RpcsByPeer.Parser, new[]{ "RpcsByPeer_" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, }), + null, null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadBalancerAccumulatedStatsRequest), global::Grpc.Testing.LoadBalancerAccumulatedStatsRequest.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadBalancerAccumulatedStatsResponse), global::Grpc.Testing.LoadBalancerAccumulatedStatsResponse.Parser, new[]{ "NumRpcsStartedByMethod", "NumRpcsSucceededByMethod", "NumRpcsFailedByMethod", "StatsPerMethod" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, null, new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadBalancerAccumulatedStatsResponse.Types.MethodStats), global::Grpc.Testing.LoadBalancerAccumulatedStatsResponse.Types.MethodStats.Parser, new[]{ "RpcsStarted", "Result" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, }), + null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfigureRequest), global::Grpc.Testing.ClientConfigureRequest.Parser, new[]{ "Types_", "Metadata", "TimeoutSec" }, null, new[]{ typeof(global::Grpc.Testing.ClientConfigureRequest.Types.RpcType) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfigureRequest.Types.Metadata), global::Grpc.Testing.ClientConfigureRequest.Types.Metadata.Parser, new[]{ "Type", "Key", "Value" }, null, null, null, null)}), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfigureResponse), global::Grpc.Testing.ClientConfigureResponse.Parser, null, null, null, null, null) + })); + } + #endregion + + } + #region Enums + /// + /// The type of payload that should be returned. + /// + public enum PayloadType { + /// + /// Compressable text format. + /// + [pbr::OriginalName("COMPRESSABLE")] Compressable = 0, + } + + /// + /// The type of route that a client took to reach a server w.r.t. gRPCLB. + /// The server must fill in "fallback" if it detects that the RPC reached + /// the server via the "gRPCLB fallback" path, and "backend" if it detects + /// that the RPC reached the server via "gRPCLB backend" path (i.e. if it got + /// the address of this server from the gRPCLB server BalanceLoad RPC). Exactly + /// how this detection is done is context and server dependent. + /// + public enum GrpclbRouteType { + /// + /// Server didn't detect the route that a client took to reach it. + /// + [pbr::OriginalName("GRPCLB_ROUTE_TYPE_UNKNOWN")] Unknown = 0, + /// + /// Indicates that a client reached a server via gRPCLB fallback. + /// + [pbr::OriginalName("GRPCLB_ROUTE_TYPE_FALLBACK")] Fallback = 1, + /// + /// Indicates that a client reached a server as a gRPCLB-given backend. + /// + [pbr::OriginalName("GRPCLB_ROUTE_TYPE_BACKEND")] Backend = 2, + } + + #endregion + + #region Messages + /// + /// TODO(dgq): Go back to using well-known types once + /// https://github.com/grpc/grpc/issues/6980 has been fixed. + /// import "google/protobuf/wrappers.proto"; + /// + public sealed partial class BoolValue : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BoolValue()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public BoolValue() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public BoolValue(BoolValue other) : this() { + value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public BoolValue Clone() { + return new BoolValue(this); + } + + /// Field number for the "value" field. + public const int ValueFieldNumber = 1; + private bool value_; + /// + /// The bool value. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Value { + get { return value_; } + set { + value_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as BoolValue); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(BoolValue other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Value != other.Value) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Value != false) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Value != false) { + output.WriteRawTag(8); + output.WriteBool(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Value != false) { + output.WriteRawTag(8); + output.WriteBool(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Value != false) { + size += 1 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(BoolValue other) { + if (other == null) { + return; + } + if (other.Value != false) { + Value = other.Value; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Value = input.ReadBool(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Value = input.ReadBool(); + break; + } + } + } + } + #endif + + } + + /// + /// A block of data, to simply increase gRPC message size. + /// + public sealed partial class Payload : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Payload()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Payload() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Payload(Payload other) : this() { + type_ = other.type_; + body_ = other.body_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Payload Clone() { + return new Payload(this); + } + + /// Field number for the "type" field. + public const int TypeFieldNumber = 1; + private global::Grpc.Testing.PayloadType type_ = global::Grpc.Testing.PayloadType.Compressable; + /// + /// The type of data in body. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.PayloadType Type { + get { return type_; } + set { + type_ = value; + } + } + + /// Field number for the "body" field. + public const int BodyFieldNumber = 2; + private pb::ByteString body_ = pb::ByteString.Empty; + /// + /// Primary contents of payload. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pb::ByteString Body { + get { return body_; } + set { + body_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Payload); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Payload other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Type != other.Type) return false; + if (Body != other.Body) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Type != global::Grpc.Testing.PayloadType.Compressable) hash ^= Type.GetHashCode(); + if (Body.Length != 0) hash ^= Body.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Type != global::Grpc.Testing.PayloadType.Compressable) { + output.WriteRawTag(8); + output.WriteEnum((int) Type); + } + if (Body.Length != 0) { + output.WriteRawTag(18); + output.WriteBytes(Body); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Type != global::Grpc.Testing.PayloadType.Compressable) { + output.WriteRawTag(8); + output.WriteEnum((int) Type); + } + if (Body.Length != 0) { + output.WriteRawTag(18); + output.WriteBytes(Body); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Type != global::Grpc.Testing.PayloadType.Compressable) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); + } + if (Body.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(Body); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Payload other) { + if (other == null) { + return; + } + if (other.Type != global::Grpc.Testing.PayloadType.Compressable) { + Type = other.Type; + } + if (other.Body.Length != 0) { + Body = other.Body; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Type = (global::Grpc.Testing.PayloadType) input.ReadEnum(); + break; + } + case 18: { + Body = input.ReadBytes(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Type = (global::Grpc.Testing.PayloadType) input.ReadEnum(); + break; + } + case 18: { + Body = input.ReadBytes(); + break; + } + } + } + } + #endif + + } + + /// + /// A protobuf representation for grpc status. This is used by test + /// clients to specify a status that the server should attempt to return. + /// + public sealed partial class EchoStatus : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EchoStatus()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EchoStatus() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EchoStatus(EchoStatus other) : this() { + code_ = other.code_; + message_ = other.message_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EchoStatus Clone() { + return new EchoStatus(this); + } + + /// Field number for the "code" field. + public const int CodeFieldNumber = 1; + private int code_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int Code { + get { return code_; } + set { + code_ = value; + } + } + + /// Field number for the "message" field. + public const int MessageFieldNumber = 2; + private string message_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Message { + get { return message_; } + set { + message_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as EchoStatus); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(EchoStatus other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Code != other.Code) return false; + if (Message != other.Message) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Code != 0) hash ^= Code.GetHashCode(); + if (Message.Length != 0) hash ^= Message.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Code != 0) { + output.WriteRawTag(8); + output.WriteInt32(Code); + } + if (Message.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Message); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Code != 0) { + output.WriteRawTag(8); + output.WriteInt32(Code); + } + if (Message.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Message); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Code != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Code); + } + if (Message.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Message); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(EchoStatus other) { + if (other == null) { + return; + } + if (other.Code != 0) { + Code = other.Code; + } + if (other.Message.Length != 0) { + Message = other.Message; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Code = input.ReadInt32(); + break; + } + case 18: { + Message = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Code = input.ReadInt32(); + break; + } + case 18: { + Message = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// Unary request. + /// + public sealed partial class SimpleRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SimpleRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SimpleRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SimpleRequest(SimpleRequest other) : this() { + responseType_ = other.responseType_; + responseSize_ = other.responseSize_; + payload_ = other.payload_ != null ? other.payload_.Clone() : null; + fillUsername_ = other.fillUsername_; + fillOauthScope_ = other.fillOauthScope_; + responseCompressed_ = other.responseCompressed_ != null ? other.responseCompressed_.Clone() : null; + responseStatus_ = other.responseStatus_ != null ? other.responseStatus_.Clone() : null; + expectCompressed_ = other.expectCompressed_ != null ? other.expectCompressed_.Clone() : null; + fillServerId_ = other.fillServerId_; + fillGrpclbRouteType_ = other.fillGrpclbRouteType_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SimpleRequest Clone() { + return new SimpleRequest(this); + } + + /// Field number for the "response_type" field. + public const int ResponseTypeFieldNumber = 1; + private global::Grpc.Testing.PayloadType responseType_ = global::Grpc.Testing.PayloadType.Compressable; + /// + /// Desired payload type in the response from the server. + /// If response_type is RANDOM, server randomly chooses one from other formats. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.PayloadType ResponseType { + get { return responseType_; } + set { + responseType_ = value; + } + } + + /// Field number for the "response_size" field. + public const int ResponseSizeFieldNumber = 2; + private int responseSize_; + /// + /// Desired payload size in the response from the server. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ResponseSize { + get { return responseSize_; } + set { + responseSize_ = value; + } + } + + /// Field number for the "payload" field. + public const int PayloadFieldNumber = 3; + private global::Grpc.Testing.Payload payload_; + /// + /// Optional input payload sent along with the request. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.Payload Payload { + get { return payload_; } + set { + payload_ = value; + } + } + + /// Field number for the "fill_username" field. + public const int FillUsernameFieldNumber = 4; + private bool fillUsername_; + /// + /// Whether SimpleResponse should include username. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool FillUsername { + get { return fillUsername_; } + set { + fillUsername_ = value; + } + } + + /// Field number for the "fill_oauth_scope" field. + public const int FillOauthScopeFieldNumber = 5; + private bool fillOauthScope_; + /// + /// Whether SimpleResponse should include OAuth scope. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool FillOauthScope { + get { return fillOauthScope_; } + set { + fillOauthScope_ = value; + } + } + + /// Field number for the "response_compressed" field. + public const int ResponseCompressedFieldNumber = 6; + private global::Grpc.Testing.BoolValue responseCompressed_; + /// + /// Whether to request the server to compress the response. This field is + /// "nullable" in order to interoperate seamlessly with clients not able to + /// implement the full compression tests by introspecting the call to verify + /// the response's compression status. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.BoolValue ResponseCompressed { + get { return responseCompressed_; } + set { + responseCompressed_ = value; + } + } + + /// Field number for the "response_status" field. + public const int ResponseStatusFieldNumber = 7; + private global::Grpc.Testing.EchoStatus responseStatus_; + /// + /// Whether server should return a given status + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.EchoStatus ResponseStatus { + get { return responseStatus_; } + set { + responseStatus_ = value; + } + } + + /// Field number for the "expect_compressed" field. + public const int ExpectCompressedFieldNumber = 8; + private global::Grpc.Testing.BoolValue expectCompressed_; + /// + /// Whether the server should expect this request to be compressed. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.BoolValue ExpectCompressed { + get { return expectCompressed_; } + set { + expectCompressed_ = value; + } + } + + /// Field number for the "fill_server_id" field. + public const int FillServerIdFieldNumber = 9; + private bool fillServerId_; + /// + /// Whether SimpleResponse should include server_id. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool FillServerId { + get { return fillServerId_; } + set { + fillServerId_ = value; + } + } + + /// Field number for the "fill_grpclb_route_type" field. + public const int FillGrpclbRouteTypeFieldNumber = 10; + private bool fillGrpclbRouteType_; + /// + /// Whether SimpleResponse should include grpclb_route_type. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool FillGrpclbRouteType { + get { return fillGrpclbRouteType_; } + set { + fillGrpclbRouteType_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as SimpleRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(SimpleRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ResponseType != other.ResponseType) return false; + if (ResponseSize != other.ResponseSize) return false; + if (!object.Equals(Payload, other.Payload)) return false; + if (FillUsername != other.FillUsername) return false; + if (FillOauthScope != other.FillOauthScope) return false; + if (!object.Equals(ResponseCompressed, other.ResponseCompressed)) return false; + if (!object.Equals(ResponseStatus, other.ResponseStatus)) return false; + if (!object.Equals(ExpectCompressed, other.ExpectCompressed)) return false; + if (FillServerId != other.FillServerId) return false; + if (FillGrpclbRouteType != other.FillGrpclbRouteType) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (ResponseType != global::Grpc.Testing.PayloadType.Compressable) hash ^= ResponseType.GetHashCode(); + if (ResponseSize != 0) hash ^= ResponseSize.GetHashCode(); + if (payload_ != null) hash ^= Payload.GetHashCode(); + if (FillUsername != false) hash ^= FillUsername.GetHashCode(); + if (FillOauthScope != false) hash ^= FillOauthScope.GetHashCode(); + if (responseCompressed_ != null) hash ^= ResponseCompressed.GetHashCode(); + if (responseStatus_ != null) hash ^= ResponseStatus.GetHashCode(); + if (expectCompressed_ != null) hash ^= ExpectCompressed.GetHashCode(); + if (FillServerId != false) hash ^= FillServerId.GetHashCode(); + if (FillGrpclbRouteType != false) hash ^= FillGrpclbRouteType.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (ResponseType != global::Grpc.Testing.PayloadType.Compressable) { + output.WriteRawTag(8); + output.WriteEnum((int) ResponseType); + } + if (ResponseSize != 0) { + output.WriteRawTag(16); + output.WriteInt32(ResponseSize); + } + if (payload_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Payload); + } + if (FillUsername != false) { + output.WriteRawTag(32); + output.WriteBool(FillUsername); + } + if (FillOauthScope != false) { + output.WriteRawTag(40); + output.WriteBool(FillOauthScope); + } + if (responseCompressed_ != null) { + output.WriteRawTag(50); + output.WriteMessage(ResponseCompressed); + } + if (responseStatus_ != null) { + output.WriteRawTag(58); + output.WriteMessage(ResponseStatus); + } + if (expectCompressed_ != null) { + output.WriteRawTag(66); + output.WriteMessage(ExpectCompressed); + } + if (FillServerId != false) { + output.WriteRawTag(72); + output.WriteBool(FillServerId); + } + if (FillGrpclbRouteType != false) { + output.WriteRawTag(80); + output.WriteBool(FillGrpclbRouteType); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (ResponseType != global::Grpc.Testing.PayloadType.Compressable) { + output.WriteRawTag(8); + output.WriteEnum((int) ResponseType); + } + if (ResponseSize != 0) { + output.WriteRawTag(16); + output.WriteInt32(ResponseSize); + } + if (payload_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Payload); + } + if (FillUsername != false) { + output.WriteRawTag(32); + output.WriteBool(FillUsername); + } + if (FillOauthScope != false) { + output.WriteRawTag(40); + output.WriteBool(FillOauthScope); + } + if (responseCompressed_ != null) { + output.WriteRawTag(50); + output.WriteMessage(ResponseCompressed); + } + if (responseStatus_ != null) { + output.WriteRawTag(58); + output.WriteMessage(ResponseStatus); + } + if (expectCompressed_ != null) { + output.WriteRawTag(66); + output.WriteMessage(ExpectCompressed); + } + if (FillServerId != false) { + output.WriteRawTag(72); + output.WriteBool(FillServerId); + } + if (FillGrpclbRouteType != false) { + output.WriteRawTag(80); + output.WriteBool(FillGrpclbRouteType); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (ResponseType != global::Grpc.Testing.PayloadType.Compressable) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseType); + } + if (ResponseSize != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ResponseSize); + } + if (payload_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); + } + if (FillUsername != false) { + size += 1 + 1; + } + if (FillOauthScope != false) { + size += 1 + 1; + } + if (responseCompressed_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ResponseCompressed); + } + if (responseStatus_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ResponseStatus); + } + if (expectCompressed_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExpectCompressed); + } + if (FillServerId != false) { + size += 1 + 1; + } + if (FillGrpclbRouteType != false) { + size += 1 + 1; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(SimpleRequest other) { + if (other == null) { + return; + } + if (other.ResponseType != global::Grpc.Testing.PayloadType.Compressable) { + ResponseType = other.ResponseType; + } + if (other.ResponseSize != 0) { + ResponseSize = other.ResponseSize; + } + if (other.payload_ != null) { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + Payload.MergeFrom(other.Payload); + } + if (other.FillUsername != false) { + FillUsername = other.FillUsername; + } + if (other.FillOauthScope != false) { + FillOauthScope = other.FillOauthScope; + } + if (other.responseCompressed_ != null) { + if (responseCompressed_ == null) { + ResponseCompressed = new global::Grpc.Testing.BoolValue(); + } + ResponseCompressed.MergeFrom(other.ResponseCompressed); + } + if (other.responseStatus_ != null) { + if (responseStatus_ == null) { + ResponseStatus = new global::Grpc.Testing.EchoStatus(); + } + ResponseStatus.MergeFrom(other.ResponseStatus); + } + if (other.expectCompressed_ != null) { + if (expectCompressed_ == null) { + ExpectCompressed = new global::Grpc.Testing.BoolValue(); + } + ExpectCompressed.MergeFrom(other.ExpectCompressed); + } + if (other.FillServerId != false) { + FillServerId = other.FillServerId; + } + if (other.FillGrpclbRouteType != false) { + FillGrpclbRouteType = other.FillGrpclbRouteType; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + ResponseType = (global::Grpc.Testing.PayloadType) input.ReadEnum(); + break; + } + case 16: { + ResponseSize = input.ReadInt32(); + break; + } + case 26: { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + input.ReadMessage(Payload); + break; + } + case 32: { + FillUsername = input.ReadBool(); + break; + } + case 40: { + FillOauthScope = input.ReadBool(); + break; + } + case 50: { + if (responseCompressed_ == null) { + ResponseCompressed = new global::Grpc.Testing.BoolValue(); + } + input.ReadMessage(ResponseCompressed); + break; + } + case 58: { + if (responseStatus_ == null) { + ResponseStatus = new global::Grpc.Testing.EchoStatus(); + } + input.ReadMessage(ResponseStatus); + break; + } + case 66: { + if (expectCompressed_ == null) { + ExpectCompressed = new global::Grpc.Testing.BoolValue(); + } + input.ReadMessage(ExpectCompressed); + break; + } + case 72: { + FillServerId = input.ReadBool(); + break; + } + case 80: { + FillGrpclbRouteType = input.ReadBool(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + ResponseType = (global::Grpc.Testing.PayloadType) input.ReadEnum(); + break; + } + case 16: { + ResponseSize = input.ReadInt32(); + break; + } + case 26: { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + input.ReadMessage(Payload); + break; + } + case 32: { + FillUsername = input.ReadBool(); + break; + } + case 40: { + FillOauthScope = input.ReadBool(); + break; + } + case 50: { + if (responseCompressed_ == null) { + ResponseCompressed = new global::Grpc.Testing.BoolValue(); + } + input.ReadMessage(ResponseCompressed); + break; + } + case 58: { + if (responseStatus_ == null) { + ResponseStatus = new global::Grpc.Testing.EchoStatus(); + } + input.ReadMessage(ResponseStatus); + break; + } + case 66: { + if (expectCompressed_ == null) { + ExpectCompressed = new global::Grpc.Testing.BoolValue(); + } + input.ReadMessage(ExpectCompressed); + break; + } + case 72: { + FillServerId = input.ReadBool(); + break; + } + case 80: { + FillGrpclbRouteType = input.ReadBool(); + break; + } + } + } + } + #endif + + } + + /// + /// Unary response, as configured by the request. + /// + public sealed partial class SimpleResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SimpleResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SimpleResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SimpleResponse(SimpleResponse other) : this() { + payload_ = other.payload_ != null ? other.payload_.Clone() : null; + username_ = other.username_; + oauthScope_ = other.oauthScope_; + serverId_ = other.serverId_; + grpclbRouteType_ = other.grpclbRouteType_; + hostname_ = other.hostname_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SimpleResponse Clone() { + return new SimpleResponse(this); + } + + /// Field number for the "payload" field. + public const int PayloadFieldNumber = 1; + private global::Grpc.Testing.Payload payload_; + /// + /// Payload to increase message size. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.Payload Payload { + get { return payload_; } + set { + payload_ = value; + } + } + + /// Field number for the "username" field. + public const int UsernameFieldNumber = 2; + private string username_ = ""; + /// + /// The user the request came from, for verifying authentication was + /// successful when the client expected it. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Username { + get { return username_; } + set { + username_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "oauth_scope" field. + public const int OauthScopeFieldNumber = 3; + private string oauthScope_ = ""; + /// + /// OAuth scope. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string OauthScope { + get { return oauthScope_; } + set { + oauthScope_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "server_id" field. + public const int ServerIdFieldNumber = 4; + private string serverId_ = ""; + /// + /// Server ID. This must be unique among different server instances, + /// but the same across all RPC's made to a particular server instance. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ServerId { + get { return serverId_; } + set { + serverId_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "grpclb_route_type" field. + public const int GrpclbRouteTypeFieldNumber = 5; + private global::Grpc.Testing.GrpclbRouteType grpclbRouteType_ = global::Grpc.Testing.GrpclbRouteType.Unknown; + /// + /// gRPCLB Path. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.GrpclbRouteType GrpclbRouteType { + get { return grpclbRouteType_; } + set { + grpclbRouteType_ = value; + } + } + + /// Field number for the "hostname" field. + public const int HostnameFieldNumber = 6; + private string hostname_ = ""; + /// + /// Server hostname. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Hostname { + get { return hostname_; } + set { + hostname_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as SimpleResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(SimpleResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Payload, other.Payload)) return false; + if (Username != other.Username) return false; + if (OauthScope != other.OauthScope) return false; + if (ServerId != other.ServerId) return false; + if (GrpclbRouteType != other.GrpclbRouteType) return false; + if (Hostname != other.Hostname) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (payload_ != null) hash ^= Payload.GetHashCode(); + if (Username.Length != 0) hash ^= Username.GetHashCode(); + if (OauthScope.Length != 0) hash ^= OauthScope.GetHashCode(); + if (ServerId.Length != 0) hash ^= ServerId.GetHashCode(); + if (GrpclbRouteType != global::Grpc.Testing.GrpclbRouteType.Unknown) hash ^= GrpclbRouteType.GetHashCode(); + if (Hostname.Length != 0) hash ^= Hostname.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (payload_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Payload); + } + if (Username.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Username); + } + if (OauthScope.Length != 0) { + output.WriteRawTag(26); + output.WriteString(OauthScope); + } + if (ServerId.Length != 0) { + output.WriteRawTag(34); + output.WriteString(ServerId); + } + if (GrpclbRouteType != global::Grpc.Testing.GrpclbRouteType.Unknown) { + output.WriteRawTag(40); + output.WriteEnum((int) GrpclbRouteType); + } + if (Hostname.Length != 0) { + output.WriteRawTag(50); + output.WriteString(Hostname); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (payload_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Payload); + } + if (Username.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Username); + } + if (OauthScope.Length != 0) { + output.WriteRawTag(26); + output.WriteString(OauthScope); + } + if (ServerId.Length != 0) { + output.WriteRawTag(34); + output.WriteString(ServerId); + } + if (GrpclbRouteType != global::Grpc.Testing.GrpclbRouteType.Unknown) { + output.WriteRawTag(40); + output.WriteEnum((int) GrpclbRouteType); + } + if (Hostname.Length != 0) { + output.WriteRawTag(50); + output.WriteString(Hostname); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (payload_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); + } + if (Username.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Username); + } + if (OauthScope.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(OauthScope); + } + if (ServerId.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ServerId); + } + if (GrpclbRouteType != global::Grpc.Testing.GrpclbRouteType.Unknown) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) GrpclbRouteType); + } + if (Hostname.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Hostname); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(SimpleResponse other) { + if (other == null) { + return; + } + if (other.payload_ != null) { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + Payload.MergeFrom(other.Payload); + } + if (other.Username.Length != 0) { + Username = other.Username; + } + if (other.OauthScope.Length != 0) { + OauthScope = other.OauthScope; + } + if (other.ServerId.Length != 0) { + ServerId = other.ServerId; + } + if (other.GrpclbRouteType != global::Grpc.Testing.GrpclbRouteType.Unknown) { + GrpclbRouteType = other.GrpclbRouteType; + } + if (other.Hostname.Length != 0) { + Hostname = other.Hostname; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + input.ReadMessage(Payload); + break; + } + case 18: { + Username = input.ReadString(); + break; + } + case 26: { + OauthScope = input.ReadString(); + break; + } + case 34: { + ServerId = input.ReadString(); + break; + } + case 40: { + GrpclbRouteType = (global::Grpc.Testing.GrpclbRouteType) input.ReadEnum(); + break; + } + case 50: { + Hostname = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + input.ReadMessage(Payload); + break; + } + case 18: { + Username = input.ReadString(); + break; + } + case 26: { + OauthScope = input.ReadString(); + break; + } + case 34: { + ServerId = input.ReadString(); + break; + } + case 40: { + GrpclbRouteType = (global::Grpc.Testing.GrpclbRouteType) input.ReadEnum(); + break; + } + case 50: { + Hostname = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// Client-streaming request. + /// + public sealed partial class StreamingInputCallRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StreamingInputCallRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StreamingInputCallRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StreamingInputCallRequest(StreamingInputCallRequest other) : this() { + payload_ = other.payload_ != null ? other.payload_.Clone() : null; + expectCompressed_ = other.expectCompressed_ != null ? other.expectCompressed_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StreamingInputCallRequest Clone() { + return new StreamingInputCallRequest(this); + } + + /// Field number for the "payload" field. + public const int PayloadFieldNumber = 1; + private global::Grpc.Testing.Payload payload_; + /// + /// Optional input payload sent along with the request. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.Payload Payload { + get { return payload_; } + set { + payload_ = value; + } + } + + /// Field number for the "expect_compressed" field. + public const int ExpectCompressedFieldNumber = 2; + private global::Grpc.Testing.BoolValue expectCompressed_; + /// + /// Whether the server should expect this request to be compressed. This field + /// is "nullable" in order to interoperate seamlessly with servers not able to + /// implement the full compression tests by introspecting the call to verify + /// the request's compression status. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.BoolValue ExpectCompressed { + get { return expectCompressed_; } + set { + expectCompressed_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as StreamingInputCallRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(StreamingInputCallRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Payload, other.Payload)) return false; + if (!object.Equals(ExpectCompressed, other.ExpectCompressed)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (payload_ != null) hash ^= Payload.GetHashCode(); + if (expectCompressed_ != null) hash ^= ExpectCompressed.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (payload_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Payload); + } + if (expectCompressed_ != null) { + output.WriteRawTag(18); + output.WriteMessage(ExpectCompressed); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (payload_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Payload); + } + if (expectCompressed_ != null) { + output.WriteRawTag(18); + output.WriteMessage(ExpectCompressed); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (payload_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); + } + if (expectCompressed_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExpectCompressed); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(StreamingInputCallRequest other) { + if (other == null) { + return; + } + if (other.payload_ != null) { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + Payload.MergeFrom(other.Payload); + } + if (other.expectCompressed_ != null) { + if (expectCompressed_ == null) { + ExpectCompressed = new global::Grpc.Testing.BoolValue(); + } + ExpectCompressed.MergeFrom(other.ExpectCompressed); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + input.ReadMessage(Payload); + break; + } + case 18: { + if (expectCompressed_ == null) { + ExpectCompressed = new global::Grpc.Testing.BoolValue(); + } + input.ReadMessage(ExpectCompressed); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + input.ReadMessage(Payload); + break; + } + case 18: { + if (expectCompressed_ == null) { + ExpectCompressed = new global::Grpc.Testing.BoolValue(); + } + input.ReadMessage(ExpectCompressed); + break; + } + } + } + } + #endif + + } + + /// + /// Client-streaming response. + /// + public sealed partial class StreamingInputCallResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StreamingInputCallResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[6]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StreamingInputCallResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StreamingInputCallResponse(StreamingInputCallResponse other) : this() { + aggregatedPayloadSize_ = other.aggregatedPayloadSize_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StreamingInputCallResponse Clone() { + return new StreamingInputCallResponse(this); + } + + /// Field number for the "aggregated_payload_size" field. + public const int AggregatedPayloadSizeFieldNumber = 1; + private int aggregatedPayloadSize_; + /// + /// Aggregated size of payloads received from the client. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int AggregatedPayloadSize { + get { return aggregatedPayloadSize_; } + set { + aggregatedPayloadSize_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as StreamingInputCallResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(StreamingInputCallResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (AggregatedPayloadSize != other.AggregatedPayloadSize) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (AggregatedPayloadSize != 0) hash ^= AggregatedPayloadSize.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (AggregatedPayloadSize != 0) { + output.WriteRawTag(8); + output.WriteInt32(AggregatedPayloadSize); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (AggregatedPayloadSize != 0) { + output.WriteRawTag(8); + output.WriteInt32(AggregatedPayloadSize); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (AggregatedPayloadSize != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(AggregatedPayloadSize); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(StreamingInputCallResponse other) { + if (other == null) { + return; + } + if (other.AggregatedPayloadSize != 0) { + AggregatedPayloadSize = other.AggregatedPayloadSize; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + AggregatedPayloadSize = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + AggregatedPayloadSize = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// Configuration for a particular response. + /// + public sealed partial class ResponseParameters : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ResponseParameters()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[7]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ResponseParameters() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ResponseParameters(ResponseParameters other) : this() { + size_ = other.size_; + intervalUs_ = other.intervalUs_; + compressed_ = other.compressed_ != null ? other.compressed_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ResponseParameters Clone() { + return new ResponseParameters(this); + } + + /// Field number for the "size" field. + public const int SizeFieldNumber = 1; + private int size_; + /// + /// Desired payload sizes in responses from the server. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int Size { + get { return size_; } + set { + size_ = value; + } + } + + /// Field number for the "interval_us" field. + public const int IntervalUsFieldNumber = 2; + private int intervalUs_; + /// + /// Desired interval between consecutive responses in the response stream in + /// microseconds. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int IntervalUs { + get { return intervalUs_; } + set { + intervalUs_ = value; + } + } + + /// Field number for the "compressed" field. + public const int CompressedFieldNumber = 3; + private global::Grpc.Testing.BoolValue compressed_; + /// + /// Whether to request the server to compress the response. This field is + /// "nullable" in order to interoperate seamlessly with clients not able to + /// implement the full compression tests by introspecting the call to verify + /// the response's compression status. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.BoolValue Compressed { + get { return compressed_; } + set { + compressed_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ResponseParameters); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ResponseParameters other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Size != other.Size) return false; + if (IntervalUs != other.IntervalUs) return false; + if (!object.Equals(Compressed, other.Compressed)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Size != 0) hash ^= Size.GetHashCode(); + if (IntervalUs != 0) hash ^= IntervalUs.GetHashCode(); + if (compressed_ != null) hash ^= Compressed.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Size != 0) { + output.WriteRawTag(8); + output.WriteInt32(Size); + } + if (IntervalUs != 0) { + output.WriteRawTag(16); + output.WriteInt32(IntervalUs); + } + if (compressed_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Compressed); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Size != 0) { + output.WriteRawTag(8); + output.WriteInt32(Size); + } + if (IntervalUs != 0) { + output.WriteRawTag(16); + output.WriteInt32(IntervalUs); + } + if (compressed_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Compressed); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Size != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Size); + } + if (IntervalUs != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntervalUs); + } + if (compressed_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Compressed); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ResponseParameters other) { + if (other == null) { + return; + } + if (other.Size != 0) { + Size = other.Size; + } + if (other.IntervalUs != 0) { + IntervalUs = other.IntervalUs; + } + if (other.compressed_ != null) { + if (compressed_ == null) { + Compressed = new global::Grpc.Testing.BoolValue(); + } + Compressed.MergeFrom(other.Compressed); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Size = input.ReadInt32(); + break; + } + case 16: { + IntervalUs = input.ReadInt32(); + break; + } + case 26: { + if (compressed_ == null) { + Compressed = new global::Grpc.Testing.BoolValue(); + } + input.ReadMessage(Compressed); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Size = input.ReadInt32(); + break; + } + case 16: { + IntervalUs = input.ReadInt32(); + break; + } + case 26: { + if (compressed_ == null) { + Compressed = new global::Grpc.Testing.BoolValue(); + } + input.ReadMessage(Compressed); + break; + } + } + } + } + #endif + + } + + /// + /// Server-streaming request. + /// + public sealed partial class StreamingOutputCallRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StreamingOutputCallRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[8]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StreamingOutputCallRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StreamingOutputCallRequest(StreamingOutputCallRequest other) : this() { + responseType_ = other.responseType_; + responseParameters_ = other.responseParameters_.Clone(); + payload_ = other.payload_ != null ? other.payload_.Clone() : null; + responseStatus_ = other.responseStatus_ != null ? other.responseStatus_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StreamingOutputCallRequest Clone() { + return new StreamingOutputCallRequest(this); + } + + /// Field number for the "response_type" field. + public const int ResponseTypeFieldNumber = 1; + private global::Grpc.Testing.PayloadType responseType_ = global::Grpc.Testing.PayloadType.Compressable; + /// + /// Desired payload type in the response from the server. + /// If response_type is RANDOM, the payload from each response in the stream + /// might be of different types. This is to simulate a mixed type of payload + /// stream. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.PayloadType ResponseType { + get { return responseType_; } + set { + responseType_ = value; + } + } + + /// Field number for the "response_parameters" field. + public const int ResponseParametersFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_responseParameters_codec + = pb::FieldCodec.ForMessage(18, global::Grpc.Testing.ResponseParameters.Parser); + private readonly pbc::RepeatedField responseParameters_ = new pbc::RepeatedField(); + /// + /// Configuration for each expected response message. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField ResponseParameters { + get { return responseParameters_; } + } + + /// Field number for the "payload" field. + public const int PayloadFieldNumber = 3; + private global::Grpc.Testing.Payload payload_; + /// + /// Optional input payload sent along with the request. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.Payload Payload { + get { return payload_; } + set { + payload_ = value; + } + } + + /// Field number for the "response_status" field. + public const int ResponseStatusFieldNumber = 7; + private global::Grpc.Testing.EchoStatus responseStatus_; + /// + /// Whether server should return a given status + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.EchoStatus ResponseStatus { + get { return responseStatus_; } + set { + responseStatus_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as StreamingOutputCallRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(StreamingOutputCallRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ResponseType != other.ResponseType) return false; + if(!responseParameters_.Equals(other.responseParameters_)) return false; + if (!object.Equals(Payload, other.Payload)) return false; + if (!object.Equals(ResponseStatus, other.ResponseStatus)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (ResponseType != global::Grpc.Testing.PayloadType.Compressable) hash ^= ResponseType.GetHashCode(); + hash ^= responseParameters_.GetHashCode(); + if (payload_ != null) hash ^= Payload.GetHashCode(); + if (responseStatus_ != null) hash ^= ResponseStatus.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (ResponseType != global::Grpc.Testing.PayloadType.Compressable) { + output.WriteRawTag(8); + output.WriteEnum((int) ResponseType); + } + responseParameters_.WriteTo(output, _repeated_responseParameters_codec); + if (payload_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Payload); + } + if (responseStatus_ != null) { + output.WriteRawTag(58); + output.WriteMessage(ResponseStatus); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (ResponseType != global::Grpc.Testing.PayloadType.Compressable) { + output.WriteRawTag(8); + output.WriteEnum((int) ResponseType); + } + responseParameters_.WriteTo(ref output, _repeated_responseParameters_codec); + if (payload_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Payload); + } + if (responseStatus_ != null) { + output.WriteRawTag(58); + output.WriteMessage(ResponseStatus); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (ResponseType != global::Grpc.Testing.PayloadType.Compressable) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseType); + } + size += responseParameters_.CalculateSize(_repeated_responseParameters_codec); + if (payload_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); + } + if (responseStatus_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ResponseStatus); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(StreamingOutputCallRequest other) { + if (other == null) { + return; + } + if (other.ResponseType != global::Grpc.Testing.PayloadType.Compressable) { + ResponseType = other.ResponseType; + } + responseParameters_.Add(other.responseParameters_); + if (other.payload_ != null) { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + Payload.MergeFrom(other.Payload); + } + if (other.responseStatus_ != null) { + if (responseStatus_ == null) { + ResponseStatus = new global::Grpc.Testing.EchoStatus(); + } + ResponseStatus.MergeFrom(other.ResponseStatus); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + ResponseType = (global::Grpc.Testing.PayloadType) input.ReadEnum(); + break; + } + case 18: { + responseParameters_.AddEntriesFrom(input, _repeated_responseParameters_codec); + break; + } + case 26: { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + input.ReadMessage(Payload); + break; + } + case 58: { + if (responseStatus_ == null) { + ResponseStatus = new global::Grpc.Testing.EchoStatus(); + } + input.ReadMessage(ResponseStatus); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + ResponseType = (global::Grpc.Testing.PayloadType) input.ReadEnum(); + break; + } + case 18: { + responseParameters_.AddEntriesFrom(ref input, _repeated_responseParameters_codec); + break; + } + case 26: { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + input.ReadMessage(Payload); + break; + } + case 58: { + if (responseStatus_ == null) { + ResponseStatus = new global::Grpc.Testing.EchoStatus(); + } + input.ReadMessage(ResponseStatus); + break; + } + } + } + } + #endif + + } + + /// + /// Server-streaming response, as configured by the request and parameters. + /// + public sealed partial class StreamingOutputCallResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StreamingOutputCallResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[9]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StreamingOutputCallResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StreamingOutputCallResponse(StreamingOutputCallResponse other) : this() { + payload_ = other.payload_ != null ? other.payload_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public StreamingOutputCallResponse Clone() { + return new StreamingOutputCallResponse(this); + } + + /// Field number for the "payload" field. + public const int PayloadFieldNumber = 1; + private global::Grpc.Testing.Payload payload_; + /// + /// Payload to increase response size. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.Payload Payload { + get { return payload_; } + set { + payload_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as StreamingOutputCallResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(StreamingOutputCallResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Payload, other.Payload)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (payload_ != null) hash ^= Payload.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (payload_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Payload); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (payload_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Payload); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (payload_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(StreamingOutputCallResponse other) { + if (other == null) { + return; + } + if (other.payload_ != null) { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + Payload.MergeFrom(other.Payload); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + input.ReadMessage(Payload); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (payload_ == null) { + Payload = new global::Grpc.Testing.Payload(); + } + input.ReadMessage(Payload); + break; + } + } + } + } + #endif + + } + + /// + /// For reconnect interop test only. + /// Client tells server what reconnection parameters it used. + /// + public sealed partial class ReconnectParams : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ReconnectParams()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[10]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ReconnectParams() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ReconnectParams(ReconnectParams other) : this() { + maxReconnectBackoffMs_ = other.maxReconnectBackoffMs_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ReconnectParams Clone() { + return new ReconnectParams(this); + } + + /// Field number for the "max_reconnect_backoff_ms" field. + public const int MaxReconnectBackoffMsFieldNumber = 1; + private int maxReconnectBackoffMs_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int MaxReconnectBackoffMs { + get { return maxReconnectBackoffMs_; } + set { + maxReconnectBackoffMs_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ReconnectParams); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ReconnectParams other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (MaxReconnectBackoffMs != other.MaxReconnectBackoffMs) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (MaxReconnectBackoffMs != 0) hash ^= MaxReconnectBackoffMs.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (MaxReconnectBackoffMs != 0) { + output.WriteRawTag(8); + output.WriteInt32(MaxReconnectBackoffMs); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (MaxReconnectBackoffMs != 0) { + output.WriteRawTag(8); + output.WriteInt32(MaxReconnectBackoffMs); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (MaxReconnectBackoffMs != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(MaxReconnectBackoffMs); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ReconnectParams other) { + if (other == null) { + return; + } + if (other.MaxReconnectBackoffMs != 0) { + MaxReconnectBackoffMs = other.MaxReconnectBackoffMs; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + MaxReconnectBackoffMs = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + MaxReconnectBackoffMs = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// For reconnect interop test only. + /// Server tells client whether its reconnects are following the spec and the + /// reconnect backoffs it saw. + /// + public sealed partial class ReconnectInfo : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ReconnectInfo()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[11]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ReconnectInfo() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ReconnectInfo(ReconnectInfo other) : this() { + passed_ = other.passed_; + backoffMs_ = other.backoffMs_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ReconnectInfo Clone() { + return new ReconnectInfo(this); + } + + /// Field number for the "passed" field. + public const int PassedFieldNumber = 1; + private bool passed_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Passed { + get { return passed_; } + set { + passed_ = value; + } + } + + /// Field number for the "backoff_ms" field. + public const int BackoffMsFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_backoffMs_codec + = pb::FieldCodec.ForInt32(18); + private readonly pbc::RepeatedField backoffMs_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField BackoffMs { + get { return backoffMs_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ReconnectInfo); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ReconnectInfo other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Passed != other.Passed) return false; + if(!backoffMs_.Equals(other.backoffMs_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Passed != false) hash ^= Passed.GetHashCode(); + hash ^= backoffMs_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Passed != false) { + output.WriteRawTag(8); + output.WriteBool(Passed); + } + backoffMs_.WriteTo(output, _repeated_backoffMs_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Passed != false) { + output.WriteRawTag(8); + output.WriteBool(Passed); + } + backoffMs_.WriteTo(ref output, _repeated_backoffMs_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Passed != false) { + size += 1 + 1; + } + size += backoffMs_.CalculateSize(_repeated_backoffMs_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ReconnectInfo other) { + if (other == null) { + return; + } + if (other.Passed != false) { + Passed = other.Passed; + } + backoffMs_.Add(other.backoffMs_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Passed = input.ReadBool(); + break; + } + case 18: + case 16: { + backoffMs_.AddEntriesFrom(input, _repeated_backoffMs_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Passed = input.ReadBool(); + break; + } + case 18: + case 16: { + backoffMs_.AddEntriesFrom(ref input, _repeated_backoffMs_codec); + break; + } + } + } + } + #endif + + } + + public sealed partial class LoadBalancerStatsRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new LoadBalancerStatsRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[12]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadBalancerStatsRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadBalancerStatsRequest(LoadBalancerStatsRequest other) : this() { + numRpcs_ = other.numRpcs_; + timeoutSec_ = other.timeoutSec_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadBalancerStatsRequest Clone() { + return new LoadBalancerStatsRequest(this); + } + + /// Field number for the "num_rpcs" field. + public const int NumRpcsFieldNumber = 1; + private int numRpcs_; + /// + /// Request stats for the next num_rpcs sent by client. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int NumRpcs { + get { return numRpcs_; } + set { + numRpcs_ = value; + } + } + + /// Field number for the "timeout_sec" field. + public const int TimeoutSecFieldNumber = 2; + private int timeoutSec_; + /// + /// If num_rpcs have not completed within timeout_sec, return partial results. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int TimeoutSec { + get { return timeoutSec_; } + set { + timeoutSec_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as LoadBalancerStatsRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(LoadBalancerStatsRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (NumRpcs != other.NumRpcs) return false; + if (TimeoutSec != other.TimeoutSec) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (NumRpcs != 0) hash ^= NumRpcs.GetHashCode(); + if (TimeoutSec != 0) hash ^= TimeoutSec.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (NumRpcs != 0) { + output.WriteRawTag(8); + output.WriteInt32(NumRpcs); + } + if (TimeoutSec != 0) { + output.WriteRawTag(16); + output.WriteInt32(TimeoutSec); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (NumRpcs != 0) { + output.WriteRawTag(8); + output.WriteInt32(NumRpcs); + } + if (TimeoutSec != 0) { + output.WriteRawTag(16); + output.WriteInt32(TimeoutSec); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (NumRpcs != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(NumRpcs); + } + if (TimeoutSec != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(TimeoutSec); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(LoadBalancerStatsRequest other) { + if (other == null) { + return; + } + if (other.NumRpcs != 0) { + NumRpcs = other.NumRpcs; + } + if (other.TimeoutSec != 0) { + TimeoutSec = other.TimeoutSec; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + NumRpcs = input.ReadInt32(); + break; + } + case 16: { + TimeoutSec = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + NumRpcs = input.ReadInt32(); + break; + } + case 16: { + TimeoutSec = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class LoadBalancerStatsResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new LoadBalancerStatsResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[13]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadBalancerStatsResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadBalancerStatsResponse(LoadBalancerStatsResponse other) : this() { + rpcsByPeer_ = other.rpcsByPeer_.Clone(); + numFailures_ = other.numFailures_; + rpcsByMethod_ = other.rpcsByMethod_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadBalancerStatsResponse Clone() { + return new LoadBalancerStatsResponse(this); + } + + /// Field number for the "rpcs_by_peer" field. + public const int RpcsByPeerFieldNumber = 1; + private static readonly pbc::MapField.Codec _map_rpcsByPeer_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForInt32(16, 0), 10); + private readonly pbc::MapField rpcsByPeer_ = new pbc::MapField(); + /// + /// The number of completed RPCs for each peer. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::MapField RpcsByPeer { + get { return rpcsByPeer_; } + } + + /// Field number for the "num_failures" field. + public const int NumFailuresFieldNumber = 2; + private int numFailures_; + /// + /// The number of RPCs that failed to record a remote peer. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int NumFailures { + get { return numFailures_; } + set { + numFailures_ = value; + } + } + + /// Field number for the "rpcs_by_method" field. + public const int RpcsByMethodFieldNumber = 3; + private static readonly pbc::MapField.Codec _map_rpcsByMethod_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForMessage(18, global::Grpc.Testing.LoadBalancerStatsResponse.Types.RpcsByPeer.Parser), 26); + private readonly pbc::MapField rpcsByMethod_ = new pbc::MapField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::MapField RpcsByMethod { + get { return rpcsByMethod_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as LoadBalancerStatsResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(LoadBalancerStatsResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!RpcsByPeer.Equals(other.RpcsByPeer)) return false; + if (NumFailures != other.NumFailures) return false; + if (!RpcsByMethod.Equals(other.RpcsByMethod)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + hash ^= RpcsByPeer.GetHashCode(); + if (NumFailures != 0) hash ^= NumFailures.GetHashCode(); + hash ^= RpcsByMethod.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + rpcsByPeer_.WriteTo(output, _map_rpcsByPeer_codec); + if (NumFailures != 0) { + output.WriteRawTag(16); + output.WriteInt32(NumFailures); + } + rpcsByMethod_.WriteTo(output, _map_rpcsByMethod_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + rpcsByPeer_.WriteTo(ref output, _map_rpcsByPeer_codec); + if (NumFailures != 0) { + output.WriteRawTag(16); + output.WriteInt32(NumFailures); + } + rpcsByMethod_.WriteTo(ref output, _map_rpcsByMethod_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + size += rpcsByPeer_.CalculateSize(_map_rpcsByPeer_codec); + if (NumFailures != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(NumFailures); + } + size += rpcsByMethod_.CalculateSize(_map_rpcsByMethod_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(LoadBalancerStatsResponse other) { + if (other == null) { + return; + } + rpcsByPeer_.Add(other.rpcsByPeer_); + if (other.NumFailures != 0) { + NumFailures = other.NumFailures; + } + rpcsByMethod_.Add(other.rpcsByMethod_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + rpcsByPeer_.AddEntriesFrom(input, _map_rpcsByPeer_codec); + break; + } + case 16: { + NumFailures = input.ReadInt32(); + break; + } + case 26: { + rpcsByMethod_.AddEntriesFrom(input, _map_rpcsByMethod_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + rpcsByPeer_.AddEntriesFrom(ref input, _map_rpcsByPeer_codec); + break; + } + case 16: { + NumFailures = input.ReadInt32(); + break; + } + case 26: { + rpcsByMethod_.AddEntriesFrom(ref input, _map_rpcsByMethod_codec); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the LoadBalancerStatsResponse message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static partial class Types { + public sealed partial class RpcsByPeer : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RpcsByPeer()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.LoadBalancerStatsResponse.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RpcsByPeer() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RpcsByPeer(RpcsByPeer other) : this() { + rpcsByPeer_ = other.rpcsByPeer_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RpcsByPeer Clone() { + return new RpcsByPeer(this); + } + + /// Field number for the "rpcs_by_peer" field. + public const int RpcsByPeer_FieldNumber = 1; + private static readonly pbc::MapField.Codec _map_rpcsByPeer_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForInt32(16, 0), 10); + private readonly pbc::MapField rpcsByPeer_ = new pbc::MapField(); + /// + /// The number of completed RPCs for each peer. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::MapField RpcsByPeer_ { + get { return rpcsByPeer_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as RpcsByPeer); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(RpcsByPeer other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!RpcsByPeer_.Equals(other.RpcsByPeer_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + hash ^= RpcsByPeer_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + rpcsByPeer_.WriteTo(output, _map_rpcsByPeer_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + rpcsByPeer_.WriteTo(ref output, _map_rpcsByPeer_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + size += rpcsByPeer_.CalculateSize(_map_rpcsByPeer_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(RpcsByPeer other) { + if (other == null) { + return; + } + rpcsByPeer_.Add(other.rpcsByPeer_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + rpcsByPeer_.AddEntriesFrom(input, _map_rpcsByPeer_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + rpcsByPeer_.AddEntriesFrom(ref input, _map_rpcsByPeer_codec); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + /// + /// Request for retrieving a test client's accumulated stats. + /// + public sealed partial class LoadBalancerAccumulatedStatsRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new LoadBalancerAccumulatedStatsRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[14]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadBalancerAccumulatedStatsRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadBalancerAccumulatedStatsRequest(LoadBalancerAccumulatedStatsRequest other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadBalancerAccumulatedStatsRequest Clone() { + return new LoadBalancerAccumulatedStatsRequest(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as LoadBalancerAccumulatedStatsRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(LoadBalancerAccumulatedStatsRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(LoadBalancerAccumulatedStatsRequest other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + } + } + } + #endif + + } + + /// + /// Accumulated stats for RPCs sent by a test client. + /// + public sealed partial class LoadBalancerAccumulatedStatsResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new LoadBalancerAccumulatedStatsResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[15]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadBalancerAccumulatedStatsResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadBalancerAccumulatedStatsResponse(LoadBalancerAccumulatedStatsResponse other) : this() { + numRpcsStartedByMethod_ = other.numRpcsStartedByMethod_.Clone(); + numRpcsSucceededByMethod_ = other.numRpcsSucceededByMethod_.Clone(); + numRpcsFailedByMethod_ = other.numRpcsFailedByMethod_.Clone(); + statsPerMethod_ = other.statsPerMethod_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public LoadBalancerAccumulatedStatsResponse Clone() { + return new LoadBalancerAccumulatedStatsResponse(this); + } + + /// Field number for the "num_rpcs_started_by_method" field. + public const int NumRpcsStartedByMethodFieldNumber = 1; + private static readonly pbc::MapField.Codec _map_numRpcsStartedByMethod_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForInt32(16, 0), 10); + private readonly pbc::MapField numRpcsStartedByMethod_ = new pbc::MapField(); + /// + /// The total number of RPCs have ever issued for each type. + /// Deprecated: use stats_per_method.rpcs_started instead. + /// + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::MapField NumRpcsStartedByMethod { + get { return numRpcsStartedByMethod_; } + } + + /// Field number for the "num_rpcs_succeeded_by_method" field. + public const int NumRpcsSucceededByMethodFieldNumber = 2; + private static readonly pbc::MapField.Codec _map_numRpcsSucceededByMethod_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForInt32(16, 0), 18); + private readonly pbc::MapField numRpcsSucceededByMethod_ = new pbc::MapField(); + /// + /// The total number of RPCs have ever completed successfully for each type. + /// Deprecated: use stats_per_method.result instead. + /// + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::MapField NumRpcsSucceededByMethod { + get { return numRpcsSucceededByMethod_; } + } + + /// Field number for the "num_rpcs_failed_by_method" field. + public const int NumRpcsFailedByMethodFieldNumber = 3; + private static readonly pbc::MapField.Codec _map_numRpcsFailedByMethod_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForInt32(16, 0), 26); + private readonly pbc::MapField numRpcsFailedByMethod_ = new pbc::MapField(); + /// + /// The total number of RPCs have ever failed for each type. + /// Deprecated: use stats_per_method.result instead. + /// + [global::System.ObsoleteAttribute] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::MapField NumRpcsFailedByMethod { + get { return numRpcsFailedByMethod_; } + } + + /// Field number for the "stats_per_method" field. + public const int StatsPerMethodFieldNumber = 4; + private static readonly pbc::MapField.Codec _map_statsPerMethod_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForString(10, ""), pb::FieldCodec.ForMessage(18, global::Grpc.Testing.LoadBalancerAccumulatedStatsResponse.Types.MethodStats.Parser), 34); + private readonly pbc::MapField statsPerMethod_ = new pbc::MapField(); + /// + /// Per-method RPC statistics. The key is the RpcType in string form; e.g. + /// 'EMPTY_CALL' or 'UNARY_CALL' + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::MapField StatsPerMethod { + get { return statsPerMethod_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as LoadBalancerAccumulatedStatsResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(LoadBalancerAccumulatedStatsResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!NumRpcsStartedByMethod.Equals(other.NumRpcsStartedByMethod)) return false; + if (!NumRpcsSucceededByMethod.Equals(other.NumRpcsSucceededByMethod)) return false; + if (!NumRpcsFailedByMethod.Equals(other.NumRpcsFailedByMethod)) return false; + if (!StatsPerMethod.Equals(other.StatsPerMethod)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + hash ^= NumRpcsStartedByMethod.GetHashCode(); + hash ^= NumRpcsSucceededByMethod.GetHashCode(); + hash ^= NumRpcsFailedByMethod.GetHashCode(); + hash ^= StatsPerMethod.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + numRpcsStartedByMethod_.WriteTo(output, _map_numRpcsStartedByMethod_codec); + numRpcsSucceededByMethod_.WriteTo(output, _map_numRpcsSucceededByMethod_codec); + numRpcsFailedByMethod_.WriteTo(output, _map_numRpcsFailedByMethod_codec); + statsPerMethod_.WriteTo(output, _map_statsPerMethod_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + numRpcsStartedByMethod_.WriteTo(ref output, _map_numRpcsStartedByMethod_codec); + numRpcsSucceededByMethod_.WriteTo(ref output, _map_numRpcsSucceededByMethod_codec); + numRpcsFailedByMethod_.WriteTo(ref output, _map_numRpcsFailedByMethod_codec); + statsPerMethod_.WriteTo(ref output, _map_statsPerMethod_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + size += numRpcsStartedByMethod_.CalculateSize(_map_numRpcsStartedByMethod_codec); + size += numRpcsSucceededByMethod_.CalculateSize(_map_numRpcsSucceededByMethod_codec); + size += numRpcsFailedByMethod_.CalculateSize(_map_numRpcsFailedByMethod_codec); + size += statsPerMethod_.CalculateSize(_map_statsPerMethod_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(LoadBalancerAccumulatedStatsResponse other) { + if (other == null) { + return; + } + numRpcsStartedByMethod_.Add(other.numRpcsStartedByMethod_); + numRpcsSucceededByMethod_.Add(other.numRpcsSucceededByMethod_); + numRpcsFailedByMethod_.Add(other.numRpcsFailedByMethod_); + statsPerMethod_.Add(other.statsPerMethod_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + numRpcsStartedByMethod_.AddEntriesFrom(input, _map_numRpcsStartedByMethod_codec); + break; + } + case 18: { + numRpcsSucceededByMethod_.AddEntriesFrom(input, _map_numRpcsSucceededByMethod_codec); + break; + } + case 26: { + numRpcsFailedByMethod_.AddEntriesFrom(input, _map_numRpcsFailedByMethod_codec); + break; + } + case 34: { + statsPerMethod_.AddEntriesFrom(input, _map_statsPerMethod_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + numRpcsStartedByMethod_.AddEntriesFrom(ref input, _map_numRpcsStartedByMethod_codec); + break; + } + case 18: { + numRpcsSucceededByMethod_.AddEntriesFrom(ref input, _map_numRpcsSucceededByMethod_codec); + break; + } + case 26: { + numRpcsFailedByMethod_.AddEntriesFrom(ref input, _map_numRpcsFailedByMethod_codec); + break; + } + case 34: { + statsPerMethod_.AddEntriesFrom(ref input, _map_statsPerMethod_codec); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the LoadBalancerAccumulatedStatsResponse message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static partial class Types { + public sealed partial class MethodStats : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MethodStats()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.LoadBalancerAccumulatedStatsResponse.Descriptor.NestedTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public MethodStats() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public MethodStats(MethodStats other) : this() { + rpcsStarted_ = other.rpcsStarted_; + result_ = other.result_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public MethodStats Clone() { + return new MethodStats(this); + } + + /// Field number for the "rpcs_started" field. + public const int RpcsStartedFieldNumber = 1; + private int rpcsStarted_; + /// + /// The number of RPCs that were started for this method. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int RpcsStarted { + get { return rpcsStarted_; } + set { + rpcsStarted_ = value; + } + } + + /// Field number for the "result" field. + public const int ResultFieldNumber = 2; + private static readonly pbc::MapField.Codec _map_result_codec + = new pbc::MapField.Codec(pb::FieldCodec.ForInt32(8, 0), pb::FieldCodec.ForInt32(16, 0), 18); + private readonly pbc::MapField result_ = new pbc::MapField(); + /// + /// The number of RPCs that completed with each status for this method. The + /// key is the integral value of a google.rpc.Code; the value is the count. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::MapField Result { + get { return result_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as MethodStats); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(MethodStats other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (RpcsStarted != other.RpcsStarted) return false; + if (!Result.Equals(other.Result)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (RpcsStarted != 0) hash ^= RpcsStarted.GetHashCode(); + hash ^= Result.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (RpcsStarted != 0) { + output.WriteRawTag(8); + output.WriteInt32(RpcsStarted); + } + result_.WriteTo(output, _map_result_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (RpcsStarted != 0) { + output.WriteRawTag(8); + output.WriteInt32(RpcsStarted); + } + result_.WriteTo(ref output, _map_result_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (RpcsStarted != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(RpcsStarted); + } + size += result_.CalculateSize(_map_result_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(MethodStats other) { + if (other == null) { + return; + } + if (other.RpcsStarted != 0) { + RpcsStarted = other.RpcsStarted; + } + result_.Add(other.result_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + RpcsStarted = input.ReadInt32(); + break; + } + case 18: { + result_.AddEntriesFrom(input, _map_result_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + RpcsStarted = input.ReadInt32(); + break; + } + case 18: { + result_.AddEntriesFrom(ref input, _map_result_codec); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + /// + /// Configurations for a test client. + /// + public sealed partial class ClientConfigureRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ClientConfigureRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[16]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientConfigureRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientConfigureRequest(ClientConfigureRequest other) : this() { + types_ = other.types_.Clone(); + metadata_ = other.metadata_.Clone(); + timeoutSec_ = other.timeoutSec_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientConfigureRequest Clone() { + return new ClientConfigureRequest(this); + } + + /// Field number for the "types" field. + public const int Types_FieldNumber = 1; + private static readonly pb::FieldCodec _repeated_types_codec + = pb::FieldCodec.ForEnum(10, x => (int) x, x => (global::Grpc.Testing.ClientConfigureRequest.Types.RpcType) x); + private readonly pbc::RepeatedField types_ = new pbc::RepeatedField(); + /// + /// The types of RPCs the client sends. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Types_ { + get { return types_; } + } + + /// Field number for the "metadata" field. + public const int MetadataFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_metadata_codec + = pb::FieldCodec.ForMessage(18, global::Grpc.Testing.ClientConfigureRequest.Types.Metadata.Parser); + private readonly pbc::RepeatedField metadata_ = new pbc::RepeatedField(); + /// + /// The collection of custom metadata to be attached to RPCs sent by the client. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Metadata { + get { return metadata_; } + } + + /// Field number for the "timeout_sec" field. + public const int TimeoutSecFieldNumber = 3; + private int timeoutSec_; + /// + /// The deadline to use, in seconds, for all RPCs. If unset or zero, the + /// client will use the default from the command-line. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int TimeoutSec { + get { return timeoutSec_; } + set { + timeoutSec_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ClientConfigureRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ClientConfigureRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!types_.Equals(other.types_)) return false; + if(!metadata_.Equals(other.metadata_)) return false; + if (TimeoutSec != other.TimeoutSec) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + hash ^= types_.GetHashCode(); + hash ^= metadata_.GetHashCode(); + if (TimeoutSec != 0) hash ^= TimeoutSec.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + types_.WriteTo(output, _repeated_types_codec); + metadata_.WriteTo(output, _repeated_metadata_codec); + if (TimeoutSec != 0) { + output.WriteRawTag(24); + output.WriteInt32(TimeoutSec); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + types_.WriteTo(ref output, _repeated_types_codec); + metadata_.WriteTo(ref output, _repeated_metadata_codec); + if (TimeoutSec != 0) { + output.WriteRawTag(24); + output.WriteInt32(TimeoutSec); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + size += types_.CalculateSize(_repeated_types_codec); + size += metadata_.CalculateSize(_repeated_metadata_codec); + if (TimeoutSec != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(TimeoutSec); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ClientConfigureRequest other) { + if (other == null) { + return; + } + types_.Add(other.types_); + metadata_.Add(other.metadata_); + if (other.TimeoutSec != 0) { + TimeoutSec = other.TimeoutSec; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: + case 8: { + types_.AddEntriesFrom(input, _repeated_types_codec); + break; + } + case 18: { + metadata_.AddEntriesFrom(input, _repeated_metadata_codec); + break; + } + case 24: { + TimeoutSec = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: + case 8: { + types_.AddEntriesFrom(ref input, _repeated_types_codec); + break; + } + case 18: { + metadata_.AddEntriesFrom(ref input, _repeated_metadata_codec); + break; + } + case 24: { + TimeoutSec = input.ReadInt32(); + break; + } + } + } + } + #endif + + #region Nested types + /// Container for nested types declared in the ClientConfigureRequest message type. + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static partial class Types { + /// + /// Type of RPCs to send. + /// + public enum RpcType { + [pbr::OriginalName("EMPTY_CALL")] EmptyCall = 0, + [pbr::OriginalName("UNARY_CALL")] UnaryCall = 1, + } + + /// + /// Metadata to be attached for the given type of RPCs. + /// + public sealed partial class Metadata : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Metadata()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.ClientConfigureRequest.Descriptor.NestedTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Metadata() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Metadata(Metadata other) : this() { + type_ = other.type_; + key_ = other.key_; + value_ = other.value_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Metadata Clone() { + return new Metadata(this); + } + + /// Field number for the "type" field. + public const int TypeFieldNumber = 1; + private global::Grpc.Testing.ClientConfigureRequest.Types.RpcType type_ = global::Grpc.Testing.ClientConfigureRequest.Types.RpcType.EmptyCall; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ClientConfigureRequest.Types.RpcType Type { + get { return type_; } + set { + type_ = value; + } + } + + /// Field number for the "key" field. + public const int KeyFieldNumber = 2; + private string key_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Key { + get { return key_; } + set { + key_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "value" field. + public const int ValueFieldNumber = 3; + private string value_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Value { + get { return value_; } + set { + value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Metadata); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Metadata other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Type != other.Type) return false; + if (Key != other.Key) return false; + if (Value != other.Value) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Type != global::Grpc.Testing.ClientConfigureRequest.Types.RpcType.EmptyCall) hash ^= Type.GetHashCode(); + if (Key.Length != 0) hash ^= Key.GetHashCode(); + if (Value.Length != 0) hash ^= Value.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Type != global::Grpc.Testing.ClientConfigureRequest.Types.RpcType.EmptyCall) { + output.WriteRawTag(8); + output.WriteEnum((int) Type); + } + if (Key.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Key); + } + if (Value.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Type != global::Grpc.Testing.ClientConfigureRequest.Types.RpcType.EmptyCall) { + output.WriteRawTag(8); + output.WriteEnum((int) Type); + } + if (Key.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Key); + } + if (Value.Length != 0) { + output.WriteRawTag(26); + output.WriteString(Value); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Type != global::Grpc.Testing.ClientConfigureRequest.Types.RpcType.EmptyCall) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); + } + if (Key.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Key); + } + if (Value.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Value); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Metadata other) { + if (other == null) { + return; + } + if (other.Type != global::Grpc.Testing.ClientConfigureRequest.Types.RpcType.EmptyCall) { + Type = other.Type; + } + if (other.Key.Length != 0) { + Key = other.Key; + } + if (other.Value.Length != 0) { + Value = other.Value; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Type = (global::Grpc.Testing.ClientConfigureRequest.Types.RpcType) input.ReadEnum(); + break; + } + case 18: { + Key = input.ReadString(); + break; + } + case 26: { + Value = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Type = (global::Grpc.Testing.ClientConfigureRequest.Types.RpcType) input.ReadEnum(); + break; + } + case 18: { + Key = input.ReadString(); + break; + } + case 26: { + Value = input.ReadString(); + break; + } + } + } + } + #endif + + } + + } + #endregion + + } + + /// + /// Response for updating a test client's configuration. + /// + public sealed partial class ClientConfigureResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ClientConfigureResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MessagesReflection.Descriptor.MessageTypes[17]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientConfigureResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientConfigureResponse(ClientConfigureResponse other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientConfigureResponse Clone() { + return new ClientConfigureResponse(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ClientConfigureResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ClientConfigureResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ClientConfigureResponse other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs new file mode 100644 index 00000000..3b186c82 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs @@ -0,0 +1,269 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Testing; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + public class MetadataCredentialsTest + { + const string Host = "localhost"; + + FakeTestService serviceImpl; + Server server; + Channel channel; + TestService.TestServiceClient client; + List options; + + [SetUp] + public void Init() + { + serviceImpl = new FakeTestService(); + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { TestService.BindService(serviceImpl) }, + Ports = { { Host, ServerPort.PickUnused, TestCredentials.CreateSslServerCredentials() } } + }; + server.Start(); + + options = new List + { + new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride) + }; + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void MetadataCredentials_Channel() + { + serviceImpl.UnaryCallHandler = (req, context) => + { + var authToken = context.RequestHeaders.First((entry) => entry.Key == "authorization").Value; + Assert.AreEqual("SECRET_TOKEN", authToken); + return Task.FromResult(new SimpleResponse()); + }; + + var asyncAuthInterceptor = new AsyncAuthInterceptor(async (context, metadata) => + { + await Task.Delay(100).ConfigureAwait(false); // make sure the operation is asynchronous. + metadata.Add("authorization", "SECRET_TOKEN"); + }); + + var channelCredentials = ChannelCredentials.Create(TestCredentials.CreateSslCredentials(), + CallCredentials.FromInterceptor(asyncAuthInterceptor)); + channel = new Channel(Host, server.Ports.Single().BoundPort, channelCredentials, options); + client = new TestService.TestServiceClient(channel); + + client.UnaryCall(new SimpleRequest { }); + } + + [Test] + public void MetadataCredentials_PerCall() + { + serviceImpl.UnaryCallHandler = (req, context) => + { + var authToken = context.RequestHeaders.First((entry) => entry.Key == "authorization").Value; + Assert.AreEqual("SECRET_TOKEN", authToken); + return Task.FromResult(new SimpleResponse()); + }; + + var asyncAuthInterceptor = new AsyncAuthInterceptor(async (context, metadata) => + { + await Task.Delay(100).ConfigureAwait(false); // make sure the operation is asynchronous. + metadata.Add("authorization", "SECRET_TOKEN"); + }); + + channel = new Channel(Host, server.Ports.Single().BoundPort, TestCredentials.CreateSslCredentials(), options); + client = new TestService.TestServiceClient(channel); + + var callCredentials = CallCredentials.FromInterceptor(asyncAuthInterceptor); + client.UnaryCall(new SimpleRequest { }, new CallOptions(credentials: callCredentials)); + } + + [Test] + public void MetadataCredentials_BothChannelAndPerCall() + { + serviceImpl.UnaryCallHandler = (req, context) => + { + var firstAuth = context.RequestHeaders.First((entry) => entry.Key == "first_authorization").Value; + Assert.AreEqual("FIRST_SECRET_TOKEN", firstAuth); + var secondAuth = context.RequestHeaders.First((entry) => entry.Key == "second_authorization").Value; + Assert.AreEqual("SECOND_SECRET_TOKEN", secondAuth); + // both values of "duplicate_authorization" are sent + Assert.AreEqual("value1", context.RequestHeaders.First((entry) => entry.Key == "duplicate_authorization").Value); + Assert.AreEqual("value2", context.RequestHeaders.Last((entry) => entry.Key == "duplicate_authorization").Value); + return Task.FromResult(new SimpleResponse()); + }; + + var channelCallCredentials = CallCredentials.FromInterceptor(new AsyncAuthInterceptor((context, metadata) => { + metadata.Add("first_authorization", "FIRST_SECRET_TOKEN"); + metadata.Add("duplicate_authorization", "value1"); + return TaskUtils.CompletedTask; + })); + var perCallCredentials = CallCredentials.FromInterceptor(new AsyncAuthInterceptor((context, metadata) => { + metadata.Add("second_authorization", "SECOND_SECRET_TOKEN"); + metadata.Add("duplicate_authorization", "value2"); + return TaskUtils.CompletedTask; + })); + + var channelCredentials = ChannelCredentials.Create(TestCredentials.CreateSslCredentials(), channelCallCredentials); + channel = new Channel(Host, server.Ports.Single().BoundPort, channelCredentials, options); + client = new TestService.TestServiceClient(channel); + + client.UnaryCall(new SimpleRequest { }, new CallOptions(credentials: perCallCredentials)); + } + + [Test] + public async Task MetadataCredentials_Composed() + { + serviceImpl.StreamingOutputCallHandler = async (req, responseStream, context) => + { + var firstAuth = context.RequestHeaders.Last((entry) => entry.Key == "first_authorization").Value; + Assert.AreEqual("FIRST_SECRET_TOKEN", firstAuth); + var secondAuth = context.RequestHeaders.First((entry) => entry.Key == "second_authorization").Value; + Assert.AreEqual("SECOND_SECRET_TOKEN", secondAuth); + var thirdAuth = context.RequestHeaders.First((entry) => entry.Key == "third_authorization").Value; + Assert.AreEqual("THIRD_SECRET_TOKEN", thirdAuth); + await responseStream.WriteAsync(new StreamingOutputCallResponse()); + }; + + var first = CallCredentials.FromInterceptor(new AsyncAuthInterceptor((context, metadata) => { + // Attempt to exercise the case where async callback is inlineable/synchronously-runnable. + metadata.Add("first_authorization", "FIRST_SECRET_TOKEN"); + return TaskUtils.CompletedTask; + })); + var second = CallCredentials.FromInterceptor(new AsyncAuthInterceptor((context, metadata) => { + metadata.Add("second_authorization", "SECOND_SECRET_TOKEN"); + return TaskUtils.CompletedTask; + })); + var third = CallCredentials.FromInterceptor(new AsyncAuthInterceptor((context, metadata) => { + metadata.Add("third_authorization", "THIRD_SECRET_TOKEN"); + return TaskUtils.CompletedTask; + })); + var channelCredentials = ChannelCredentials.Create(TestCredentials.CreateSslCredentials(), + CallCredentials.Compose(first, second, third)); + channel = new Channel(Host, server.Ports.Single().BoundPort, channelCredentials, options); + var client = new TestService.TestServiceClient(channel); + var call = client.StreamingOutputCall(new StreamingOutputCallRequest { }); + Assert.IsTrue(await call.ResponseStream.MoveNext()); + Assert.IsFalse(await call.ResponseStream.MoveNext()); + } + + [Test] + public async Task MetadataCredentials_ComposedPerCall() + { + serviceImpl.StreamingOutputCallHandler = async (req, responseStream, context) => + { + var firstAuth = context.RequestHeaders.Last((entry) => entry.Key == "first_authorization").Value; + Assert.AreEqual("FIRST_SECRET_TOKEN", firstAuth); + var secondAuth = context.RequestHeaders.First((entry) => entry.Key == "second_authorization").Value; + Assert.AreEqual("SECOND_SECRET_TOKEN", secondAuth); + await responseStream.WriteAsync(new StreamingOutputCallResponse()); + }; + + channel = new Channel(Host, server.Ports.Single().BoundPort, TestCredentials.CreateSslCredentials(), options); + var client = new TestService.TestServiceClient(channel); + var first = CallCredentials.FromInterceptor(new AsyncAuthInterceptor((context, metadata) => { + metadata.Add("first_authorization", "FIRST_SECRET_TOKEN"); + return TaskUtils.CompletedTask; + })); + var second = CallCredentials.FromInterceptor(new AsyncAuthInterceptor((context, metadata) => { + metadata.Add("second_authorization", "SECOND_SECRET_TOKEN"); + return TaskUtils.CompletedTask; + })); + var call = client.StreamingOutputCall(new StreamingOutputCallRequest{ }, + new CallOptions(credentials: CallCredentials.Compose(first, second))); + Assert.IsTrue(await call.ResponseStream.MoveNext()); + Assert.IsFalse(await call.ResponseStream.MoveNext()); + } + + [Test] + public void MetadataCredentials_InterceptorLeavesMetadataEmpty() + { + serviceImpl.UnaryCallHandler = (req, context) => + { + var authHeaderCount = context.RequestHeaders.Count((entry) => entry.Key == "authorization"); + Assert.AreEqual(0, authHeaderCount); + return Task.FromResult(new SimpleResponse()); + }; + var channelCredentials = ChannelCredentials.Create(TestCredentials.CreateSslCredentials(), + CallCredentials.FromInterceptor(new AsyncAuthInterceptor((context, metadata) => TaskUtils.CompletedTask))); + channel = new Channel(Host, server.Ports.Single().BoundPort, channelCredentials, options); + client = new TestService.TestServiceClient(channel); + client.UnaryCall(new SimpleRequest { }); + } + + [Test] + public void MetadataCredentials_InterceptorThrows() + { + var authInterceptorExceptionMessage = "Auth interceptor throws"; + var callCredentials = CallCredentials.FromInterceptor(new AsyncAuthInterceptor((context, metadata) => + { + throw new Exception(authInterceptorExceptionMessage); + })); + var channelCredentials = ChannelCredentials.Create(TestCredentials.CreateSslCredentials(), callCredentials); + channel = new Channel(Host, server.Ports.Single().BoundPort, channelCredentials, options); + client = new TestService.TestServiceClient(channel); + + var ex = Assert.Throws(() => client.UnaryCall(new SimpleRequest { })); + Assert.AreEqual(StatusCode.Unavailable, ex.Status.StatusCode); + StringAssert.Contains(authInterceptorExceptionMessage, ex.Status.Detail); + } + + private class FakeTestService : TestService.TestServiceBase + { + public UnaryServerMethod UnaryCallHandler; + + public ServerStreamingServerMethod StreamingOutputCallHandler; + + public override Task UnaryCall(SimpleRequest request, ServerCallContext context) + { + if (UnaryCallHandler != null) + { + return UnaryCallHandler(request, context); + } + return base.UnaryCall(request, context); + } + + public override Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter responseStream, ServerCallContext context) + { + if (StreamingOutputCallHandler != null) + { + return StreamingOutputCallHandler(request, responseStream, context); + } + return base.StreamingOutputCall(request, responseStream, context); + } + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/Metrics.cs b/src/csharp/Grpc.IntegrationTesting/Metrics.cs new file mode 100644 index 00000000..3b622f99 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/Metrics.cs @@ -0,0 +1,735 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/metrics.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Testing { + + /// Holder for reflection information generated from src/proto/grpc/testing/metrics.proto + public static partial class MetricsReflection { + + #region Descriptor + /// File descriptor for src/proto/grpc/testing/metrics.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static MetricsReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CiRzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL21ldHJpY3MucHJvdG8SDGdycGMu", + "dGVzdGluZyJsCg1HYXVnZVJlc3BvbnNlEgwKBG5hbWUYASABKAkSFAoKbG9u", + "Z192YWx1ZRgCIAEoA0gAEhYKDGRvdWJsZV92YWx1ZRgDIAEoAUgAEhYKDHN0", + "cmluZ192YWx1ZRgEIAEoCUgAQgcKBXZhbHVlIhwKDEdhdWdlUmVxdWVzdBIM", + "CgRuYW1lGAEgASgJIg4KDEVtcHR5TWVzc2FnZTKgAQoOTWV0cmljc1NlcnZp", + "Y2USSQoMR2V0QWxsR2F1Z2VzEhouZ3JwYy50ZXN0aW5nLkVtcHR5TWVzc2Fn", + "ZRobLmdycGMudGVzdGluZy5HYXVnZVJlc3BvbnNlMAESQwoIR2V0R2F1Z2US", + "Gi5ncnBjLnRlc3RpbmcuR2F1Z2VSZXF1ZXN0GhsuZ3JwYy50ZXN0aW5nLkdh", + "dWdlUmVzcG9uc2ViBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.GaugeResponse), global::Grpc.Testing.GaugeResponse.Parser, new[]{ "Name", "LongValue", "DoubleValue", "StringValue" }, new[]{ "Value" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.GaugeRequest), global::Grpc.Testing.GaugeRequest.Parser, new[]{ "Name" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.EmptyMessage), global::Grpc.Testing.EmptyMessage.Parser, null, null, null, null, null) + })); + } + #endregion + + } + #region Messages + /// + /// Response message containing the gauge name and value + /// + public sealed partial class GaugeResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new GaugeResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public GaugeResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public GaugeResponse(GaugeResponse other) : this() { + name_ = other.name_; + switch (other.ValueCase) { + case ValueOneofCase.LongValue: + LongValue = other.LongValue; + break; + case ValueOneofCase.DoubleValue: + DoubleValue = other.DoubleValue; + break; + case ValueOneofCase.StringValue: + StringValue = other.StringValue; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public GaugeResponse Clone() { + return new GaugeResponse(this); + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 1; + private string name_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "long_value" field. + public const int LongValueFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long LongValue { + get { return valueCase_ == ValueOneofCase.LongValue ? (long) value_ : 0L; } + set { + value_ = value; + valueCase_ = ValueOneofCase.LongValue; + } + } + + /// Field number for the "double_value" field. + public const int DoubleValueFieldNumber = 3; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double DoubleValue { + get { return valueCase_ == ValueOneofCase.DoubleValue ? (double) value_ : 0D; } + set { + value_ = value; + valueCase_ = ValueOneofCase.DoubleValue; + } + } + + /// Field number for the "string_value" field. + public const int StringValueFieldNumber = 4; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string StringValue { + get { return valueCase_ == ValueOneofCase.StringValue ? (string) value_ : ""; } + set { + value_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + valueCase_ = ValueOneofCase.StringValue; + } + } + + private object value_; + /// Enum of possible cases for the "value" oneof. + public enum ValueOneofCase { + None = 0, + LongValue = 2, + DoubleValue = 3, + StringValue = 4, + } + private ValueOneofCase valueCase_ = ValueOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ValueOneofCase ValueCase { + get { return valueCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearValue() { + valueCase_ = ValueOneofCase.None; + value_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as GaugeResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(GaugeResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Name != other.Name) return false; + if (LongValue != other.LongValue) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleValue, other.DoubleValue)) return false; + if (StringValue != other.StringValue) return false; + if (ValueCase != other.ValueCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (valueCase_ == ValueOneofCase.LongValue) hash ^= LongValue.GetHashCode(); + if (valueCase_ == ValueOneofCase.DoubleValue) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleValue); + if (valueCase_ == ValueOneofCase.StringValue) hash ^= StringValue.GetHashCode(); + hash ^= (int) valueCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (valueCase_ == ValueOneofCase.LongValue) { + output.WriteRawTag(16); + output.WriteInt64(LongValue); + } + if (valueCase_ == ValueOneofCase.DoubleValue) { + output.WriteRawTag(25); + output.WriteDouble(DoubleValue); + } + if (valueCase_ == ValueOneofCase.StringValue) { + output.WriteRawTag(34); + output.WriteString(StringValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (valueCase_ == ValueOneofCase.LongValue) { + output.WriteRawTag(16); + output.WriteInt64(LongValue); + } + if (valueCase_ == ValueOneofCase.DoubleValue) { + output.WriteRawTag(25); + output.WriteDouble(DoubleValue); + } + if (valueCase_ == ValueOneofCase.StringValue) { + output.WriteRawTag(34); + output.WriteString(StringValue); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + if (valueCase_ == ValueOneofCase.LongValue) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(LongValue); + } + if (valueCase_ == ValueOneofCase.DoubleValue) { + size += 1 + 8; + } + if (valueCase_ == ValueOneofCase.StringValue) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(StringValue); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(GaugeResponse other) { + if (other == null) { + return; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + switch (other.ValueCase) { + case ValueOneofCase.LongValue: + LongValue = other.LongValue; + break; + case ValueOneofCase.DoubleValue: + DoubleValue = other.DoubleValue; + break; + case ValueOneofCase.StringValue: + StringValue = other.StringValue; + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 16: { + LongValue = input.ReadInt64(); + break; + } + case 25: { + DoubleValue = input.ReadDouble(); + break; + } + case 34: { + StringValue = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + case 16: { + LongValue = input.ReadInt64(); + break; + } + case 25: { + DoubleValue = input.ReadDouble(); + break; + } + case 34: { + StringValue = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// Request message containing the gauge name + /// + public sealed partial class GaugeRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new GaugeRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public GaugeRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public GaugeRequest(GaugeRequest other) : this() { + name_ = other.name_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public GaugeRequest Clone() { + return new GaugeRequest(this); + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 1; + private string name_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as GaugeRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(GaugeRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Name != other.Name) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(GaugeRequest other) { + if (other == null) { + return; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Name = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + } + } + } + #endif + + } + + public sealed partial class EmptyMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new EmptyMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EmptyMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EmptyMessage(EmptyMessage other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public EmptyMessage Clone() { + return new EmptyMessage(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as EmptyMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(EmptyMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(EmptyMessage other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs new file mode 100644 index 00000000..994546cd --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs @@ -0,0 +1,262 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/metrics.proto +// +// Original file comments: +// Copyright 2015-2016 gRPC authors. +// +// 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. +// +// Contains the definitions for a metrics service and the type of metrics +// exposed by the service. +// +// Currently, 'Gauge' (i.e a metric that represents the measured value of +// something at an instant of time) is the only metric type supported by the +// service. +#pragma warning disable 0414, 1591 +#region Designer generated code + +using grpc = global::Grpc.Core; + +namespace Grpc.Testing { + public static partial class MetricsService + { + static readonly string __ServiceName = "grpc.testing.MetricsService"; + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context) + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (message is global::Google.Protobuf.IBufferMessage) + { + context.SetPayloadLength(message.CalculateSize()); + global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter()); + context.Complete(); + return; + } + #endif + context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static class __Helper_MessageCache + { + public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static T __Helper_DeserializeMessage(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser parser) where T : global::Google.Protobuf.IMessage + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (__Helper_MessageCache.IsBufferMessage) + { + return parser.ParseFrom(context.PayloadAsReadOnlySequence()); + } + #endif + return parser.ParseFrom(context.PayloadAsNewBuffer()); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_EmptyMessage = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.EmptyMessage.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_GaugeResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.GaugeResponse.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_GaugeRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.GaugeRequest.Parser)); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_GetAllGauges = new grpc::Method( + grpc::MethodType.ServerStreaming, + __ServiceName, + "GetAllGauges", + __Marshaller_grpc_testing_EmptyMessage, + __Marshaller_grpc_testing_GaugeResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_GetGauge = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "GetGauge", + __Marshaller_grpc_testing_GaugeRequest, + __Marshaller_grpc_testing_GaugeResponse); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Testing.MetricsReflection.Descriptor.Services[0]; } + } + + /// Base class for server-side implementations of MetricsService + [grpc::BindServiceMethod(typeof(MetricsService), "BindService")] + public abstract partial class MetricsServiceBase + { + /// + /// Returns the values of all the gauges that are currently being maintained by + /// the service + /// + /// The request received from the client. + /// Used for sending responses back to the client. + /// The context of the server-side call handler being invoked. + /// A task indicating completion of the handler. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// Returns the value of one gauge + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task GetGauge(global::Grpc.Testing.GaugeRequest request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for MetricsService + public partial class MetricsServiceClient : grpc::ClientBase + { + /// Creates a new client for MetricsService + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public MetricsServiceClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for MetricsService that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public MetricsServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected MetricsServiceClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected MetricsServiceClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// Returns the values of all the gauges that are currently being maintained by + /// the service + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncServerStreamingCall GetAllGauges(global::Grpc.Testing.EmptyMessage request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return GetAllGauges(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Returns the values of all the gauges that are currently being maintained by + /// the service + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncServerStreamingCall GetAllGauges(global::Grpc.Testing.EmptyMessage request, grpc::CallOptions options) + { + return CallInvoker.AsyncServerStreamingCall(__Method_GetAllGauges, null, options, request); + } + /// + /// Returns the value of one gauge + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return GetGauge(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Returns the value of one gauge + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_GetGauge, null, options, request); + } + /// + /// Returns the value of one gauge + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return GetGaugeAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Returns the value of one gauge + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_GetGauge, null, options, request); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override MetricsServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new MetricsServiceClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static grpc::ServerServiceDefinition BindService(MetricsServiceBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_GetAllGauges, serviceImpl.GetAllGauges) + .AddMethod(__Method_GetGauge, serviceImpl.GetGauge).Build(); + } + + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static void BindService(grpc::ServiceBinderBase serviceBinder, MetricsServiceBase serviceImpl) + { + serviceBinder.AddMethod(__Method_GetAllGauges, serviceImpl == null ? null : new grpc::ServerStreamingServerMethod(serviceImpl.GetAllGauges)); + serviceBinder.AddMethod(__Method_GetGauge, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.GetGauge)); + } + + } +} +#endregion diff --git a/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs b/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs new file mode 100644 index 00000000..41351862 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/NUnitMain.cs @@ -0,0 +1,40 @@ +#region Copyright notice and license + +// Copyright 2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Reflection; +using Grpc.Core; +using Grpc.Core.Logging; +using NUnit.Common; +using NUnitLite; + +namespace Grpc.IntegrationTesting +{ + /// + /// Provides entry point for NUnitLite + /// + public class NUnitMain + { + public static int Main(string[] args) + { + // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. + GrpcEnvironment.SetLogger(new ConsoleLogger()); + return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/Payloads.cs b/src/csharp/Grpc.IntegrationTesting/Payloads.cs new file mode 100644 index 00000000..309e6a68 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/Payloads.cs @@ -0,0 +1,999 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/payloads.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Testing { + + /// Holder for reflection information generated from src/proto/grpc/testing/payloads.proto + public static partial class PayloadsReflection { + + #region Descriptor + /// File descriptor for src/proto/grpc/testing/payloads.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static PayloadsReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CiVzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3BheWxvYWRzLnByb3RvEgxncnBj", + "LnRlc3RpbmciNwoQQnl0ZUJ1ZmZlclBhcmFtcxIQCghyZXFfc2l6ZRgBIAEo", + "BRIRCglyZXNwX3NpemUYAiABKAUiOAoRU2ltcGxlUHJvdG9QYXJhbXMSEAoI", + "cmVxX3NpemUYASABKAUSEQoJcmVzcF9zaXplGAIgASgFIhQKEkNvbXBsZXhQ", + "cm90b1BhcmFtcyLKAQoNUGF5bG9hZENvbmZpZxI4Cg5ieXRlYnVmX3BhcmFt", + "cxgBIAEoCzIeLmdycGMudGVzdGluZy5CeXRlQnVmZmVyUGFyYW1zSAASOAoN", + "c2ltcGxlX3BhcmFtcxgCIAEoCzIfLmdycGMudGVzdGluZy5TaW1wbGVQcm90", + "b1BhcmFtc0gAEjoKDmNvbXBsZXhfcGFyYW1zGAMgASgLMiAuZ3JwYy50ZXN0", + "aW5nLkNvbXBsZXhQcm90b1BhcmFtc0gAQgkKB3BheWxvYWRiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ByteBufferParams), global::Grpc.Testing.ByteBufferParams.Parser, new[]{ "ReqSize", "RespSize" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SimpleProtoParams), global::Grpc.Testing.SimpleProtoParams.Parser, new[]{ "ReqSize", "RespSize" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ComplexProtoParams), global::Grpc.Testing.ComplexProtoParams.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.PayloadConfig), global::Grpc.Testing.PayloadConfig.Parser, new[]{ "BytebufParams", "SimpleParams", "ComplexParams" }, new[]{ "Payload" }, null, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class ByteBufferParams : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ByteBufferParams()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.PayloadsReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ByteBufferParams() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ByteBufferParams(ByteBufferParams other) : this() { + reqSize_ = other.reqSize_; + respSize_ = other.respSize_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ByteBufferParams Clone() { + return new ByteBufferParams(this); + } + + /// Field number for the "req_size" field. + public const int ReqSizeFieldNumber = 1; + private int reqSize_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ReqSize { + get { return reqSize_; } + set { + reqSize_ = value; + } + } + + /// Field number for the "resp_size" field. + public const int RespSizeFieldNumber = 2; + private int respSize_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int RespSize { + get { return respSize_; } + set { + respSize_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ByteBufferParams); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ByteBufferParams other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ReqSize != other.ReqSize) return false; + if (RespSize != other.RespSize) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (ReqSize != 0) hash ^= ReqSize.GetHashCode(); + if (RespSize != 0) hash ^= RespSize.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (ReqSize != 0) { + output.WriteRawTag(8); + output.WriteInt32(ReqSize); + } + if (RespSize != 0) { + output.WriteRawTag(16); + output.WriteInt32(RespSize); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (ReqSize != 0) { + output.WriteRawTag(8); + output.WriteInt32(ReqSize); + } + if (RespSize != 0) { + output.WriteRawTag(16); + output.WriteInt32(RespSize); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (ReqSize != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ReqSize); + } + if (RespSize != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ByteBufferParams other) { + if (other == null) { + return; + } + if (other.ReqSize != 0) { + ReqSize = other.ReqSize; + } + if (other.RespSize != 0) { + RespSize = other.RespSize; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + ReqSize = input.ReadInt32(); + break; + } + case 16: { + RespSize = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + ReqSize = input.ReadInt32(); + break; + } + case 16: { + RespSize = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + public sealed partial class SimpleProtoParams : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SimpleProtoParams()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.PayloadsReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SimpleProtoParams() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SimpleProtoParams(SimpleProtoParams other) : this() { + reqSize_ = other.reqSize_; + respSize_ = other.respSize_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public SimpleProtoParams Clone() { + return new SimpleProtoParams(this); + } + + /// Field number for the "req_size" field. + public const int ReqSizeFieldNumber = 1; + private int reqSize_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ReqSize { + get { return reqSize_; } + set { + reqSize_ = value; + } + } + + /// Field number for the "resp_size" field. + public const int RespSizeFieldNumber = 2; + private int respSize_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int RespSize { + get { return respSize_; } + set { + respSize_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as SimpleProtoParams); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(SimpleProtoParams other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ReqSize != other.ReqSize) return false; + if (RespSize != other.RespSize) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (ReqSize != 0) hash ^= ReqSize.GetHashCode(); + if (RespSize != 0) hash ^= RespSize.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (ReqSize != 0) { + output.WriteRawTag(8); + output.WriteInt32(ReqSize); + } + if (RespSize != 0) { + output.WriteRawTag(16); + output.WriteInt32(RespSize); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (ReqSize != 0) { + output.WriteRawTag(8); + output.WriteInt32(ReqSize); + } + if (RespSize != 0) { + output.WriteRawTag(16); + output.WriteInt32(RespSize); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (ReqSize != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ReqSize); + } + if (RespSize != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(SimpleProtoParams other) { + if (other == null) { + return; + } + if (other.ReqSize != 0) { + ReqSize = other.ReqSize; + } + if (other.RespSize != 0) { + RespSize = other.RespSize; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + ReqSize = input.ReadInt32(); + break; + } + case 16: { + RespSize = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + ReqSize = input.ReadInt32(); + break; + } + case 16: { + RespSize = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// TODO (vpai): Fill this in once the details of complex, representative + /// protos are decided + /// + public sealed partial class ComplexProtoParams : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ComplexProtoParams()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.PayloadsReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ComplexProtoParams() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ComplexProtoParams(ComplexProtoParams other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ComplexProtoParams Clone() { + return new ComplexProtoParams(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ComplexProtoParams); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ComplexProtoParams other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ComplexProtoParams other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + } + } + } + #endif + + } + + public sealed partial class PayloadConfig : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new PayloadConfig()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.PayloadsReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public PayloadConfig() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public PayloadConfig(PayloadConfig other) : this() { + switch (other.PayloadCase) { + case PayloadOneofCase.BytebufParams: + BytebufParams = other.BytebufParams.Clone(); + break; + case PayloadOneofCase.SimpleParams: + SimpleParams = other.SimpleParams.Clone(); + break; + case PayloadOneofCase.ComplexParams: + ComplexParams = other.ComplexParams.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public PayloadConfig Clone() { + return new PayloadConfig(this); + } + + /// Field number for the "bytebuf_params" field. + public const int BytebufParamsFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ByteBufferParams BytebufParams { + get { return payloadCase_ == PayloadOneofCase.BytebufParams ? (global::Grpc.Testing.ByteBufferParams) payload_ : null; } + set { + payload_ = value; + payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.BytebufParams; + } + } + + /// Field number for the "simple_params" field. + public const int SimpleParamsFieldNumber = 2; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.SimpleProtoParams SimpleParams { + get { return payloadCase_ == PayloadOneofCase.SimpleParams ? (global::Grpc.Testing.SimpleProtoParams) payload_ : null; } + set { + payload_ = value; + payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.SimpleParams; + } + } + + /// Field number for the "complex_params" field. + public const int ComplexParamsFieldNumber = 3; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.ComplexProtoParams ComplexParams { + get { return payloadCase_ == PayloadOneofCase.ComplexParams ? (global::Grpc.Testing.ComplexProtoParams) payload_ : null; } + set { + payload_ = value; + payloadCase_ = value == null ? PayloadOneofCase.None : PayloadOneofCase.ComplexParams; + } + } + + private object payload_; + /// Enum of possible cases for the "payload" oneof. + public enum PayloadOneofCase { + None = 0, + BytebufParams = 1, + SimpleParams = 2, + ComplexParams = 3, + } + private PayloadOneofCase payloadCase_ = PayloadOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public PayloadOneofCase PayloadCase { + get { return payloadCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearPayload() { + payloadCase_ = PayloadOneofCase.None; + payload_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as PayloadConfig); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(PayloadConfig other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(BytebufParams, other.BytebufParams)) return false; + if (!object.Equals(SimpleParams, other.SimpleParams)) return false; + if (!object.Equals(ComplexParams, other.ComplexParams)) return false; + if (PayloadCase != other.PayloadCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (payloadCase_ == PayloadOneofCase.BytebufParams) hash ^= BytebufParams.GetHashCode(); + if (payloadCase_ == PayloadOneofCase.SimpleParams) hash ^= SimpleParams.GetHashCode(); + if (payloadCase_ == PayloadOneofCase.ComplexParams) hash ^= ComplexParams.GetHashCode(); + hash ^= (int) payloadCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (payloadCase_ == PayloadOneofCase.BytebufParams) { + output.WriteRawTag(10); + output.WriteMessage(BytebufParams); + } + if (payloadCase_ == PayloadOneofCase.SimpleParams) { + output.WriteRawTag(18); + output.WriteMessage(SimpleParams); + } + if (payloadCase_ == PayloadOneofCase.ComplexParams) { + output.WriteRawTag(26); + output.WriteMessage(ComplexParams); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (payloadCase_ == PayloadOneofCase.BytebufParams) { + output.WriteRawTag(10); + output.WriteMessage(BytebufParams); + } + if (payloadCase_ == PayloadOneofCase.SimpleParams) { + output.WriteRawTag(18); + output.WriteMessage(SimpleParams); + } + if (payloadCase_ == PayloadOneofCase.ComplexParams) { + output.WriteRawTag(26); + output.WriteMessage(ComplexParams); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (payloadCase_ == PayloadOneofCase.BytebufParams) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(BytebufParams); + } + if (payloadCase_ == PayloadOneofCase.SimpleParams) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(SimpleParams); + } + if (payloadCase_ == PayloadOneofCase.ComplexParams) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ComplexParams); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(PayloadConfig other) { + if (other == null) { + return; + } + switch (other.PayloadCase) { + case PayloadOneofCase.BytebufParams: + if (BytebufParams == null) { + BytebufParams = new global::Grpc.Testing.ByteBufferParams(); + } + BytebufParams.MergeFrom(other.BytebufParams); + break; + case PayloadOneofCase.SimpleParams: + if (SimpleParams == null) { + SimpleParams = new global::Grpc.Testing.SimpleProtoParams(); + } + SimpleParams.MergeFrom(other.SimpleParams); + break; + case PayloadOneofCase.ComplexParams: + if (ComplexParams == null) { + ComplexParams = new global::Grpc.Testing.ComplexProtoParams(); + } + ComplexParams.MergeFrom(other.ComplexParams); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + global::Grpc.Testing.ByteBufferParams subBuilder = new global::Grpc.Testing.ByteBufferParams(); + if (payloadCase_ == PayloadOneofCase.BytebufParams) { + subBuilder.MergeFrom(BytebufParams); + } + input.ReadMessage(subBuilder); + BytebufParams = subBuilder; + break; + } + case 18: { + global::Grpc.Testing.SimpleProtoParams subBuilder = new global::Grpc.Testing.SimpleProtoParams(); + if (payloadCase_ == PayloadOneofCase.SimpleParams) { + subBuilder.MergeFrom(SimpleParams); + } + input.ReadMessage(subBuilder); + SimpleParams = subBuilder; + break; + } + case 26: { + global::Grpc.Testing.ComplexProtoParams subBuilder = new global::Grpc.Testing.ComplexProtoParams(); + if (payloadCase_ == PayloadOneofCase.ComplexParams) { + subBuilder.MergeFrom(ComplexParams); + } + input.ReadMessage(subBuilder); + ComplexParams = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + global::Grpc.Testing.ByteBufferParams subBuilder = new global::Grpc.Testing.ByteBufferParams(); + if (payloadCase_ == PayloadOneofCase.BytebufParams) { + subBuilder.MergeFrom(BytebufParams); + } + input.ReadMessage(subBuilder); + BytebufParams = subBuilder; + break; + } + case 18: { + global::Grpc.Testing.SimpleProtoParams subBuilder = new global::Grpc.Testing.SimpleProtoParams(); + if (payloadCase_ == PayloadOneofCase.SimpleParams) { + subBuilder.MergeFrom(SimpleParams); + } + input.ReadMessage(subBuilder); + SimpleParams = subBuilder; + break; + } + case 26: { + global::Grpc.Testing.ComplexProtoParams subBuilder = new global::Grpc.Testing.ComplexProtoParams(); + if (payloadCase_ == PayloadOneofCase.ComplexParams) { + subBuilder.MergeFrom(ComplexParams); + } + input.ReadMessage(subBuilder); + ComplexParams = subBuilder; + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..e0f92cc2 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.IntegrationTesting")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs new file mode 100644 index 00000000..a579fb80 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs @@ -0,0 +1,87 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +using CommandLine; +using CommandLine.Text; +using Grpc.Core; +using Grpc.Core.Logging; +using Grpc.Core.Utils; +using Grpc.Testing; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + public class QpsWorker + { + private class ServerOptions + { + [Option("driver_port", Default = 0)] + public int DriverPort { get; set; } + } + + ServerOptions options; + + private QpsWorker(ServerOptions options) + { + this.options = options; + } + + public static void Run(string[] args) + { + GrpcEnvironment.SetLogger(new ConsoleLogger()); + var parserResult = Parser.Default.ParseArguments(args) + .WithNotParsed((x) => Environment.Exit(1)) + .WithParsed(options => + { + var workerServer = new QpsWorker(options); + workerServer.RunAsync().Wait(); + }); + } + + private async Task RunAsync() + { + string host = "0.0.0.0"; + int port = options.DriverPort; + + var tcs = new TaskCompletionSource(); + var workerServiceImpl = new WorkerServiceImpl(() => { Task.Run(() => tcs.SetResult(null)); }); + + var server = new Server + { + Services = { WorkerService.BindService(workerServiceImpl) }, + Ports = { new ServerPort(host, options.DriverPort, ServerCredentials.Insecure )} + }; + int boundPort = server.Ports.Single().BoundPort; + GrpcEnvironment.Logger.Info("Running qps worker server on {0}:{1}", host, boundPort); + server.Start(); + await tcs.Task; + await server.ShutdownAsync(); + + GrpcEnvironment.Logger.Info("GC collection counts (after shutdown): gen0 {0}, gen1 {1}, gen2 {2}", + GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2)); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioService.cs b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioService.cs new file mode 100644 index 00000000..fdad8acc --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioService.cs @@ -0,0 +1,41 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/report_qps_scenario_service.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Testing { + + /// Holder for reflection information generated from src/proto/grpc/testing/report_qps_scenario_service.proto + public static partial class ReportQpsScenarioServiceReflection { + + #region Descriptor + /// File descriptor for src/proto/grpc/testing/report_qps_scenario_service.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static ReportQpsScenarioServiceReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CjhzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3JlcG9ydF9xcHNfc2NlbmFyaW9f", + "c2VydmljZS5wcm90bxIMZ3JwYy50ZXN0aW5nGiRzcmMvcHJvdG8vZ3JwYy90", + "ZXN0aW5nL2NvbnRyb2wucHJvdG8yXgoYUmVwb3J0UXBzU2NlbmFyaW9TZXJ2", + "aWNlEkIKDlJlcG9ydFNjZW5hcmlvEhwuZ3JwYy50ZXN0aW5nLlNjZW5hcmlv", + "UmVzdWx0GhIuZ3JwYy50ZXN0aW5nLlZvaWRiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Grpc.Testing.ControlReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, null, null)); + } + #endregion + + } +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs new file mode 100644 index 00000000..36ba70d8 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs @@ -0,0 +1,206 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/report_qps_scenario_service.proto +// +// Original file comments: +// Copyright 2015 gRPC authors. +// +// 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. +// +// An integration test service that covers all the method signature permutations +// of unary/streaming requests/responses. +#pragma warning disable 0414, 1591 +#region Designer generated code + +using grpc = global::Grpc.Core; + +namespace Grpc.Testing { + public static partial class ReportQpsScenarioService + { + static readonly string __ServiceName = "grpc.testing.ReportQpsScenarioService"; + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context) + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (message is global::Google.Protobuf.IBufferMessage) + { + context.SetPayloadLength(message.CalculateSize()); + global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter()); + context.Complete(); + return; + } + #endif + context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static class __Helper_MessageCache + { + public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static T __Helper_DeserializeMessage(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser parser) where T : global::Google.Protobuf.IMessage + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (__Helper_MessageCache.IsBufferMessage) + { + return parser.ParseFrom(context.PayloadAsReadOnlySequence()); + } + #endif + return parser.ParseFrom(context.PayloadAsNewBuffer()); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_ScenarioResult = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.ScenarioResult.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_Void = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.Void.Parser)); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_ReportScenario = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "ReportScenario", + __Marshaller_grpc_testing_ScenarioResult, + __Marshaller_grpc_testing_Void); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Testing.ReportQpsScenarioServiceReflection.Descriptor.Services[0]; } + } + + /// Base class for server-side implementations of ReportQpsScenarioService + [grpc::BindServiceMethod(typeof(ReportQpsScenarioService), "BindService")] + public abstract partial class ReportQpsScenarioServiceBase + { + /// + /// Report results of a QPS test benchmark scenario. + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task ReportScenario(global::Grpc.Testing.ScenarioResult request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for ReportQpsScenarioService + public partial class ReportQpsScenarioServiceClient : grpc::ClientBase + { + /// Creates a new client for ReportQpsScenarioService + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public ReportQpsScenarioServiceClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for ReportQpsScenarioService that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public ReportQpsScenarioServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected ReportQpsScenarioServiceClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected ReportQpsScenarioServiceClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// Report results of a QPS test benchmark scenario. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Void ReportScenario(global::Grpc.Testing.ScenarioResult request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return ReportScenario(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Report results of a QPS test benchmark scenario. + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Void ReportScenario(global::Grpc.Testing.ScenarioResult request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_ReportScenario, null, options, request); + } + /// + /// Report results of a QPS test benchmark scenario. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall ReportScenarioAsync(global::Grpc.Testing.ScenarioResult request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return ReportScenarioAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Report results of a QPS test benchmark scenario. + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall ReportScenarioAsync(global::Grpc.Testing.ScenarioResult request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_ReportScenario, null, options, request); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override ReportQpsScenarioServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new ReportQpsScenarioServiceClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static grpc::ServerServiceDefinition BindService(ReportQpsScenarioServiceBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_ReportScenario, serviceImpl.ReportScenario).Build(); + } + + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static void BindService(grpc::ServiceBinderBase serviceBinder, ReportQpsScenarioServiceBase serviceImpl) + { + serviceBinder.AddMethod(__Method_ReportScenario, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.ReportScenario)); + } + + } +} +#endregion diff --git a/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs new file mode 100644 index 00000000..c5c92aa9 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/RunnerClientServerTest.cs @@ -0,0 +1,95 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Testing; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + /// + /// Runs performance tests in-process. + /// + public class RunnerClientServerTest + { + IServerRunner serverRunner; + + [OneTimeSetUp] + public void Init() + { + var serverConfig = new ServerConfig + { + ServerType = ServerType.AsyncServer + }; + serverRunner = ServerRunners.CreateStarted(serverConfig); + } + + [OneTimeTearDown] + public void Cleanup() + { + serverRunner.StopAsync().Wait(); + } + + + [Test] + [Category("Performance")] + [Ignore("Prevent running on Jenkins")] + public async Task ClientServerRunner() + { + var config = new ClientConfig + { + ServerTargets = { string.Format("{0}:{1}", "localhost", serverRunner.BoundPort) }, + RpcType = RpcType.Unary, + LoadParams = new LoadParams { ClosedLoop = new ClosedLoopParams() }, + PayloadConfig = new PayloadConfig + { + SimpleParams = new SimpleProtoParams + { + ReqSize = 100, + RespSize = 100 + } + }, + HistogramParams = new HistogramParams + { + Resolution = 0.01, + MaxPossible = 60e9 + } + }; + + var runner = ClientRunners.CreateStarted(config); + + System.Console.WriteLine("Warming up"); + await Task.Delay(3000); + runner.GetStats(true); // throw away warm-up data + + System.Console.WriteLine("Benchmarking"); + await Task.Delay(3000); + var stats = runner.GetStats(true); + await runner.StopAsync(); + + System.Console.WriteLine(stats); + System.Console.WriteLine("avg micros/call " + (long) (stats.Latencies.Sum / stats.Latencies.Count / 1000.0)); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs new file mode 100644 index 00000000..ea29bd74 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs @@ -0,0 +1,163 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Google.Protobuf; +using Grpc.Core; +using Grpc.Core.Logging; +using Grpc.Core.Utils; +using NUnit.Framework; +using Grpc.Testing; + +namespace Grpc.IntegrationTesting +{ + /// + /// Helper methods to start server runners for performance testing. + /// + public class ServerRunners + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + + /// + /// Creates a started server runner. + /// + public static IServerRunner CreateStarted(ServerConfig config) + { + Logger.Debug("ServerConfig: {0}", config); + var credentials = config.SecurityParams != null ? TestCredentials.CreateSslServerCredentials() : ServerCredentials.Insecure; + + if (config.AsyncServerThreads != 0) + { + Logger.Warning("ServerConfig.AsyncServerThreads is not supported for C#. Ignoring the value"); + } + if (config.CoreLimit != 0) + { + Logger.Warning("ServerConfig.CoreLimit is not supported for C#. Ignoring the value"); + } + if (config.CoreList.Count > 0) + { + Logger.Warning("ServerConfig.CoreList is not supported for C#. Ignoring the value"); + } + + ServerServiceDefinition service = null; + if (config.ServerType == ServerType.AsyncServer) + { + GrpcPreconditions.CheckArgument(config.PayloadConfig == null, + "ServerConfig.PayloadConfig shouldn't be set for BenchmarkService based server."); + service = BenchmarkService.BindService(new BenchmarkServiceImpl()); + } + else if (config.ServerType == ServerType.AsyncGenericServer) + { + var genericService = new GenericServiceImpl(config.PayloadConfig.BytebufParams.RespSize); + service = GenericService.BindHandler(genericService.StreamingCall); + } + else + { + throw new ArgumentException("Unsupported ServerType"); + } + + var channelOptions = new List(config.ChannelArgs.Select((arg) => arg.ToChannelOption())); + var server = new Server(channelOptions) + { + Services = { service }, + Ports = { new ServerPort("[::]", config.Port, credentials) } + }; + + server.Start(); + return new ServerRunnerImpl(server); + } + + private class GenericServiceImpl + { + readonly byte[] response; + + public GenericServiceImpl(int responseSize) + { + this.response = new byte[responseSize]; + } + + /// + /// Generic streaming call handler. + /// + public async Task StreamingCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + { + await requestStream.ForEachAsync(async request => + { + await responseStream.WriteAsync(response); + }); + } + } + } + + /// + /// Server runner. + /// + public class ServerRunnerImpl : IServerRunner + { + readonly Server server; + readonly TimeStats timeStats = new TimeStats(); + + public ServerRunnerImpl(Server server) + { + this.server = GrpcPreconditions.CheckNotNull(server); + } + + public int BoundPort + { + get + { + return server.Ports.Single().BoundPort; + } + } + + /// + /// Gets server stats. + /// + /// The stats. + public ServerStats GetStats(bool reset) + { + var timeSnapshot = timeStats.GetSnapshot(reset); + + GrpcEnvironment.Logger.Info("[ServerRunner.GetStats] GC collection counts: gen0 {0}, gen1 {1}, gen2 {2}, (seconds since last reset {3})", + GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2), timeSnapshot.WallClockTime.TotalSeconds); + + return new ServerStats + { + TimeElapsed = timeSnapshot.WallClockTime.TotalSeconds, + TimeUser = timeSnapshot.UserProcessorTime.TotalSeconds, + TimeSystem = timeSnapshot.PrivilegedProcessorTime.TotalSeconds + }; + } + + /// + /// Asynchronously stops the server. + /// + /// Task that finishes when server has shutdown. + public Task StopAsync() + { + return server.ShutdownAsync(); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs new file mode 100644 index 00000000..c7ff3216 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs @@ -0,0 +1,289 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Google.Protobuf; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Testing; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + /// + /// Test SSL credentials where server authenticates client + /// and client authenticates the server. + /// + public class SslCredentialsTest + { + const string Host = "localhost"; + const string IsPeerAuthenticatedMetadataKey = "test_only_is_peer_authenticated"; + Server server; + Channel channel; + TestService.TestServiceClient client; + + string rootCert; + KeyCertificatePair keyCertPair; + + public void InitClientAndServer(bool clientAddKeyCertPair, + SslClientCertificateRequestType clientCertRequestType, + VerifyPeerCallback verifyPeerCallback = null) + { + rootCert = File.ReadAllText(TestCredentials.ClientCertAuthorityPath); + keyCertPair = new KeyCertificatePair( + File.ReadAllText(TestCredentials.ServerCertChainPath), + File.ReadAllText(TestCredentials.ServerPrivateKeyPath)); + + var serverCredentials = new SslServerCredentials(new[] { keyCertPair }, rootCert, clientCertRequestType); + var clientCredentials = new SslCredentials(rootCert, clientAddKeyCertPair ? keyCertPair : null, verifyPeerCallback); + + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { TestService.BindService(new SslCredentialsTestServiceImpl()) }, + Ports = { { Host, ServerPort.PickUnused, serverCredentials } } + }; + server.Start(); + + var options = new List + { + new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride) + }; + + channel = new Channel(Host, server.Ports.Single().BoundPort, clientCredentials, options); + client = new TestService.TestServiceClient(channel); + } + + [OneTimeTearDown] + public void Cleanup() + { + if (channel != null) + { + channel.ShutdownAsync().Wait(); + } + if (server != null) + { + server.ShutdownAsync().Wait(); + } + } + + [Test] + public async Task NoClientCert_DontRequestClientCertificate_Accepted() + { + InitClientAndServer( + clientAddKeyCertPair: false, + clientCertRequestType: SslClientCertificateRequestType.DontRequest); + + await CheckAccepted(expectPeerAuthenticated: false); + } + + [Test] + public async Task ClientWithCert_DontRequestClientCertificate_AcceptedButPeerNotAuthenticated() + { + InitClientAndServer( + clientAddKeyCertPair: true, + clientCertRequestType: SslClientCertificateRequestType.DontRequest); + + await CheckAccepted(expectPeerAuthenticated: false); + } + + [Test] + public async Task NoClientCert_RequestClientCertificateButDontVerify_Accepted() + { + InitClientAndServer( + clientAddKeyCertPair: false, + clientCertRequestType: SslClientCertificateRequestType.RequestButDontVerify); + + await CheckAccepted(expectPeerAuthenticated: false); + } + + [Test] + public async Task NoClientCert_RequestClientCertificateAndVerify_Accepted() + { + InitClientAndServer( + clientAddKeyCertPair: false, + clientCertRequestType: SslClientCertificateRequestType.RequestAndVerify); + + await CheckAccepted(expectPeerAuthenticated: false); + } + + [Test] + public async Task ClientWithCert_RequestAndRequireClientCertificateButDontVerify_Accepted() + { + InitClientAndServer( + clientAddKeyCertPair: true, + clientCertRequestType: SslClientCertificateRequestType.RequestAndRequireButDontVerify); + + await CheckAccepted(expectPeerAuthenticated: true); + await CheckAuthContextIsPopulated(); + } + + [Test] + public async Task ClientWithCert_RequestAndRequireClientCertificateAndVerify_Accepted() + { + InitClientAndServer( + clientAddKeyCertPair: true, + clientCertRequestType: SslClientCertificateRequestType.RequestAndRequireAndVerify); + + await CheckAccepted(expectPeerAuthenticated: true); + await CheckAuthContextIsPopulated(); + } + + [Test] + public void NoClientCert_RequestAndRequireClientCertificateButDontVerify_Rejected() + { + InitClientAndServer( + clientAddKeyCertPair: false, + clientCertRequestType: SslClientCertificateRequestType.RequestAndRequireButDontVerify); + + CheckRejected(); + } + + [Test] + public void NoClientCert_RequestAndRequireClientCertificateAndVerify_Rejected() + { + InitClientAndServer( + clientAddKeyCertPair: false, + clientCertRequestType: SslClientCertificateRequestType.RequestAndRequireAndVerify); + + CheckRejected(); + } + + [Test] + public void Constructor_LegacyForceClientAuth() + { + var creds = new SslServerCredentials(new[] { keyCertPair }, rootCert, true); + Assert.AreEqual(SslClientCertificateRequestType.RequestAndRequireAndVerify, creds.ClientCertificateRequest); + + var creds2 = new SslServerCredentials(new[] { keyCertPair }, rootCert, false); + Assert.AreEqual(SslClientCertificateRequestType.DontRequest, creds2.ClientCertificateRequest); + } + + [Test] + public void Constructor_NullRootCerts() + { + var keyCertPairs = new[] { keyCertPair }; + Assert.DoesNotThrow(() => new SslServerCredentials(keyCertPairs, null, SslClientCertificateRequestType.DontRequest)); + Assert.DoesNotThrow(() => new SslServerCredentials(keyCertPairs, null, SslClientCertificateRequestType.RequestAndVerify)); + Assert.DoesNotThrow(() => new SslServerCredentials(keyCertPairs, null, SslClientCertificateRequestType.RequestAndRequireButDontVerify)); + Assert.Throws(typeof(ArgumentNullException), () => new SslServerCredentials(keyCertPairs, null, SslClientCertificateRequestType.RequestAndRequireAndVerify)); + } + + [Test] + public async Task VerifyPeerCallback_Accepted() + { + string targetNameFromCallback = null; + string peerPemFromCallback = null; + InitClientAndServer( + clientAddKeyCertPair: false, + clientCertRequestType: SslClientCertificateRequestType.DontRequest, + verifyPeerCallback: (ctx) => + { + targetNameFromCallback = ctx.TargetName; + peerPemFromCallback = ctx.PeerPem; + return true; + }); + await CheckAccepted(expectPeerAuthenticated: false); + Assert.AreEqual(TestCredentials.DefaultHostOverride, targetNameFromCallback); + var expectedServerPem = File.ReadAllText(TestCredentials.ServerCertChainPath).Replace("\r", ""); + Assert.AreEqual(expectedServerPem, peerPemFromCallback); + } + + [Test] + public void VerifyPeerCallback_CallbackThrows_Rejected() + { + InitClientAndServer( + clientAddKeyCertPair: false, + clientCertRequestType: SslClientCertificateRequestType.DontRequest, + verifyPeerCallback: (ctx) => + { + throw new Exception("VerifyPeerCallback has thrown on purpose."); + }); + CheckRejected(); + } + + [Test] + public void VerifyPeerCallback_Rejected() + { + InitClientAndServer( + clientAddKeyCertPair: false, + clientCertRequestType: SslClientCertificateRequestType.DontRequest, + verifyPeerCallback: (ctx) => + { + return false; + }); + CheckRejected(); + } + + private async Task CheckAccepted(bool expectPeerAuthenticated) + { + var call = client.UnaryCallAsync(new SimpleRequest { ResponseSize = 10 }); + var response = await call; + Assert.AreEqual(10, response.Payload.Body.Length); + Assert.AreEqual(expectPeerAuthenticated.ToString(), call.GetTrailers().First((entry) => entry.Key == IsPeerAuthenticatedMetadataKey).Value); + } + + private void CheckRejected() + { + var ex = Assert.Throws(() => client.UnaryCall(new SimpleRequest { ResponseSize = 10 })); + if (ex.Status.StatusCode != StatusCode.Unavailable & ex.Status.StatusCode != StatusCode.Unknown) { + Assert.Fail("Expect status to be either Unavailable or Unknown"); + } + } + + private async Task CheckAuthContextIsPopulated() + { + var call = client.StreamingInputCall(); + await call.RequestStream.CompleteAsync(); + var response = await call.ResponseAsync; + Assert.AreEqual(12345, response.AggregatedPayloadSize); + } + + private class SslCredentialsTestServiceImpl : TestService.TestServiceBase + { + public override Task UnaryCall(SimpleRequest request, ServerCallContext context) + { + context.ResponseTrailers.Add(IsPeerAuthenticatedMetadataKey, context.AuthContext.IsPeerAuthenticated.ToString()); + return Task.FromResult(new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) }); + } + + public override async Task StreamingInputCall(IAsyncStreamReader requestStream, ServerCallContext context) + { + var authContext = context.AuthContext; + await requestStream.ForEachAsync(request => TaskUtils.CompletedTask); + + Assert.IsTrue(authContext.IsPeerAuthenticated); + Assert.AreEqual("x509_subject_alternative_name", authContext.PeerIdentityPropertyName); + Assert.IsTrue(authContext.PeerIdentity.Count() > 0); + Assert.AreEqual("ssl", authContext.FindPropertiesByName("transport_security_type").First().Value); + + return new StreamingInputCallResponse { AggregatedPayloadSize = 12345 }; + } + + private static Payload CreateZerosPayload(int size) + { + return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; + } + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/Stats.cs b/src/csharp/Grpc.IntegrationTesting/Stats.cs new file mode 100644 index 00000000..375ca03e --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/Stats.cs @@ -0,0 +1,1766 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/stats.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Testing { + + /// Holder for reflection information generated from src/proto/grpc/testing/stats.proto + public static partial class StatsReflection { + + #region Descriptor + /// File descriptor for src/proto/grpc/testing/stats.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static StatsReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CiJzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3N0YXRzLnByb3RvEgxncnBjLnRl", + "c3RpbmcaH3NyYy9wcm90by9ncnBjL2NvcmUvc3RhdHMucHJvdG8itwEKC1Nl", + "cnZlclN0YXRzEhQKDHRpbWVfZWxhcHNlZBgBIAEoARIRCgl0aW1lX3VzZXIY", + "AiABKAESEwoLdGltZV9zeXN0ZW0YAyABKAESFgoOdG90YWxfY3B1X3RpbWUY", + "BCABKAQSFQoNaWRsZV9jcHVfdGltZRgFIAEoBBIVCg1jcV9wb2xsX2NvdW50", + "GAYgASgEEiQKCmNvcmVfc3RhdHMYByABKAsyEC5ncnBjLmNvcmUuU3RhdHMi", + "OwoPSGlzdG9ncmFtUGFyYW1zEhIKCnJlc29sdXRpb24YASABKAESFAoMbWF4", + "X3Bvc3NpYmxlGAIgASgBIncKDUhpc3RvZ3JhbURhdGESDgoGYnVja2V0GAEg", + "AygNEhAKCG1pbl9zZWVuGAIgASgBEhAKCG1heF9zZWVuGAMgASgBEgsKA3N1", + "bRgEIAEoARIWCg5zdW1fb2Zfc3F1YXJlcxgFIAEoARINCgVjb3VudBgGIAEo", + "ASI4ChJSZXF1ZXN0UmVzdWx0Q291bnQSEwoLc3RhdHVzX2NvZGUYASABKAUS", + "DQoFY291bnQYAiABKAMi8wEKC0NsaWVudFN0YXRzEi4KCWxhdGVuY2llcxgB", + "IAEoCzIbLmdycGMudGVzdGluZy5IaXN0b2dyYW1EYXRhEhQKDHRpbWVfZWxh", + "cHNlZBgCIAEoARIRCgl0aW1lX3VzZXIYAyABKAESEwoLdGltZV9zeXN0ZW0Y", + "BCABKAESOQoPcmVxdWVzdF9yZXN1bHRzGAUgAygLMiAuZ3JwYy50ZXN0aW5n", + "LlJlcXVlc3RSZXN1bHRDb3VudBIVCg1jcV9wb2xsX2NvdW50GAYgASgEEiQK", + "CmNvcmVfc3RhdHMYByABKAsyEC5ncnBjLmNvcmUuU3RhdHNiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Grpc.Core.StatsReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStats), global::Grpc.Testing.ServerStats.Parser, new[]{ "TimeElapsed", "TimeUser", "TimeSystem", "TotalCpuTime", "IdleCpuTime", "CqPollCount", "CoreStats" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.HistogramParams), global::Grpc.Testing.HistogramParams.Parser, new[]{ "Resolution", "MaxPossible" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.HistogramData), global::Grpc.Testing.HistogramData.Parser, new[]{ "Bucket", "MinSeen", "MaxSeen", "Sum", "SumOfSquares", "Count" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.RequestResultCount), global::Grpc.Testing.RequestResultCount.Parser, new[]{ "StatusCode", "Count" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStats), global::Grpc.Testing.ClientStats.Parser, new[]{ "Latencies", "TimeElapsed", "TimeUser", "TimeSystem", "RequestResults", "CqPollCount", "CoreStats" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + public sealed partial class ServerStats : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServerStats()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.StatsReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerStats() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerStats(ServerStats other) : this() { + timeElapsed_ = other.timeElapsed_; + timeUser_ = other.timeUser_; + timeSystem_ = other.timeSystem_; + totalCpuTime_ = other.totalCpuTime_; + idleCpuTime_ = other.idleCpuTime_; + cqPollCount_ = other.cqPollCount_; + coreStats_ = other.coreStats_ != null ? other.coreStats_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerStats Clone() { + return new ServerStats(this); + } + + /// Field number for the "time_elapsed" field. + public const int TimeElapsedFieldNumber = 1; + private double timeElapsed_; + /// + /// wall clock time change in seconds since last reset + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double TimeElapsed { + get { return timeElapsed_; } + set { + timeElapsed_ = value; + } + } + + /// Field number for the "time_user" field. + public const int TimeUserFieldNumber = 2; + private double timeUser_; + /// + /// change in user time (in seconds) used by the server since last reset + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double TimeUser { + get { return timeUser_; } + set { + timeUser_ = value; + } + } + + /// Field number for the "time_system" field. + public const int TimeSystemFieldNumber = 3; + private double timeSystem_; + /// + /// change in server time (in seconds) used by the server process and all + /// threads since last reset + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double TimeSystem { + get { return timeSystem_; } + set { + timeSystem_ = value; + } + } + + /// Field number for the "total_cpu_time" field. + public const int TotalCpuTimeFieldNumber = 4; + private ulong totalCpuTime_; + /// + /// change in total cpu time of the server (data from proc/stat) + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ulong TotalCpuTime { + get { return totalCpuTime_; } + set { + totalCpuTime_ = value; + } + } + + /// Field number for the "idle_cpu_time" field. + public const int IdleCpuTimeFieldNumber = 5; + private ulong idleCpuTime_; + /// + /// change in idle time of the server (data from proc/stat) + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ulong IdleCpuTime { + get { return idleCpuTime_; } + set { + idleCpuTime_ = value; + } + } + + /// Field number for the "cq_poll_count" field. + public const int CqPollCountFieldNumber = 6; + private ulong cqPollCount_; + /// + /// Number of polls called inside completion queue + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ulong CqPollCount { + get { return cqPollCount_; } + set { + cqPollCount_ = value; + } + } + + /// Field number for the "core_stats" field. + public const int CoreStatsFieldNumber = 7; + private global::Grpc.Core.Stats coreStats_; + /// + /// Core library stats + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Core.Stats CoreStats { + get { return coreStats_; } + set { + coreStats_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ServerStats); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ServerStats other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeElapsed, other.TimeElapsed)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeUser, other.TimeUser)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeSystem, other.TimeSystem)) return false; + if (TotalCpuTime != other.TotalCpuTime) return false; + if (IdleCpuTime != other.IdleCpuTime) return false; + if (CqPollCount != other.CqPollCount) return false; + if (!object.Equals(CoreStats, other.CoreStats)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (TimeElapsed != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeElapsed); + if (TimeUser != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeUser); + if (TimeSystem != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeSystem); + if (TotalCpuTime != 0UL) hash ^= TotalCpuTime.GetHashCode(); + if (IdleCpuTime != 0UL) hash ^= IdleCpuTime.GetHashCode(); + if (CqPollCount != 0UL) hash ^= CqPollCount.GetHashCode(); + if (coreStats_ != null) hash ^= CoreStats.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (TimeElapsed != 0D) { + output.WriteRawTag(9); + output.WriteDouble(TimeElapsed); + } + if (TimeUser != 0D) { + output.WriteRawTag(17); + output.WriteDouble(TimeUser); + } + if (TimeSystem != 0D) { + output.WriteRawTag(25); + output.WriteDouble(TimeSystem); + } + if (TotalCpuTime != 0UL) { + output.WriteRawTag(32); + output.WriteUInt64(TotalCpuTime); + } + if (IdleCpuTime != 0UL) { + output.WriteRawTag(40); + output.WriteUInt64(IdleCpuTime); + } + if (CqPollCount != 0UL) { + output.WriteRawTag(48); + output.WriteUInt64(CqPollCount); + } + if (coreStats_ != null) { + output.WriteRawTag(58); + output.WriteMessage(CoreStats); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (TimeElapsed != 0D) { + output.WriteRawTag(9); + output.WriteDouble(TimeElapsed); + } + if (TimeUser != 0D) { + output.WriteRawTag(17); + output.WriteDouble(TimeUser); + } + if (TimeSystem != 0D) { + output.WriteRawTag(25); + output.WriteDouble(TimeSystem); + } + if (TotalCpuTime != 0UL) { + output.WriteRawTag(32); + output.WriteUInt64(TotalCpuTime); + } + if (IdleCpuTime != 0UL) { + output.WriteRawTag(40); + output.WriteUInt64(IdleCpuTime); + } + if (CqPollCount != 0UL) { + output.WriteRawTag(48); + output.WriteUInt64(CqPollCount); + } + if (coreStats_ != null) { + output.WriteRawTag(58); + output.WriteMessage(CoreStats); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (TimeElapsed != 0D) { + size += 1 + 8; + } + if (TimeUser != 0D) { + size += 1 + 8; + } + if (TimeSystem != 0D) { + size += 1 + 8; + } + if (TotalCpuTime != 0UL) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(TotalCpuTime); + } + if (IdleCpuTime != 0UL) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(IdleCpuTime); + } + if (CqPollCount != 0UL) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(CqPollCount); + } + if (coreStats_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(CoreStats); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ServerStats other) { + if (other == null) { + return; + } + if (other.TimeElapsed != 0D) { + TimeElapsed = other.TimeElapsed; + } + if (other.TimeUser != 0D) { + TimeUser = other.TimeUser; + } + if (other.TimeSystem != 0D) { + TimeSystem = other.TimeSystem; + } + if (other.TotalCpuTime != 0UL) { + TotalCpuTime = other.TotalCpuTime; + } + if (other.IdleCpuTime != 0UL) { + IdleCpuTime = other.IdleCpuTime; + } + if (other.CqPollCount != 0UL) { + CqPollCount = other.CqPollCount; + } + if (other.coreStats_ != null) { + if (coreStats_ == null) { + CoreStats = new global::Grpc.Core.Stats(); + } + CoreStats.MergeFrom(other.CoreStats); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 9: { + TimeElapsed = input.ReadDouble(); + break; + } + case 17: { + TimeUser = input.ReadDouble(); + break; + } + case 25: { + TimeSystem = input.ReadDouble(); + break; + } + case 32: { + TotalCpuTime = input.ReadUInt64(); + break; + } + case 40: { + IdleCpuTime = input.ReadUInt64(); + break; + } + case 48: { + CqPollCount = input.ReadUInt64(); + break; + } + case 58: { + if (coreStats_ == null) { + CoreStats = new global::Grpc.Core.Stats(); + } + input.ReadMessage(CoreStats); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 9: { + TimeElapsed = input.ReadDouble(); + break; + } + case 17: { + TimeUser = input.ReadDouble(); + break; + } + case 25: { + TimeSystem = input.ReadDouble(); + break; + } + case 32: { + TotalCpuTime = input.ReadUInt64(); + break; + } + case 40: { + IdleCpuTime = input.ReadUInt64(); + break; + } + case 48: { + CqPollCount = input.ReadUInt64(); + break; + } + case 58: { + if (coreStats_ == null) { + CoreStats = new global::Grpc.Core.Stats(); + } + input.ReadMessage(CoreStats); + break; + } + } + } + } + #endif + + } + + /// + /// Histogram params based on grpc/support/histogram.c + /// + public sealed partial class HistogramParams : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HistogramParams()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.StatsReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public HistogramParams() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public HistogramParams(HistogramParams other) : this() { + resolution_ = other.resolution_; + maxPossible_ = other.maxPossible_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public HistogramParams Clone() { + return new HistogramParams(this); + } + + /// Field number for the "resolution" field. + public const int ResolutionFieldNumber = 1; + private double resolution_; + /// + /// first bucket is [0, 1 + resolution) + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double Resolution { + get { return resolution_; } + set { + resolution_ = value; + } + } + + /// Field number for the "max_possible" field. + public const int MaxPossibleFieldNumber = 2; + private double maxPossible_; + /// + /// use enough buckets to allow this value + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double MaxPossible { + get { return maxPossible_; } + set { + maxPossible_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as HistogramParams); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(HistogramParams other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Resolution, other.Resolution)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(MaxPossible, other.MaxPossible)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Resolution != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Resolution); + if (MaxPossible != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(MaxPossible); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Resolution != 0D) { + output.WriteRawTag(9); + output.WriteDouble(Resolution); + } + if (MaxPossible != 0D) { + output.WriteRawTag(17); + output.WriteDouble(MaxPossible); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Resolution != 0D) { + output.WriteRawTag(9); + output.WriteDouble(Resolution); + } + if (MaxPossible != 0D) { + output.WriteRawTag(17); + output.WriteDouble(MaxPossible); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Resolution != 0D) { + size += 1 + 8; + } + if (MaxPossible != 0D) { + size += 1 + 8; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(HistogramParams other) { + if (other == null) { + return; + } + if (other.Resolution != 0D) { + Resolution = other.Resolution; + } + if (other.MaxPossible != 0D) { + MaxPossible = other.MaxPossible; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 9: { + Resolution = input.ReadDouble(); + break; + } + case 17: { + MaxPossible = input.ReadDouble(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 9: { + Resolution = input.ReadDouble(); + break; + } + case 17: { + MaxPossible = input.ReadDouble(); + break; + } + } + } + } + #endif + + } + + /// + /// Histogram data based on grpc/support/histogram.c + /// + public sealed partial class HistogramData : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HistogramData()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.StatsReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public HistogramData() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public HistogramData(HistogramData other) : this() { + bucket_ = other.bucket_.Clone(); + minSeen_ = other.minSeen_; + maxSeen_ = other.maxSeen_; + sum_ = other.sum_; + sumOfSquares_ = other.sumOfSquares_; + count_ = other.count_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public HistogramData Clone() { + return new HistogramData(this); + } + + /// Field number for the "bucket" field. + public const int BucketFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_bucket_codec + = pb::FieldCodec.ForUInt32(10); + private readonly pbc::RepeatedField bucket_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Bucket { + get { return bucket_; } + } + + /// Field number for the "min_seen" field. + public const int MinSeenFieldNumber = 2; + private double minSeen_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double MinSeen { + get { return minSeen_; } + set { + minSeen_ = value; + } + } + + /// Field number for the "max_seen" field. + public const int MaxSeenFieldNumber = 3; + private double maxSeen_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double MaxSeen { + get { return maxSeen_; } + set { + maxSeen_ = value; + } + } + + /// Field number for the "sum" field. + public const int SumFieldNumber = 4; + private double sum_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double Sum { + get { return sum_; } + set { + sum_ = value; + } + } + + /// Field number for the "sum_of_squares" field. + public const int SumOfSquaresFieldNumber = 5; + private double sumOfSquares_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double SumOfSquares { + get { return sumOfSquares_; } + set { + sumOfSquares_ = value; + } + } + + /// Field number for the "count" field. + public const int CountFieldNumber = 6; + private double count_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double Count { + get { return count_; } + set { + count_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as HistogramData); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(HistogramData other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!bucket_.Equals(other.bucket_)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(MinSeen, other.MinSeen)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(MaxSeen, other.MaxSeen)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Sum, other.Sum)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(SumOfSquares, other.SumOfSquares)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Count, other.Count)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + hash ^= bucket_.GetHashCode(); + if (MinSeen != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(MinSeen); + if (MaxSeen != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(MaxSeen); + if (Sum != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Sum); + if (SumOfSquares != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(SumOfSquares); + if (Count != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Count); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + bucket_.WriteTo(output, _repeated_bucket_codec); + if (MinSeen != 0D) { + output.WriteRawTag(17); + output.WriteDouble(MinSeen); + } + if (MaxSeen != 0D) { + output.WriteRawTag(25); + output.WriteDouble(MaxSeen); + } + if (Sum != 0D) { + output.WriteRawTag(33); + output.WriteDouble(Sum); + } + if (SumOfSquares != 0D) { + output.WriteRawTag(41); + output.WriteDouble(SumOfSquares); + } + if (Count != 0D) { + output.WriteRawTag(49); + output.WriteDouble(Count); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + bucket_.WriteTo(ref output, _repeated_bucket_codec); + if (MinSeen != 0D) { + output.WriteRawTag(17); + output.WriteDouble(MinSeen); + } + if (MaxSeen != 0D) { + output.WriteRawTag(25); + output.WriteDouble(MaxSeen); + } + if (Sum != 0D) { + output.WriteRawTag(33); + output.WriteDouble(Sum); + } + if (SumOfSquares != 0D) { + output.WriteRawTag(41); + output.WriteDouble(SumOfSquares); + } + if (Count != 0D) { + output.WriteRawTag(49); + output.WriteDouble(Count); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + size += bucket_.CalculateSize(_repeated_bucket_codec); + if (MinSeen != 0D) { + size += 1 + 8; + } + if (MaxSeen != 0D) { + size += 1 + 8; + } + if (Sum != 0D) { + size += 1 + 8; + } + if (SumOfSquares != 0D) { + size += 1 + 8; + } + if (Count != 0D) { + size += 1 + 8; + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(HistogramData other) { + if (other == null) { + return; + } + bucket_.Add(other.bucket_); + if (other.MinSeen != 0D) { + MinSeen = other.MinSeen; + } + if (other.MaxSeen != 0D) { + MaxSeen = other.MaxSeen; + } + if (other.Sum != 0D) { + Sum = other.Sum; + } + if (other.SumOfSquares != 0D) { + SumOfSquares = other.SumOfSquares; + } + if (other.Count != 0D) { + Count = other.Count; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: + case 8: { + bucket_.AddEntriesFrom(input, _repeated_bucket_codec); + break; + } + case 17: { + MinSeen = input.ReadDouble(); + break; + } + case 25: { + MaxSeen = input.ReadDouble(); + break; + } + case 33: { + Sum = input.ReadDouble(); + break; + } + case 41: { + SumOfSquares = input.ReadDouble(); + break; + } + case 49: { + Count = input.ReadDouble(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: + case 8: { + bucket_.AddEntriesFrom(ref input, _repeated_bucket_codec); + break; + } + case 17: { + MinSeen = input.ReadDouble(); + break; + } + case 25: { + MaxSeen = input.ReadDouble(); + break; + } + case 33: { + Sum = input.ReadDouble(); + break; + } + case 41: { + SumOfSquares = input.ReadDouble(); + break; + } + case 49: { + Count = input.ReadDouble(); + break; + } + } + } + } + #endif + + } + + public sealed partial class RequestResultCount : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RequestResultCount()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.StatsReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RequestResultCount() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RequestResultCount(RequestResultCount other) : this() { + statusCode_ = other.statusCode_; + count_ = other.count_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RequestResultCount Clone() { + return new RequestResultCount(this); + } + + /// Field number for the "status_code" field. + public const int StatusCodeFieldNumber = 1; + private int statusCode_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int StatusCode { + get { return statusCode_; } + set { + statusCode_ = value; + } + } + + /// Field number for the "count" field. + public const int CountFieldNumber = 2; + private long count_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long Count { + get { return count_; } + set { + count_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as RequestResultCount); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(RequestResultCount other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (StatusCode != other.StatusCode) return false; + if (Count != other.Count) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (StatusCode != 0) hash ^= StatusCode.GetHashCode(); + if (Count != 0L) hash ^= Count.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (StatusCode != 0) { + output.WriteRawTag(8); + output.WriteInt32(StatusCode); + } + if (Count != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Count); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (StatusCode != 0) { + output.WriteRawTag(8); + output.WriteInt32(StatusCode); + } + if (Count != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Count); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (StatusCode != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(StatusCode); + } + if (Count != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Count); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(RequestResultCount other) { + if (other == null) { + return; + } + if (other.StatusCode != 0) { + StatusCode = other.StatusCode; + } + if (other.Count != 0L) { + Count = other.Count; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + StatusCode = input.ReadInt32(); + break; + } + case 16: { + Count = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + StatusCode = input.ReadInt32(); + break; + } + case 16: { + Count = input.ReadInt64(); + break; + } + } + } + } + #endif + + } + + public sealed partial class ClientStats : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ClientStats()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.StatsReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientStats() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientStats(ClientStats other) : this() { + latencies_ = other.latencies_ != null ? other.latencies_.Clone() : null; + timeElapsed_ = other.timeElapsed_; + timeUser_ = other.timeUser_; + timeSystem_ = other.timeSystem_; + requestResults_ = other.requestResults_.Clone(); + cqPollCount_ = other.cqPollCount_; + coreStats_ = other.coreStats_ != null ? other.coreStats_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ClientStats Clone() { + return new ClientStats(this); + } + + /// Field number for the "latencies" field. + public const int LatenciesFieldNumber = 1; + private global::Grpc.Testing.HistogramData latencies_; + /// + /// Latency histogram. Data points are in nanoseconds. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Testing.HistogramData Latencies { + get { return latencies_; } + set { + latencies_ = value; + } + } + + /// Field number for the "time_elapsed" field. + public const int TimeElapsedFieldNumber = 2; + private double timeElapsed_; + /// + /// See ServerStats for details. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double TimeElapsed { + get { return timeElapsed_; } + set { + timeElapsed_ = value; + } + } + + /// Field number for the "time_user" field. + public const int TimeUserFieldNumber = 3; + private double timeUser_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double TimeUser { + get { return timeUser_; } + set { + timeUser_ = value; + } + } + + /// Field number for the "time_system" field. + public const int TimeSystemFieldNumber = 4; + private double timeSystem_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public double TimeSystem { + get { return timeSystem_; } + set { + timeSystem_ = value; + } + } + + /// Field number for the "request_results" field. + public const int RequestResultsFieldNumber = 5; + private static readonly pb::FieldCodec _repeated_requestResults_codec + = pb::FieldCodec.ForMessage(42, global::Grpc.Testing.RequestResultCount.Parser); + private readonly pbc::RepeatedField requestResults_ = new pbc::RepeatedField(); + /// + /// Number of failed requests (one row per status code seen) + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField RequestResults { + get { return requestResults_; } + } + + /// Field number for the "cq_poll_count" field. + public const int CqPollCountFieldNumber = 6; + private ulong cqPollCount_; + /// + /// Number of polls called inside completion queue + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ulong CqPollCount { + get { return cqPollCount_; } + set { + cqPollCount_ = value; + } + } + + /// Field number for the "core_stats" field. + public const int CoreStatsFieldNumber = 7; + private global::Grpc.Core.Stats coreStats_; + /// + /// Core library stats + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Core.Stats CoreStats { + get { return coreStats_; } + set { + coreStats_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ClientStats); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ClientStats other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Latencies, other.Latencies)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeElapsed, other.TimeElapsed)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeUser, other.TimeUser)) return false; + if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeSystem, other.TimeSystem)) return false; + if(!requestResults_.Equals(other.requestResults_)) return false; + if (CqPollCount != other.CqPollCount) return false; + if (!object.Equals(CoreStats, other.CoreStats)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (latencies_ != null) hash ^= Latencies.GetHashCode(); + if (TimeElapsed != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeElapsed); + if (TimeUser != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeUser); + if (TimeSystem != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeSystem); + hash ^= requestResults_.GetHashCode(); + if (CqPollCount != 0UL) hash ^= CqPollCount.GetHashCode(); + if (coreStats_ != null) hash ^= CoreStats.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (latencies_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Latencies); + } + if (TimeElapsed != 0D) { + output.WriteRawTag(17); + output.WriteDouble(TimeElapsed); + } + if (TimeUser != 0D) { + output.WriteRawTag(25); + output.WriteDouble(TimeUser); + } + if (TimeSystem != 0D) { + output.WriteRawTag(33); + output.WriteDouble(TimeSystem); + } + requestResults_.WriteTo(output, _repeated_requestResults_codec); + if (CqPollCount != 0UL) { + output.WriteRawTag(48); + output.WriteUInt64(CqPollCount); + } + if (coreStats_ != null) { + output.WriteRawTag(58); + output.WriteMessage(CoreStats); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (latencies_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Latencies); + } + if (TimeElapsed != 0D) { + output.WriteRawTag(17); + output.WriteDouble(TimeElapsed); + } + if (TimeUser != 0D) { + output.WriteRawTag(25); + output.WriteDouble(TimeUser); + } + if (TimeSystem != 0D) { + output.WriteRawTag(33); + output.WriteDouble(TimeSystem); + } + requestResults_.WriteTo(ref output, _repeated_requestResults_codec); + if (CqPollCount != 0UL) { + output.WriteRawTag(48); + output.WriteUInt64(CqPollCount); + } + if (coreStats_ != null) { + output.WriteRawTag(58); + output.WriteMessage(CoreStats); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (latencies_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Latencies); + } + if (TimeElapsed != 0D) { + size += 1 + 8; + } + if (TimeUser != 0D) { + size += 1 + 8; + } + if (TimeSystem != 0D) { + size += 1 + 8; + } + size += requestResults_.CalculateSize(_repeated_requestResults_codec); + if (CqPollCount != 0UL) { + size += 1 + pb::CodedOutputStream.ComputeUInt64Size(CqPollCount); + } + if (coreStats_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(CoreStats); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ClientStats other) { + if (other == null) { + return; + } + if (other.latencies_ != null) { + if (latencies_ == null) { + Latencies = new global::Grpc.Testing.HistogramData(); + } + Latencies.MergeFrom(other.Latencies); + } + if (other.TimeElapsed != 0D) { + TimeElapsed = other.TimeElapsed; + } + if (other.TimeUser != 0D) { + TimeUser = other.TimeUser; + } + if (other.TimeSystem != 0D) { + TimeSystem = other.TimeSystem; + } + requestResults_.Add(other.requestResults_); + if (other.CqPollCount != 0UL) { + CqPollCount = other.CqPollCount; + } + if (other.coreStats_ != null) { + if (coreStats_ == null) { + CoreStats = new global::Grpc.Core.Stats(); + } + CoreStats.MergeFrom(other.CoreStats); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (latencies_ == null) { + Latencies = new global::Grpc.Testing.HistogramData(); + } + input.ReadMessage(Latencies); + break; + } + case 17: { + TimeElapsed = input.ReadDouble(); + break; + } + case 25: { + TimeUser = input.ReadDouble(); + break; + } + case 33: { + TimeSystem = input.ReadDouble(); + break; + } + case 42: { + requestResults_.AddEntriesFrom(input, _repeated_requestResults_codec); + break; + } + case 48: { + CqPollCount = input.ReadUInt64(); + break; + } + case 58: { + if (coreStats_ == null) { + CoreStats = new global::Grpc.Core.Stats(); + } + input.ReadMessage(CoreStats); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (latencies_ == null) { + Latencies = new global::Grpc.Testing.HistogramData(); + } + input.ReadMessage(Latencies); + break; + } + case 17: { + TimeElapsed = input.ReadDouble(); + break; + } + case 25: { + TimeUser = input.ReadDouble(); + break; + } + case 33: { + TimeSystem = input.ReadDouble(); + break; + } + case 42: { + requestResults_.AddEntriesFrom(ref input, _repeated_requestResults_codec); + break; + } + case 48: { + CqPollCount = input.ReadUInt64(); + break; + } + case 58: { + if (coreStats_ == null) { + CoreStats = new global::Grpc.Core.Stats(); + } + input.ReadMessage(CoreStats); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs b/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs new file mode 100644 index 00000000..0c623807 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs @@ -0,0 +1,289 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using CommandLine; +using CommandLine.Text; +using Grpc.Core; +using Grpc.Core.Logging; +using Grpc.Core.Utils; +using Grpc.Testing; + +namespace Grpc.IntegrationTesting +{ + public class StressTestClient + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + const double SecondsToNanos = 1e9; + + private class ClientOptions + { + [Option("server_addresses", Default = "localhost:8080")] + public string ServerAddresses { get; set; } + + [Option("test_cases", Default = "large_unary:100")] + public string TestCases { get; set; } + + [Option("test_duration_secs", Default = -1)] + public int TestDurationSecs { get; set; } + + [Option("num_channels_per_server", Default = 1)] + public int NumChannelsPerServer { get; set; } + + [Option("num_stubs_per_channel", Default = 1)] + public int NumStubsPerChannel { get; set; } + + [Option("metrics_port", Default = 8081)] + public int MetricsPort { get; set; } + } + + ClientOptions options; + List serverAddresses; + Dictionary weightedTestCases; + WeightedRandomGenerator testCaseGenerator; + + // cancellation will be emitted once test_duration_secs has elapsed. + CancellationTokenSource finishedTokenSource = new CancellationTokenSource(); + Histogram histogram = new Histogram(0.01, 60 * SecondsToNanos); + + private StressTestClient(ClientOptions options, List serverAddresses, Dictionary weightedTestCases) + { + this.options = options; + this.serverAddresses = serverAddresses; + this.weightedTestCases = weightedTestCases; + this.testCaseGenerator = new WeightedRandomGenerator(this.weightedTestCases); + } + + public static void Run(string[] args) + { + GrpcEnvironment.SetLogger(new ConsoleLogger()); + var parserResult = Parser.Default.ParseArguments(args) + .WithNotParsed((x) => Environment.Exit(1)) + .WithParsed(options => { + GrpcPreconditions.CheckArgument(options.NumChannelsPerServer > 0); + GrpcPreconditions.CheckArgument(options.NumStubsPerChannel > 0); + + var serverAddresses = options.ServerAddresses.Split(','); + GrpcPreconditions.CheckArgument(serverAddresses.Length > 0, "You need to provide at least one server address"); + + var testCases = ParseWeightedTestCases(options.TestCases); + GrpcPreconditions.CheckArgument(testCases.Count > 0, "You need to provide at least one test case"); + + var interopClient = new StressTestClient(options, serverAddresses.ToList(), testCases); + interopClient.Run().Wait(); + }); + } + + async Task Run() + { + var metricsServer = new Server() + { + Services = { MetricsService.BindService(new MetricsServiceImpl(histogram)) }, + Ports = { { "[::]", options.MetricsPort, ServerCredentials.Insecure } } + }; + metricsServer.Start(); + + if (options.TestDurationSecs >= 0) + { + finishedTokenSource.CancelAfter(TimeSpan.FromSeconds(options.TestDurationSecs)); + } + + var tasks = new List(); + var channels = new List(); + foreach (var serverAddress in serverAddresses) + { + for (int i = 0; i < options.NumChannelsPerServer; i++) + { + var channel = new Channel(serverAddress, ChannelCredentials.Insecure); + channels.Add(channel); + for (int j = 0; j < options.NumStubsPerChannel; j++) + { + var client = new TestService.TestServiceClient(channel); + var task = Task.Factory.StartNew(() => RunBodyAsync(client).GetAwaiter().GetResult(), + TaskCreationOptions.LongRunning); + tasks.Add(task); + } + } + } + await Task.WhenAll(tasks); + + foreach (var channel in channels) + { + await channel.ShutdownAsync(); + } + + await metricsServer.ShutdownAsync(); + } + + async Task RunBodyAsync(TestService.TestServiceClient client) + { + Logger.Info("Starting stress test client thread."); + while (!finishedTokenSource.Token.IsCancellationRequested) + { + var testCase = testCaseGenerator.GetNext(); + + var stopwatch = Stopwatch.StartNew(); + + await RunTestCaseAsync(client, testCase); + + stopwatch.Stop(); + histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos); + } + Logger.Info("Stress test client thread finished."); + } + + async Task RunTestCaseAsync(TestService.TestServiceClient client, string testCase) + { + switch (testCase) + { + case "empty_unary": + InteropClient.RunEmptyUnary(client); + break; + case "large_unary": + InteropClient.RunLargeUnary(client); + break; + case "client_streaming": + await InteropClient.RunClientStreamingAsync(client); + break; + case "server_streaming": + await InteropClient.RunServerStreamingAsync(client); + break; + case "ping_pong": + await InteropClient.RunPingPongAsync(client); + break; + case "empty_stream": + await InteropClient.RunEmptyStreamAsync(client); + break; + case "cancel_after_begin": + await InteropClient.RunCancelAfterBeginAsync(client); + break; + case "cancel_after_first_response": + await InteropClient.RunCancelAfterFirstResponseAsync(client); + break; + case "timeout_on_sleeping_server": + await InteropClient.RunTimeoutOnSleepingServerAsync(client); + break; + case "custom_metadata": + await InteropClient.RunCustomMetadataAsync(client); + break; + case "status_code_and_message": + await InteropClient.RunStatusCodeAndMessageAsync(client); + break; + default: + throw new ArgumentException("Unsupported test case " + testCase); + } + } + + static Dictionary ParseWeightedTestCases(string weightedTestCases) + { + var result = new Dictionary(); + foreach (var weightedTestCase in weightedTestCases.Split(',')) + { + var parts = weightedTestCase.Split(new char[] {':'}, 2); + GrpcPreconditions.CheckArgument(parts.Length == 2, "Malformed test_cases option."); + result.Add(parts[0], int.Parse(parts[1])); + } + return result; + } + + class WeightedRandomGenerator + { + readonly Random random = new Random(); + readonly List> cumulativeSums; + readonly int weightSum; + + public WeightedRandomGenerator(Dictionary weightedItems) + { + cumulativeSums = new List>(); + weightSum = 0; + foreach (var entry in weightedItems) + { + weightSum += entry.Value; + cumulativeSums.Add(Tuple.Create(weightSum, entry.Key)); + } + } + + public string GetNext() + { + int rand = random.Next(weightSum); + foreach (var entry in cumulativeSums) + { + if (rand < entry.Item1) + { + return entry.Item2; + } + } + throw new InvalidOperationException("GetNext() failed."); + } + } + + class MetricsServiceImpl : MetricsService.MetricsServiceBase + { + const string GaugeName = "csharp_overall_qps"; + + readonly Histogram histogram; + readonly TimeStats timeStats = new TimeStats(); + + public MetricsServiceImpl(Histogram histogram) + { + this.histogram = histogram; + } + + public override Task GetGauge(GaugeRequest request, ServerCallContext context) + { + if (request.Name == GaugeName) + { + long qps = GetQpsAndReset(); + + return Task.FromResult(new GaugeResponse + { + Name = GaugeName, + LongValue = qps + }); + } + throw new RpcException(new Status(StatusCode.InvalidArgument, "Gauge does not exist")); + } + + public override async Task GetAllGauges(EmptyMessage request, IServerStreamWriter responseStream, ServerCallContext context) + { + long qps = GetQpsAndReset(); + + var response = new GaugeResponse + { + Name = GaugeName, + LongValue = qps + }; + await responseStream.WriteAsync(response); + } + + long GetQpsAndReset() + { + var snapshot = histogram.GetSnapshot(true); + var timeSnapshot = timeStats.GetSnapshot(true); + + return (long) (snapshot.Count / timeSnapshot.WallClockTime.TotalSeconds); + } + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/Test.cs b/src/csharp/Grpc.IntegrationTesting/Test.cs new file mode 100644 index 00000000..f82862a5 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/Test.cs @@ -0,0 +1,72 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/test.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Testing { + + /// Holder for reflection information generated from src/proto/grpc/testing/test.proto + public static partial class TestReflection { + + #region Descriptor + /// File descriptor for src/proto/grpc/testing/test.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static TestReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CiFzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3Rlc3QucHJvdG8SDGdycGMudGVz", + "dGluZxoic3JjL3Byb3RvL2dycGMvdGVzdGluZy9lbXB0eS5wcm90bxolc3Jj", + "L3Byb3RvL2dycGMvdGVzdGluZy9tZXNzYWdlcy5wcm90bzLLBQoLVGVzdFNl", + "cnZpY2USNQoJRW1wdHlDYWxsEhMuZ3JwYy50ZXN0aW5nLkVtcHR5GhMuZ3Jw", + "Yy50ZXN0aW5nLkVtcHR5EkYKCVVuYXJ5Q2FsbBIbLmdycGMudGVzdGluZy5T", + "aW1wbGVSZXF1ZXN0GhwuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlc3BvbnNlEk8K", + "EkNhY2hlYWJsZVVuYXJ5Q2FsbBIbLmdycGMudGVzdGluZy5TaW1wbGVSZXF1", + "ZXN0GhwuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlc3BvbnNlEmwKE1N0cmVhbWlu", + "Z091dHB1dENhbGwSKC5ncnBjLnRlc3RpbmcuU3RyZWFtaW5nT3V0cHV0Q2Fs", + "bFJlcXVlc3QaKS5ncnBjLnRlc3RpbmcuU3RyZWFtaW5nT3V0cHV0Q2FsbFJl", + "c3BvbnNlMAESaQoSU3RyZWFtaW5nSW5wdXRDYWxsEicuZ3JwYy50ZXN0aW5n", + "LlN0cmVhbWluZ0lucHV0Q2FsbFJlcXVlc3QaKC5ncnBjLnRlc3RpbmcuU3Ry", + "ZWFtaW5nSW5wdXRDYWxsUmVzcG9uc2UoARJpCg5GdWxsRHVwbGV4Q2FsbBIo", + "LmdycGMudGVzdGluZy5TdHJlYW1pbmdPdXRwdXRDYWxsUmVxdWVzdBopLmdy", + "cGMudGVzdGluZy5TdHJlYW1pbmdPdXRwdXRDYWxsUmVzcG9uc2UoATABEmkK", + "DkhhbGZEdXBsZXhDYWxsEiguZ3JwYy50ZXN0aW5nLlN0cmVhbWluZ091dHB1", + "dENhbGxSZXF1ZXN0GikuZ3JwYy50ZXN0aW5nLlN0cmVhbWluZ091dHB1dENh", + "bGxSZXNwb25zZSgBMAESPQoRVW5pbXBsZW1lbnRlZENhbGwSEy5ncnBjLnRl", + "c3RpbmcuRW1wdHkaEy5ncnBjLnRlc3RpbmcuRW1wdHkyVQoUVW5pbXBsZW1l", + "bnRlZFNlcnZpY2USPQoRVW5pbXBsZW1lbnRlZENhbGwSEy5ncnBjLnRlc3Rp", + "bmcuRW1wdHkaEy5ncnBjLnRlc3RpbmcuRW1wdHkyiQEKEFJlY29ubmVjdFNl", + "cnZpY2USOwoFU3RhcnQSHS5ncnBjLnRlc3RpbmcuUmVjb25uZWN0UGFyYW1z", + "GhMuZ3JwYy50ZXN0aW5nLkVtcHR5EjgKBFN0b3ASEy5ncnBjLnRlc3Rpbmcu", + "RW1wdHkaGy5ncnBjLnRlc3RpbmcuUmVjb25uZWN0SW5mbzKGAgoYTG9hZEJh", + "bGFuY2VyU3RhdHNTZXJ2aWNlEmMKDkdldENsaWVudFN0YXRzEiYuZ3JwYy50", + "ZXN0aW5nLkxvYWRCYWxhbmNlclN0YXRzUmVxdWVzdBonLmdycGMudGVzdGlu", + "Zy5Mb2FkQmFsYW5jZXJTdGF0c1Jlc3BvbnNlIgAShAEKGUdldENsaWVudEFj", + "Y3VtdWxhdGVkU3RhdHMSMS5ncnBjLnRlc3RpbmcuTG9hZEJhbGFuY2VyQWNj", + "dW11bGF0ZWRTdGF0c1JlcXVlc3QaMi5ncnBjLnRlc3RpbmcuTG9hZEJhbGFu", + "Y2VyQWNjdW11bGF0ZWRTdGF0c1Jlc3BvbnNlIgAyiwEKFlhkc1VwZGF0ZUhl", + "YWx0aFNlcnZpY2USNgoKU2V0U2VydmluZxITLmdycGMudGVzdGluZy5FbXB0", + "eRoTLmdycGMudGVzdGluZy5FbXB0eRI5Cg1TZXROb3RTZXJ2aW5nEhMuZ3Jw", + "Yy50ZXN0aW5nLkVtcHR5GhMuZ3JwYy50ZXN0aW5nLkVtcHR5MnsKH1hkc1Vw", + "ZGF0ZUNsaWVudENvbmZpZ3VyZVNlcnZpY2USWAoJQ29uZmlndXJlEiQuZ3Jw", + "Yy50ZXN0aW5nLkNsaWVudENvbmZpZ3VyZVJlcXVlc3QaJS5ncnBjLnRlc3Rp", + "bmcuQ2xpZW50Q29uZmlndXJlUmVzcG9uc2ViBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Grpc.Testing.EmptyReflection.Descriptor, global::Grpc.Testing.MessagesReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, null, null)); + } + #endregion + + } +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs new file mode 100644 index 00000000..7837e957 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs @@ -0,0 +1,82 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + /// + /// SSL Credentials for testing. + /// + public static class TestCredentials + { + public const string DefaultHostOverride = "foo.test.google.fr"; + + public static string ClientCertAuthorityPath + { + get + { + return GetPath("data/ca.pem"); + } + } + + public static string ServerCertChainPath + { + get + { + return GetPath("data/server1.pem"); + } + } + + public static string ServerPrivateKeyPath + { + get + { + return GetPath("data/server1.key"); + } + } + + public static SslCredentials CreateSslCredentials() + { + return new SslCredentials(File.ReadAllText(ClientCertAuthorityPath)); + } + + public static SslServerCredentials CreateSslServerCredentials() + { + var keyCertPair = new KeyCertificatePair( + File.ReadAllText(ServerCertChainPath), + File.ReadAllText(ServerPrivateKeyPath)); + return new SslServerCredentials(new[] { keyCertPair }); + } + + private static string GetPath(string relativePath) + { + var assemblyDir = Path.GetDirectoryName(typeof(TestCredentials).GetTypeInfo().Assembly.Location); + return Path.Combine(assemblyDir, relativePath); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs new file mode 100644 index 00000000..4887c671 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -0,0 +1,1625 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/test.proto +// +// Original file comments: +// Copyright 2015-2016 gRPC authors. +// +// 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. +// +// An integration test service that covers all the method signature permutations +// of unary/streaming requests/responses. +// +#pragma warning disable 0414, 1591 +#region Designer generated code + +using grpc = global::Grpc.Core; + +namespace Grpc.Testing { + /// + /// A simple service to test the various types of RPCs and experiment with + /// performance with various types of payload. + /// + public static partial class TestService + { + static readonly string __ServiceName = "grpc.testing.TestService"; + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context) + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (message is global::Google.Protobuf.IBufferMessage) + { + context.SetPayloadLength(message.CalculateSize()); + global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter()); + context.Complete(); + return; + } + #endif + context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static class __Helper_MessageCache + { + public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static T __Helper_DeserializeMessage(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser parser) where T : global::Google.Protobuf.IMessage + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (__Helper_MessageCache.IsBufferMessage) + { + return parser.ParseFrom(context.PayloadAsReadOnlySequence()); + } + #endif + return parser.ParseFrom(context.PayloadAsNewBuffer()); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_Empty = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.Empty.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_SimpleRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.SimpleRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_SimpleResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.SimpleResponse.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_StreamingOutputCallRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.StreamingOutputCallRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_StreamingOutputCallResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.StreamingOutputCallResponse.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_StreamingInputCallRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.StreamingInputCallRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_StreamingInputCallResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.StreamingInputCallResponse.Parser)); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_EmptyCall = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "EmptyCall", + __Marshaller_grpc_testing_Empty, + __Marshaller_grpc_testing_Empty); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_UnaryCall = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "UnaryCall", + __Marshaller_grpc_testing_SimpleRequest, + __Marshaller_grpc_testing_SimpleResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_CacheableUnaryCall = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "CacheableUnaryCall", + __Marshaller_grpc_testing_SimpleRequest, + __Marshaller_grpc_testing_SimpleResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_StreamingOutputCall = new grpc::Method( + grpc::MethodType.ServerStreaming, + __ServiceName, + "StreamingOutputCall", + __Marshaller_grpc_testing_StreamingOutputCallRequest, + __Marshaller_grpc_testing_StreamingOutputCallResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_StreamingInputCall = new grpc::Method( + grpc::MethodType.ClientStreaming, + __ServiceName, + "StreamingInputCall", + __Marshaller_grpc_testing_StreamingInputCallRequest, + __Marshaller_grpc_testing_StreamingInputCallResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_FullDuplexCall = new grpc::Method( + grpc::MethodType.DuplexStreaming, + __ServiceName, + "FullDuplexCall", + __Marshaller_grpc_testing_StreamingOutputCallRequest, + __Marshaller_grpc_testing_StreamingOutputCallResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_HalfDuplexCall = new grpc::Method( + grpc::MethodType.DuplexStreaming, + __ServiceName, + "HalfDuplexCall", + __Marshaller_grpc_testing_StreamingOutputCallRequest, + __Marshaller_grpc_testing_StreamingOutputCallResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_UnimplementedCall = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "UnimplementedCall", + __Marshaller_grpc_testing_Empty, + __Marshaller_grpc_testing_Empty); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Testing.TestReflection.Descriptor.Services[0]; } + } + + /// Base class for server-side implementations of TestService + [grpc::BindServiceMethod(typeof(TestService), "BindService")] + public abstract partial class TestServiceBase + { + /// + /// One empty request followed by one empty response. + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task EmptyCall(global::Grpc.Testing.Empty request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// One request followed by one response. + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// One request followed by one response. Response has cache control + /// headers set such that a caching HTTP proxy (such as GFE) can + /// satisfy subsequent requests. + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task CacheableUnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// One request followed by a sequence of responses (streamed download). + /// The server returns the payload with client desired type and sizes. + /// + /// The request received from the client. + /// Used for sending responses back to the client. + /// The context of the server-side call handler being invoked. + /// A task indicating completion of the handler. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// A sequence of requests followed by one response (streamed upload). + /// The server returns the aggregated size of client payload as the result. + /// + /// Used for reading requests from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task StreamingInputCall(grpc::IAsyncStreamReader requestStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// A sequence of requests with each request served by the server immediately. + /// As one request could lead to multiple responses, this interface + /// demonstrates the idea of full duplexing. + /// + /// Used for reading requests from the client. + /// Used for sending responses back to the client. + /// The context of the server-side call handler being invoked. + /// A task indicating completion of the handler. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task FullDuplexCall(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// A sequence of requests followed by a sequence of responses. + /// The server buffers all the client requests and then serves them in order. A + /// stream of responses are returned to the client when the server starts with + /// first request. + /// + /// Used for reading requests from the client. + /// Used for sending responses back to the client. + /// The context of the server-side call handler being invoked. + /// A task indicating completion of the handler. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task HalfDuplexCall(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// The test server will not implement this method. It will be used + /// to test the behavior when clients call unimplemented methods. + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task UnimplementedCall(global::Grpc.Testing.Empty request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for TestService + public partial class TestServiceClient : grpc::ClientBase + { + /// Creates a new client for TestService + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public TestServiceClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for TestService that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public TestServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected TestServiceClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected TestServiceClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// One empty request followed by one empty response. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return EmptyCall(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// One empty request followed by one empty response. + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_EmptyCall, null, options, request); + } + /// + /// One empty request followed by one empty response. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall EmptyCallAsync(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return EmptyCallAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// One empty request followed by one empty response. + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall EmptyCallAsync(global::Grpc.Testing.Empty request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_EmptyCall, null, options, request); + } + /// + /// One request followed by one response. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return UnaryCall(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// One request followed by one response. + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request); + } + /// + /// One request followed by one response. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return UnaryCallAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// One request followed by one response. + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request); + } + /// + /// One request followed by one response. Response has cache control + /// headers set such that a caching HTTP proxy (such as GFE) can + /// satisfy subsequent requests. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.SimpleResponse CacheableUnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return CacheableUnaryCall(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// One request followed by one response. Response has cache control + /// headers set such that a caching HTTP proxy (such as GFE) can + /// satisfy subsequent requests. + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.SimpleResponse CacheableUnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_CacheableUnaryCall, null, options, request); + } + /// + /// One request followed by one response. Response has cache control + /// headers set such that a caching HTTP proxy (such as GFE) can + /// satisfy subsequent requests. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CacheableUnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return CacheableUnaryCallAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// One request followed by one response. Response has cache control + /// headers set such that a caching HTTP proxy (such as GFE) can + /// satisfy subsequent requests. + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CacheableUnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_CacheableUnaryCall, null, options, request); + } + /// + /// One request followed by a sequence of responses (streamed download). + /// The server returns the payload with client desired type and sizes. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncServerStreamingCall StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return StreamingOutputCall(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// One request followed by a sequence of responses (streamed download). + /// The server returns the payload with client desired type and sizes. + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncServerStreamingCall StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncServerStreamingCall(__Method_StreamingOutputCall, null, options, request); + } + /// + /// A sequence of requests followed by one response (streamed upload). + /// The server returns the aggregated size of client payload as the result. + /// + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncClientStreamingCall StreamingInputCall(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return StreamingInputCall(new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// A sequence of requests followed by one response (streamed upload). + /// The server returns the aggregated size of client payload as the result. + /// + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncClientStreamingCall StreamingInputCall(grpc::CallOptions options) + { + return CallInvoker.AsyncClientStreamingCall(__Method_StreamingInputCall, null, options); + } + /// + /// A sequence of requests with each request served by the server immediately. + /// As one request could lead to multiple responses, this interface + /// demonstrates the idea of full duplexing. + /// + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall FullDuplexCall(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return FullDuplexCall(new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// A sequence of requests with each request served by the server immediately. + /// As one request could lead to multiple responses, this interface + /// demonstrates the idea of full duplexing. + /// + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall FullDuplexCall(grpc::CallOptions options) + { + return CallInvoker.AsyncDuplexStreamingCall(__Method_FullDuplexCall, null, options); + } + /// + /// A sequence of requests followed by a sequence of responses. + /// The server buffers all the client requests and then serves them in order. A + /// stream of responses are returned to the client when the server starts with + /// first request. + /// + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall HalfDuplexCall(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return HalfDuplexCall(new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// A sequence of requests followed by a sequence of responses. + /// The server buffers all the client requests and then serves them in order. A + /// stream of responses are returned to the client when the server starts with + /// first request. + /// + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall HalfDuplexCall(grpc::CallOptions options) + { + return CallInvoker.AsyncDuplexStreamingCall(__Method_HalfDuplexCall, null, options); + } + /// + /// The test server will not implement this method. It will be used + /// to test the behavior when clients call unimplemented methods. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return UnimplementedCall(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// The test server will not implement this method. It will be used + /// to test the behavior when clients call unimplemented methods. + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_UnimplementedCall, null, options, request); + } + /// + /// The test server will not implement this method. It will be used + /// to test the behavior when clients call unimplemented methods. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall UnimplementedCallAsync(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return UnimplementedCallAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// The test server will not implement this method. It will be used + /// to test the behavior when clients call unimplemented methods. + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall UnimplementedCallAsync(global::Grpc.Testing.Empty request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_UnimplementedCall, null, options, request); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override TestServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new TestServiceClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static grpc::ServerServiceDefinition BindService(TestServiceBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall) + .AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall) + .AddMethod(__Method_CacheableUnaryCall, serviceImpl.CacheableUnaryCall) + .AddMethod(__Method_StreamingOutputCall, serviceImpl.StreamingOutputCall) + .AddMethod(__Method_StreamingInputCall, serviceImpl.StreamingInputCall) + .AddMethod(__Method_FullDuplexCall, serviceImpl.FullDuplexCall) + .AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall) + .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build(); + } + + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static void BindService(grpc::ServiceBinderBase serviceBinder, TestServiceBase serviceImpl) + { + serviceBinder.AddMethod(__Method_EmptyCall, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.EmptyCall)); + serviceBinder.AddMethod(__Method_UnaryCall, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.UnaryCall)); + serviceBinder.AddMethod(__Method_CacheableUnaryCall, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.CacheableUnaryCall)); + serviceBinder.AddMethod(__Method_StreamingOutputCall, serviceImpl == null ? null : new grpc::ServerStreamingServerMethod(serviceImpl.StreamingOutputCall)); + serviceBinder.AddMethod(__Method_StreamingInputCall, serviceImpl == null ? null : new grpc::ClientStreamingServerMethod(serviceImpl.StreamingInputCall)); + serviceBinder.AddMethod(__Method_FullDuplexCall, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.FullDuplexCall)); + serviceBinder.AddMethod(__Method_HalfDuplexCall, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.HalfDuplexCall)); + serviceBinder.AddMethod(__Method_UnimplementedCall, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.UnimplementedCall)); + } + + } + /// + /// A simple service NOT implemented at servers so clients can test for + /// that case. + /// + public static partial class UnimplementedService + { + static readonly string __ServiceName = "grpc.testing.UnimplementedService"; + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context) + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (message is global::Google.Protobuf.IBufferMessage) + { + context.SetPayloadLength(message.CalculateSize()); + global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter()); + context.Complete(); + return; + } + #endif + context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static class __Helper_MessageCache + { + public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static T __Helper_DeserializeMessage(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser parser) where T : global::Google.Protobuf.IMessage + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (__Helper_MessageCache.IsBufferMessage) + { + return parser.ParseFrom(context.PayloadAsReadOnlySequence()); + } + #endif + return parser.ParseFrom(context.PayloadAsNewBuffer()); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_Empty = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.Empty.Parser)); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_UnimplementedCall = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "UnimplementedCall", + __Marshaller_grpc_testing_Empty, + __Marshaller_grpc_testing_Empty); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Testing.TestReflection.Descriptor.Services[1]; } + } + + /// Base class for server-side implementations of UnimplementedService + [grpc::BindServiceMethod(typeof(UnimplementedService), "BindService")] + public abstract partial class UnimplementedServiceBase + { + /// + /// A call that no server should implement + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task UnimplementedCall(global::Grpc.Testing.Empty request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for UnimplementedService + public partial class UnimplementedServiceClient : grpc::ClientBase + { + /// Creates a new client for UnimplementedService + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public UnimplementedServiceClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for UnimplementedService that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public UnimplementedServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected UnimplementedServiceClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected UnimplementedServiceClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// A call that no server should implement + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return UnimplementedCall(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// A call that no server should implement + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_UnimplementedCall, null, options, request); + } + /// + /// A call that no server should implement + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall UnimplementedCallAsync(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return UnimplementedCallAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// A call that no server should implement + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall UnimplementedCallAsync(global::Grpc.Testing.Empty request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_UnimplementedCall, null, options, request); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override UnimplementedServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new UnimplementedServiceClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static grpc::ServerServiceDefinition BindService(UnimplementedServiceBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build(); + } + + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static void BindService(grpc::ServiceBinderBase serviceBinder, UnimplementedServiceBase serviceImpl) + { + serviceBinder.AddMethod(__Method_UnimplementedCall, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.UnimplementedCall)); + } + + } + /// + /// A service used to control reconnect server. + /// + public static partial class ReconnectService + { + static readonly string __ServiceName = "grpc.testing.ReconnectService"; + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context) + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (message is global::Google.Protobuf.IBufferMessage) + { + context.SetPayloadLength(message.CalculateSize()); + global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter()); + context.Complete(); + return; + } + #endif + context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static class __Helper_MessageCache + { + public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static T __Helper_DeserializeMessage(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser parser) where T : global::Google.Protobuf.IMessage + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (__Helper_MessageCache.IsBufferMessage) + { + return parser.ParseFrom(context.PayloadAsReadOnlySequence()); + } + #endif + return parser.ParseFrom(context.PayloadAsNewBuffer()); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_ReconnectParams = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.ReconnectParams.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_Empty = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.Empty.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_ReconnectInfo = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.ReconnectInfo.Parser)); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_Start = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "Start", + __Marshaller_grpc_testing_ReconnectParams, + __Marshaller_grpc_testing_Empty); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_Stop = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "Stop", + __Marshaller_grpc_testing_Empty, + __Marshaller_grpc_testing_ReconnectInfo); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Testing.TestReflection.Descriptor.Services[2]; } + } + + /// Base class for server-side implementations of ReconnectService + [grpc::BindServiceMethod(typeof(ReconnectService), "BindService")] + public abstract partial class ReconnectServiceBase + { + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task Start(global::Grpc.Testing.ReconnectParams request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task Stop(global::Grpc.Testing.Empty request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for ReconnectService + public partial class ReconnectServiceClient : grpc::ClientBase + { + /// Creates a new client for ReconnectService + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public ReconnectServiceClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for ReconnectService that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public ReconnectServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected ReconnectServiceClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected ReconnectServiceClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Empty Start(global::Grpc.Testing.ReconnectParams request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return Start(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Empty Start(global::Grpc.Testing.ReconnectParams request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_Start, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall StartAsync(global::Grpc.Testing.ReconnectParams request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return StartAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall StartAsync(global::Grpc.Testing.ReconnectParams request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_Start, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return Stop(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_Stop, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall StopAsync(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return StopAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall StopAsync(global::Grpc.Testing.Empty request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_Stop, null, options, request); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override ReconnectServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new ReconnectServiceClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static grpc::ServerServiceDefinition BindService(ReconnectServiceBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_Start, serviceImpl.Start) + .AddMethod(__Method_Stop, serviceImpl.Stop).Build(); + } + + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static void BindService(grpc::ServiceBinderBase serviceBinder, ReconnectServiceBase serviceImpl) + { + serviceBinder.AddMethod(__Method_Start, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.Start)); + serviceBinder.AddMethod(__Method_Stop, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.Stop)); + } + + } + /// + /// A service used to obtain stats for verifying LB behavior. + /// + public static partial class LoadBalancerStatsService + { + static readonly string __ServiceName = "grpc.testing.LoadBalancerStatsService"; + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context) + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (message is global::Google.Protobuf.IBufferMessage) + { + context.SetPayloadLength(message.CalculateSize()); + global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter()); + context.Complete(); + return; + } + #endif + context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static class __Helper_MessageCache + { + public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static T __Helper_DeserializeMessage(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser parser) where T : global::Google.Protobuf.IMessage + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (__Helper_MessageCache.IsBufferMessage) + { + return parser.ParseFrom(context.PayloadAsReadOnlySequence()); + } + #endif + return parser.ParseFrom(context.PayloadAsNewBuffer()); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_LoadBalancerStatsRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.LoadBalancerStatsRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_LoadBalancerStatsResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.LoadBalancerStatsResponse.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_LoadBalancerAccumulatedStatsRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.LoadBalancerAccumulatedStatsRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_LoadBalancerAccumulatedStatsResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.LoadBalancerAccumulatedStatsResponse.Parser)); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_GetClientStats = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "GetClientStats", + __Marshaller_grpc_testing_LoadBalancerStatsRequest, + __Marshaller_grpc_testing_LoadBalancerStatsResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_GetClientAccumulatedStats = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "GetClientAccumulatedStats", + __Marshaller_grpc_testing_LoadBalancerAccumulatedStatsRequest, + __Marshaller_grpc_testing_LoadBalancerAccumulatedStatsResponse); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Testing.TestReflection.Descriptor.Services[3]; } + } + + /// Base class for server-side implementations of LoadBalancerStatsService + [grpc::BindServiceMethod(typeof(LoadBalancerStatsService), "BindService")] + public abstract partial class LoadBalancerStatsServiceBase + { + /// + /// Gets the backend distribution for RPCs sent by a test client. + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task GetClientStats(global::Grpc.Testing.LoadBalancerStatsRequest request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// Gets the accumulated stats for RPCs sent by a test client. + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task GetClientAccumulatedStats(global::Grpc.Testing.LoadBalancerAccumulatedStatsRequest request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for LoadBalancerStatsService + public partial class LoadBalancerStatsServiceClient : grpc::ClientBase + { + /// Creates a new client for LoadBalancerStatsService + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public LoadBalancerStatsServiceClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for LoadBalancerStatsService that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public LoadBalancerStatsServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected LoadBalancerStatsServiceClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected LoadBalancerStatsServiceClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// Gets the backend distribution for RPCs sent by a test client. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.LoadBalancerStatsResponse GetClientStats(global::Grpc.Testing.LoadBalancerStatsRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return GetClientStats(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Gets the backend distribution for RPCs sent by a test client. + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.LoadBalancerStatsResponse GetClientStats(global::Grpc.Testing.LoadBalancerStatsRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_GetClientStats, null, options, request); + } + /// + /// Gets the backend distribution for RPCs sent by a test client. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall GetClientStatsAsync(global::Grpc.Testing.LoadBalancerStatsRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return GetClientStatsAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Gets the backend distribution for RPCs sent by a test client. + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall GetClientStatsAsync(global::Grpc.Testing.LoadBalancerStatsRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_GetClientStats, null, options, request); + } + /// + /// Gets the accumulated stats for RPCs sent by a test client. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.LoadBalancerAccumulatedStatsResponse GetClientAccumulatedStats(global::Grpc.Testing.LoadBalancerAccumulatedStatsRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return GetClientAccumulatedStats(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Gets the accumulated stats for RPCs sent by a test client. + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.LoadBalancerAccumulatedStatsResponse GetClientAccumulatedStats(global::Grpc.Testing.LoadBalancerAccumulatedStatsRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_GetClientAccumulatedStats, null, options, request); + } + /// + /// Gets the accumulated stats for RPCs sent by a test client. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall GetClientAccumulatedStatsAsync(global::Grpc.Testing.LoadBalancerAccumulatedStatsRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return GetClientAccumulatedStatsAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Gets the accumulated stats for RPCs sent by a test client. + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall GetClientAccumulatedStatsAsync(global::Grpc.Testing.LoadBalancerAccumulatedStatsRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_GetClientAccumulatedStats, null, options, request); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override LoadBalancerStatsServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new LoadBalancerStatsServiceClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static grpc::ServerServiceDefinition BindService(LoadBalancerStatsServiceBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_GetClientStats, serviceImpl.GetClientStats) + .AddMethod(__Method_GetClientAccumulatedStats, serviceImpl.GetClientAccumulatedStats).Build(); + } + + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static void BindService(grpc::ServiceBinderBase serviceBinder, LoadBalancerStatsServiceBase serviceImpl) + { + serviceBinder.AddMethod(__Method_GetClientStats, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.GetClientStats)); + serviceBinder.AddMethod(__Method_GetClientAccumulatedStats, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.GetClientAccumulatedStats)); + } + + } + /// + /// A service to remotely control health status of an xDS test server. + /// + public static partial class XdsUpdateHealthService + { + static readonly string __ServiceName = "grpc.testing.XdsUpdateHealthService"; + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context) + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (message is global::Google.Protobuf.IBufferMessage) + { + context.SetPayloadLength(message.CalculateSize()); + global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter()); + context.Complete(); + return; + } + #endif + context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static class __Helper_MessageCache + { + public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static T __Helper_DeserializeMessage(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser parser) where T : global::Google.Protobuf.IMessage + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (__Helper_MessageCache.IsBufferMessage) + { + return parser.ParseFrom(context.PayloadAsReadOnlySequence()); + } + #endif + return parser.ParseFrom(context.PayloadAsNewBuffer()); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_Empty = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.Empty.Parser)); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_SetServing = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "SetServing", + __Marshaller_grpc_testing_Empty, + __Marshaller_grpc_testing_Empty); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_SetNotServing = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "SetNotServing", + __Marshaller_grpc_testing_Empty, + __Marshaller_grpc_testing_Empty); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Testing.TestReflection.Descriptor.Services[4]; } + } + + /// Base class for server-side implementations of XdsUpdateHealthService + [grpc::BindServiceMethod(typeof(XdsUpdateHealthService), "BindService")] + public abstract partial class XdsUpdateHealthServiceBase + { + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task SetServing(global::Grpc.Testing.Empty request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task SetNotServing(global::Grpc.Testing.Empty request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for XdsUpdateHealthService + public partial class XdsUpdateHealthServiceClient : grpc::ClientBase + { + /// Creates a new client for XdsUpdateHealthService + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public XdsUpdateHealthServiceClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for XdsUpdateHealthService that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public XdsUpdateHealthServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected XdsUpdateHealthServiceClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected XdsUpdateHealthServiceClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Empty SetServing(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return SetServing(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Empty SetServing(global::Grpc.Testing.Empty request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_SetServing, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall SetServingAsync(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return SetServingAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall SetServingAsync(global::Grpc.Testing.Empty request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_SetServing, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Empty SetNotServing(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return SetNotServing(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Empty SetNotServing(global::Grpc.Testing.Empty request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_SetNotServing, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall SetNotServingAsync(global::Grpc.Testing.Empty request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return SetNotServingAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall SetNotServingAsync(global::Grpc.Testing.Empty request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_SetNotServing, null, options, request); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override XdsUpdateHealthServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new XdsUpdateHealthServiceClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static grpc::ServerServiceDefinition BindService(XdsUpdateHealthServiceBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_SetServing, serviceImpl.SetServing) + .AddMethod(__Method_SetNotServing, serviceImpl.SetNotServing).Build(); + } + + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static void BindService(grpc::ServiceBinderBase serviceBinder, XdsUpdateHealthServiceBase serviceImpl) + { + serviceBinder.AddMethod(__Method_SetServing, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.SetServing)); + serviceBinder.AddMethod(__Method_SetNotServing, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.SetNotServing)); + } + + } + /// + /// A service to dynamically update the configuration of an xDS test client. + /// + public static partial class XdsUpdateClientConfigureService + { + static readonly string __ServiceName = "grpc.testing.XdsUpdateClientConfigureService"; + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context) + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (message is global::Google.Protobuf.IBufferMessage) + { + context.SetPayloadLength(message.CalculateSize()); + global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter()); + context.Complete(); + return; + } + #endif + context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static class __Helper_MessageCache + { + public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static T __Helper_DeserializeMessage(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser parser) where T : global::Google.Protobuf.IMessage + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (__Helper_MessageCache.IsBufferMessage) + { + return parser.ParseFrom(context.PayloadAsReadOnlySequence()); + } + #endif + return parser.ParseFrom(context.PayloadAsNewBuffer()); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_ClientConfigureRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.ClientConfigureRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_ClientConfigureResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.ClientConfigureResponse.Parser)); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_Configure = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "Configure", + __Marshaller_grpc_testing_ClientConfigureRequest, + __Marshaller_grpc_testing_ClientConfigureResponse); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Testing.TestReflection.Descriptor.Services[5]; } + } + + /// Base class for server-side implementations of XdsUpdateClientConfigureService + [grpc::BindServiceMethod(typeof(XdsUpdateClientConfigureService), "BindService")] + public abstract partial class XdsUpdateClientConfigureServiceBase + { + /// + /// Update the tes client's configuration. + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task Configure(global::Grpc.Testing.ClientConfigureRequest request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for XdsUpdateClientConfigureService + public partial class XdsUpdateClientConfigureServiceClient : grpc::ClientBase + { + /// Creates a new client for XdsUpdateClientConfigureService + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public XdsUpdateClientConfigureServiceClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for XdsUpdateClientConfigureService that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public XdsUpdateClientConfigureServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected XdsUpdateClientConfigureServiceClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected XdsUpdateClientConfigureServiceClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// Update the tes client's configuration. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.ClientConfigureResponse Configure(global::Grpc.Testing.ClientConfigureRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return Configure(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Update the tes client's configuration. + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.ClientConfigureResponse Configure(global::Grpc.Testing.ClientConfigureRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_Configure, null, options, request); + } + /// + /// Update the tes client's configuration. + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall ConfigureAsync(global::Grpc.Testing.ClientConfigureRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return ConfigureAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Update the tes client's configuration. + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall ConfigureAsync(global::Grpc.Testing.ClientConfigureRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_Configure, null, options, request); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override XdsUpdateClientConfigureServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new XdsUpdateClientConfigureServiceClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static grpc::ServerServiceDefinition BindService(XdsUpdateClientConfigureServiceBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_Configure, serviceImpl.Configure).Build(); + } + + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static void BindService(grpc::ServiceBinderBase serviceBinder, XdsUpdateClientConfigureServiceBase serviceImpl) + { + serviceBinder.AddMethod(__Method_Configure, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.Configure)); + } + + } +} +#endregion diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs new file mode 100644 index 00000000..09725123 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs @@ -0,0 +1,122 @@ +#region Copyright notice and license + +// Copyright 2015-2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Google.Protobuf; +using Grpc.Core; +using Grpc.Core.Utils; + +namespace Grpc.Testing +{ + /// + /// Implementation of TestService server + /// + public class TestServiceImpl : TestService.TestServiceBase + { + public override Task EmptyCall(Empty request, ServerCallContext context) + { + return Task.FromResult(new Empty()); + } + + public override async Task UnaryCall(SimpleRequest request, ServerCallContext context) + { + await EnsureEchoMetadataAsync(context); + EnsureEchoStatus(request.ResponseStatus, context); + + var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) }; + return response; + } + + public override async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter responseStream, ServerCallContext context) + { + await EnsureEchoMetadataAsync(context); + EnsureEchoStatus(request.ResponseStatus, context); + + foreach (var responseParam in request.ResponseParameters) + { + var response = new StreamingOutputCallResponse { Payload = CreateZerosPayload(responseParam.Size) }; + await responseStream.WriteAsync(response); + } + } + + public override async Task StreamingInputCall(IAsyncStreamReader requestStream, ServerCallContext context) + { + await EnsureEchoMetadataAsync(context); + + int sum = 0; + await requestStream.ForEachAsync(request => + { + sum += request.Payload.Body.Length; + return TaskUtils.CompletedTask; + }); + return new StreamingInputCallResponse { AggregatedPayloadSize = sum }; + } + + public override async Task FullDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + { + await EnsureEchoMetadataAsync(context); + + await requestStream.ForEachAsync(async request => + { + EnsureEchoStatus(request.ResponseStatus, context); + foreach (var responseParam in request.ResponseParameters) + { + var response = new StreamingOutputCallResponse { Payload = CreateZerosPayload(responseParam.Size) }; + await responseStream.WriteAsync(response); + } + }); + } + + public override Task HalfDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + { + throw new NotImplementedException(); + } + + private static Payload CreateZerosPayload(int size) + { + return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; + } + + private static async Task EnsureEchoMetadataAsync(ServerCallContext context) + { + var echoInitialList = context.RequestHeaders.Where((entry) => entry.Key == "x-grpc-test-echo-initial").ToList(); + if (echoInitialList.Any()) { + var entry = echoInitialList.Single(); + await context.WriteResponseHeadersAsync(new Metadata { entry }); + } + + var echoTrailingList = context.RequestHeaders.Where((entry) => entry.Key == "x-grpc-test-echo-trailing-bin").ToList(); + if (echoTrailingList.Any()) { + context.ResponseTrailers.Add(echoTrailingList.Single()); + } + } + + private static void EnsureEchoStatus(EchoStatus responseStatus, ServerCallContext context) + { + if (responseStatus != null) + { + var statusCode = (StatusCode)responseStatus.Code; + context.Status = new Status(statusCode, responseStatus.Message); + } + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/TimeStats.cs b/src/csharp/Grpc.IntegrationTesting/TimeStats.cs new file mode 100644 index 00000000..6aba04c1 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/TimeStats.cs @@ -0,0 +1,90 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Google.Protobuf; +using Grpc.Core; +using Grpc.Core.Utils; +using NUnit.Framework; +using Grpc.Testing; + +namespace Grpc.IntegrationTesting +{ + /// + /// Snapshottable time statistics. + /// + public class TimeStats + { + readonly object myLock = new object(); + DateTime lastWallClock; + TimeSpan lastUserTime; + TimeSpan lastPrivilegedTime; + + public TimeStats() + { + lastWallClock = DateTime.UtcNow; + lastUserTime = Process.GetCurrentProcess().UserProcessorTime; + lastPrivilegedTime = Process.GetCurrentProcess().PrivilegedProcessorTime; + } + + public Snapshot GetSnapshot(bool reset) + { + lock (myLock) + { + var wallClock = DateTime.UtcNow; + var userTime = Process.GetCurrentProcess().UserProcessorTime; + var privilegedTime = Process.GetCurrentProcess().PrivilegedProcessorTime; + var snapshot = new Snapshot(wallClock - lastWallClock, userTime - lastUserTime, privilegedTime - lastPrivilegedTime); + + if (reset) + { + lastWallClock = wallClock; + lastUserTime = userTime; + lastPrivilegedTime = privilegedTime; + } + return snapshot; + } + } + + public class Snapshot + { + public TimeSpan WallClockTime { get; } + public TimeSpan UserProcessorTime { get; } + public TimeSpan PrivilegedProcessorTime { get; } + + public Snapshot(TimeSpan wallClockTime, TimeSpan userProcessorTime, TimeSpan privilegedProcessorTime) + { + this.WallClockTime = wallClockTime; + this.UserProcessorTime = userProcessorTime; + this.PrivilegedProcessorTime = privilegedProcessorTime; + } + + public override string ToString() + { + return string.Format("[TimeStats.Snapshot: wallClock {0}, userProcessor {1}, privilegedProcessor {2}]", WallClockTime, UserProcessorTime, PrivilegedProcessorTime); + } + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/UnobservedTaskExceptionTest.cs b/src/csharp/Grpc.IntegrationTesting/UnobservedTaskExceptionTest.cs new file mode 100644 index 00000000..db2c6c37 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/UnobservedTaskExceptionTest.cs @@ -0,0 +1,100 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using Grpc.Testing; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + /// + /// Runs interop tests in-process. + /// + public class UnobservedTaskExceptionTest + { + const string Host = "localhost"; + Server server; + Channel channel; + TestService.TestServiceClient client; + + [OneTimeSetUp] + public void Init() + { + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { TestService.BindService(new TestServiceImpl()) }, + Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } + }; + server.Start(); + + int port = server.Ports.Single().BoundPort; + channel = new Channel(Host, port, ChannelCredentials.Insecure); + client = new TestService.TestServiceClient(channel); + } + + [OneTimeTearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public async Task NoUnobservedTaskExceptionForAbandonedStreamingResponse() + { + // Verify that https://github.com/grpc/grpc/issues/17458 has been fixed. + // Create a streaming response call, then cancel it without reading all the responses + // and check that no unobserved task exceptions have been thrown. + + var unobservedTaskExceptionCounter = new AtomicCounter(); + + TaskScheduler.UnobservedTaskException += (sender, e) => { + unobservedTaskExceptionCounter.Increment(); + Console.WriteLine("Detected unobserved task exception: " + e.Exception); + }; + + var bodySizes = new List { 10, 10, 10, 10, 10 }; + var request = new StreamingOutputCallRequest { + ResponseParameters = { bodySizes.Select((size) => new ResponseParameters { Size = size }) } + }; + + for (int i = 0; i < 50; i++) + { + Console.WriteLine($"Starting iteration {i}"); + using (var call = client.StreamingOutputCall(request)) + { + // Intentionally only read the first response (we know there's more) + // The call will be cancelled as soon as we leave the "using" statement. + var firstResponse = await call.ResponseStream.MoveNext(); + } + // Make it more likely to trigger the "Unobserved task exception" warning + GC.Collect(); + } + + Assert.AreEqual(0, unobservedTaskExceptionCounter.Count); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerService.cs b/src/csharp/Grpc.IntegrationTesting/WorkerService.cs new file mode 100644 index 00000000..9f6cbd28 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/WorkerService.cs @@ -0,0 +1,45 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/worker_service.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Testing { + + /// Holder for reflection information generated from src/proto/grpc/testing/worker_service.proto + public static partial class WorkerServiceReflection { + + #region Descriptor + /// File descriptor for src/proto/grpc/testing/worker_service.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static WorkerServiceReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CitzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3dvcmtlcl9zZXJ2aWNlLnByb3Rv", + "EgxncnBjLnRlc3RpbmcaJHNyYy9wcm90by9ncnBjL3Rlc3RpbmcvY29udHJv", + "bC5wcm90bzKXAgoNV29ya2VyU2VydmljZRJFCglSdW5TZXJ2ZXISGC5ncnBj", + "LnRlc3RpbmcuU2VydmVyQXJncxoaLmdycGMudGVzdGluZy5TZXJ2ZXJTdGF0", + "dXMoATABEkUKCVJ1bkNsaWVudBIYLmdycGMudGVzdGluZy5DbGllbnRBcmdz", + "GhouZ3JwYy50ZXN0aW5nLkNsaWVudFN0YXR1cygBMAESQgoJQ29yZUNvdW50", + "EhkuZ3JwYy50ZXN0aW5nLkNvcmVSZXF1ZXN0GhouZ3JwYy50ZXN0aW5nLkNv", + "cmVSZXNwb25zZRI0CgpRdWl0V29ya2VyEhIuZ3JwYy50ZXN0aW5nLlZvaWQa", + "Ei5ncnBjLnRlc3RpbmcuVm9pZGIGcHJvdG8z")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Grpc.Testing.ControlReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, null, null)); + } + #endregion + + } +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs new file mode 100644 index 00000000..90047939 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs @@ -0,0 +1,406 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: src/proto/grpc/testing/worker_service.proto +// +// Original file comments: +// Copyright 2015 gRPC authors. +// +// 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. +// +// An integration test service that covers all the method signature permutations +// of unary/streaming requests/responses. +#pragma warning disable 0414, 1591 +#region Designer generated code + +using grpc = global::Grpc.Core; + +namespace Grpc.Testing { + public static partial class WorkerService + { + static readonly string __ServiceName = "grpc.testing.WorkerService"; + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context) + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (message is global::Google.Protobuf.IBufferMessage) + { + context.SetPayloadLength(message.CalculateSize()); + global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter()); + context.Complete(); + return; + } + #endif + context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static class __Helper_MessageCache + { + public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static T __Helper_DeserializeMessage(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser parser) where T : global::Google.Protobuf.IMessage + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (__Helper_MessageCache.IsBufferMessage) + { + return parser.ParseFrom(context.PayloadAsReadOnlySequence()); + } + #endif + return parser.ParseFrom(context.PayloadAsNewBuffer()); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_ServerArgs = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.ServerArgs.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_ServerStatus = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.ServerStatus.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_ClientArgs = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.ClientArgs.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_ClientStatus = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.ClientStatus.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_CoreRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.CoreRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_CoreResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.CoreResponse.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_testing_Void = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Testing.Void.Parser)); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_RunServer = new grpc::Method( + grpc::MethodType.DuplexStreaming, + __ServiceName, + "RunServer", + __Marshaller_grpc_testing_ServerArgs, + __Marshaller_grpc_testing_ServerStatus); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_RunClient = new grpc::Method( + grpc::MethodType.DuplexStreaming, + __ServiceName, + "RunClient", + __Marshaller_grpc_testing_ClientArgs, + __Marshaller_grpc_testing_ClientStatus); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_CoreCount = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "CoreCount", + __Marshaller_grpc_testing_CoreRequest, + __Marshaller_grpc_testing_CoreResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_QuitWorker = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "QuitWorker", + __Marshaller_grpc_testing_Void, + __Marshaller_grpc_testing_Void); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Testing.WorkerServiceReflection.Descriptor.Services[0]; } + } + + /// Base class for server-side implementations of WorkerService + [grpc::BindServiceMethod(typeof(WorkerService), "BindService")] + public abstract partial class WorkerServiceBase + { + /// + /// Start server with specified workload. + /// First request sent specifies the ServerConfig followed by ServerStatus + /// response. After that, a "Mark" can be sent anytime to request the latest + /// stats. Closing the stream will initiate shutdown of the test server + /// and once the shutdown has finished, the OK status is sent to terminate + /// this RPC. + /// + /// Used for reading requests from the client. + /// Used for sending responses back to the client. + /// The context of the server-side call handler being invoked. + /// A task indicating completion of the handler. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task RunServer(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// Start client with specified workload. + /// First request sent specifies the ClientConfig followed by ClientStatus + /// response. After that, a "Mark" can be sent anytime to request the latest + /// stats. Closing the stream will initiate shutdown of the test client + /// and once the shutdown has finished, the OK status is sent to terminate + /// this RPC. + /// + /// Used for reading requests from the client. + /// Used for sending responses back to the client. + /// The context of the server-side call handler being invoked. + /// A task indicating completion of the handler. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task RunClient(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// Just return the core count - unary call + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task CoreCount(global::Grpc.Testing.CoreRequest request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + /// + /// Quit this worker + /// + /// The request received from the client. + /// The context of the server-side call handler being invoked. + /// The response to send back to the client (wrapped by a task). + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task QuitWorker(global::Grpc.Testing.Void request, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for WorkerService + public partial class WorkerServiceClient : grpc::ClientBase + { + /// Creates a new client for WorkerService + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public WorkerServiceClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for WorkerService that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public WorkerServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected WorkerServiceClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected WorkerServiceClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// Start server with specified workload. + /// First request sent specifies the ServerConfig followed by ServerStatus + /// response. After that, a "Mark" can be sent anytime to request the latest + /// stats. Closing the stream will initiate shutdown of the test server + /// and once the shutdown has finished, the OK status is sent to terminate + /// this RPC. + /// + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall RunServer(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return RunServer(new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Start server with specified workload. + /// First request sent specifies the ServerConfig followed by ServerStatus + /// response. After that, a "Mark" can be sent anytime to request the latest + /// stats. Closing the stream will initiate shutdown of the test server + /// and once the shutdown has finished, the OK status is sent to terminate + /// this RPC. + /// + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall RunServer(grpc::CallOptions options) + { + return CallInvoker.AsyncDuplexStreamingCall(__Method_RunServer, null, options); + } + /// + /// Start client with specified workload. + /// First request sent specifies the ClientConfig followed by ClientStatus + /// response. After that, a "Mark" can be sent anytime to request the latest + /// stats. Closing the stream will initiate shutdown of the test client + /// and once the shutdown has finished, the OK status is sent to terminate + /// this RPC. + /// + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall RunClient(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return RunClient(new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Start client with specified workload. + /// First request sent specifies the ClientConfig followed by ClientStatus + /// response. After that, a "Mark" can be sent anytime to request the latest + /// stats. Closing the stream will initiate shutdown of the test client + /// and once the shutdown has finished, the OK status is sent to terminate + /// this RPC. + /// + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall RunClient(grpc::CallOptions options) + { + return CallInvoker.AsyncDuplexStreamingCall(__Method_RunClient, null, options); + } + /// + /// Just return the core count - unary call + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return CoreCount(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Just return the core count - unary call + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_CoreCount, null, options, request); + } + /// + /// Just return the core count - unary call + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CoreCountAsync(global::Grpc.Testing.CoreRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return CoreCountAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Just return the core count - unary call + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CoreCountAsync(global::Grpc.Testing.CoreRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_CoreCount, null, options, request); + } + /// + /// Quit this worker + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return QuitWorker(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Quit this worker + /// + /// The request to send to the server. + /// The options for the call. + /// The response received from the server. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_QuitWorker, null, options, request); + } + /// + /// Quit this worker + /// + /// The request to send to the server. + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall QuitWorkerAsync(global::Grpc.Testing.Void request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return QuitWorkerAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// Quit this worker + /// + /// The request to send to the server. + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall QuitWorkerAsync(global::Grpc.Testing.Void request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_QuitWorker, null, options, request); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override WorkerServiceClient NewInstance(ClientBaseConfiguration configuration) + { + return new WorkerServiceClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static grpc::ServerServiceDefinition BindService(WorkerServiceBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_RunServer, serviceImpl.RunServer) + .AddMethod(__Method_RunClient, serviceImpl.RunClient) + .AddMethod(__Method_CoreCount, serviceImpl.CoreCount) + .AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build(); + } + + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static void BindService(grpc::ServiceBinderBase serviceBinder, WorkerServiceBase serviceImpl) + { + serviceBinder.AddMethod(__Method_RunServer, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.RunServer)); + serviceBinder.AddMethod(__Method_RunClient, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.RunClient)); + serviceBinder.AddMethod(__Method_CoreCount, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.CoreCount)); + serviceBinder.AddMethod(__Method_QuitWorker, serviceImpl == null ? null : new grpc::UnaryServerMethod(serviceImpl.QuitWorker)); + } + + } +} +#endregion diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs new file mode 100644 index 00000000..e6e380d7 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs @@ -0,0 +1,99 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Google.Protobuf; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.IntegrationTesting; + +namespace Grpc.Testing +{ + /// + /// Implementation of WorkerService server + /// + public class WorkerServiceImpl : WorkerService.WorkerServiceBase + { + readonly Action stopRequestHandler; + + public WorkerServiceImpl(Action stopRequestHandler) + { + this.stopRequestHandler = GrpcPreconditions.CheckNotNull(stopRequestHandler); + } + + public override async Task RunServer(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + { + GrpcPreconditions.CheckState(await requestStream.MoveNext()); + var serverConfig = requestStream.Current.Setup; + var runner = ServerRunners.CreateStarted(serverConfig); + + await responseStream.WriteAsync(new ServerStatus + { + Stats = runner.GetStats(false), + Port = runner.BoundPort, + Cores = Environment.ProcessorCount, + }); + + while (await requestStream.MoveNext()) + { + var reset = requestStream.Current.Mark.Reset; + await responseStream.WriteAsync(new ServerStatus + { + Stats = runner.GetStats(reset) + }); + } + await runner.StopAsync(); + } + + public override async Task RunClient(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + { + GrpcPreconditions.CheckState(await requestStream.MoveNext()); + var clientConfig = requestStream.Current.Setup; + var runner = ClientRunners.CreateStarted(clientConfig); + + await responseStream.WriteAsync(new ClientStatus + { + Stats = runner.GetStats(false) + }); + + while (await requestStream.MoveNext()) + { + var reset = requestStream.Current.Mark.Reset; + await responseStream.WriteAsync(new ClientStatus + { + Stats = runner.GetStats(reset) + }); + } + await runner.StopAsync(); + } + + public override Task CoreCount(CoreRequest request, ServerCallContext context) + { + return Task.FromResult(new CoreResponse { Cores = Environment.ProcessorCount }); + } + + public override Task QuitWorker(Void request, ServerCallContext context) + { + stopRequestHandler(); + return Task.FromResult(new Void()); + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/XdsInteropClient.cs b/src/csharp/Grpc.IntegrationTesting/XdsInteropClient.cs new file mode 100644 index 00000000..f30f5b8f --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/XdsInteropClient.cs @@ -0,0 +1,438 @@ +#region Copyright notice and license + +// Copyright 2020 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +using CommandLine; +using Grpc.Core; +using Grpc.Core.Logging; +using Grpc.Core.Internal; +using Grpc.Testing; + +namespace Grpc.IntegrationTesting +{ + public class XdsInteropClient + { + internal class ClientOptions + { + [Option("num_channels", Default = 1)] + public int NumChannels { get; set; } + + [Option("qps", Default = 1)] + + // The desired QPS per channel, for each type of RPC. + public int Qps { get; set; } + + [Option("server", Default = "localhost:8080")] + public string Server { get; set; } + + [Option("stats_port", Default = 8081)] + public int StatsPort { get; set; } + + [Option("rpc_timeout_sec", Default = 30)] + public int RpcTimeoutSec { get; set; } + + [Option("print_response", Default = false)] + public bool PrintResponse { get; set; } + + // Types of RPCs to make, ',' separated string. RPCs can be EmptyCall or UnaryCall + [Option("rpc", Default = "UnaryCall")] + public string Rpc { get; set; } + + // The metadata to send with each RPC, in the format EmptyCall:key1:value1,UnaryCall:key2:value2 + [Option("metadata", Default = null)] + public string Metadata { get; set; } + } + + internal enum RpcType + { + UnaryCall, + EmptyCall + } + + ClientOptions options; + + StatsWatcher statsWatcher = new StatsWatcher(); + + List rpcs; + Dictionary metadata; + + // make watcher accessible by tests + internal StatsWatcher StatsWatcher => statsWatcher; + + internal XdsInteropClient(ClientOptions options) + { + this.options = options; + this.rpcs = ParseRpcArgument(this.options.Rpc); + this.metadata = ParseMetadataArgument(this.options.Metadata); + } + + public static void Run(string[] args) + { + GrpcEnvironment.SetLogger(new ConsoleLogger()); + var parserResult = Parser.Default.ParseArguments(args) + .WithNotParsed(errors => Environment.Exit(1)) + .WithParsed(options => + { + var xdsInteropClient = new XdsInteropClient(options); + xdsInteropClient.RunAsync().Wait(); + }); + } + + private async Task RunAsync() + { + var server = new Server + { + Services = { LoadBalancerStatsService.BindService(new LoadBalancerStatsServiceImpl(statsWatcher)) } + }; + + string host = "0.0.0.0"; + server.Ports.Add(host, options.StatsPort, ServerCredentials.Insecure); + Console.WriteLine($"Running server on {host}:{options.StatsPort}"); + server.Start(); + + var cancellationTokenSource = new CancellationTokenSource(); + await RunChannelsAsync(cancellationTokenSource.Token); + + await server.ShutdownAsync(); + } + + // method made internal to make it runnable by tests + internal async Task RunChannelsAsync(CancellationToken cancellationToken) + { + var channelTasks = new List(); + for (int channelId = 0; channelId < options.NumChannels; channelId++) + { + var channelTask = RunSingleChannelAsync(channelId, cancellationToken); + channelTasks.Add(channelTask); + } + + for (int channelId = 0; channelId < options.NumChannels; channelId++) + { + await channelTasks[channelId]; + } + } + + private async Task RunSingleChannelAsync(int channelId, CancellationToken cancellationToken) + { + Console.WriteLine($"Starting channel {channelId}"); + var channel = new Channel(options.Server, ChannelCredentials.Insecure); + var client = new TestService.TestServiceClient(channel); + + var inflightTasks = new List(); + long rpcsStarted = 0; + var stopwatch = Stopwatch.StartNew(); + while (!cancellationToken.IsCancellationRequested) + { + foreach (var rpcType in rpcs) + { + inflightTasks.Add(RunSingleRpcAsync(client, cancellationToken, rpcType)); + rpcsStarted++; + } + + // only cleanup calls that have already completed, calls that are still inflight will be cleaned up later. + await CleanupCompletedTasksAsync(inflightTasks); + + // if needed, wait a bit before we start the next RPC. + int nextDueInMillis = (int) Math.Max(0, (1000 * rpcsStarted / options.Qps / rpcs.Count) - stopwatch.ElapsedMilliseconds); + if (nextDueInMillis > 0) + { + await Task.Delay(nextDueInMillis); + } + } + stopwatch.Stop(); + + Console.WriteLine($"Shutting down channel {channelId}"); + await channel.ShutdownAsync(); + Console.WriteLine($"Channel shutdown {channelId}"); + } + + private async Task RunSingleRpcAsync(TestService.TestServiceClient client, CancellationToken cancellationToken, RpcType rpcType) + { + long rpcId = statsWatcher.RpcIdGenerator.Increment(); + try + { + // metadata to send with the RPC + var headers = new Metadata(); + if (metadata.ContainsKey(rpcType)) + { + headers = metadata[rpcType]; + if (headers.Count > 0) + { + var printableHeaders = "[" + string.Join(", ", headers) + "]"; + } + } + + if (rpcType == RpcType.UnaryCall) + { + + var call = client.UnaryCallAsync(new SimpleRequest(), + new CallOptions(headers: headers, cancellationToken: cancellationToken, deadline: DateTime.UtcNow.AddSeconds(options.RpcTimeoutSec))); + + var response = await call; + var hostname = (await call.ResponseHeadersAsync).GetValue("hostname") ?? response.Hostname; + statsWatcher.OnRpcComplete(rpcId, rpcType, hostname); + if (options.PrintResponse) + { + Console.WriteLine($"Got response {response}"); + } + } + else if (rpcType == RpcType.EmptyCall) + { + var call = client.EmptyCallAsync(new Empty(), + new CallOptions(headers: headers, cancellationToken: cancellationToken, deadline: DateTime.UtcNow.AddSeconds(options.RpcTimeoutSec))); + + var response = await call; + var hostname = (await call.ResponseHeadersAsync).GetValue("hostname"); + statsWatcher.OnRpcComplete(rpcId, rpcType, hostname); + if (options.PrintResponse) + { + Console.WriteLine($"Got response {response}"); + } + } + else + { + throw new InvalidOperationException($"Unsupported RPC type ${rpcType}"); + } + } + catch (RpcException ex) + { + statsWatcher.OnRpcComplete(rpcId, rpcType, null); + if (options.PrintResponse) + { + Console.WriteLine($"RPC {rpcId} failed: {ex}"); + } + } + } + + private async Task CleanupCompletedTasksAsync(List tasks) + { + var toRemove = new List(); + foreach (var task in tasks) + { + if (task.IsCompleted) + { + // awaiting tasks that have already completed should be instantaneous + await task; + } + toRemove.Add(task); + } + foreach (var task in toRemove) + { + tasks.Remove(task); + } + } + + private static List ParseRpcArgument(string rpcArg) + { + var result = new List(); + foreach (var part in rpcArg.Split(',')) + { + result.Add(ParseRpc(part)); + } + return result; + } + + private static RpcType ParseRpc(string rpc) + { + switch (rpc) + { + case "UnaryCall": + return RpcType.UnaryCall; + case "EmptyCall": + return RpcType.EmptyCall; + default: + throw new ArgumentException($"Unknown RPC: \"{rpc}\""); + } + } + + private static Dictionary ParseMetadataArgument(string metadataArg) + { + var rpcMetadata = new Dictionary(); + if (string.IsNullOrEmpty(metadataArg)) + { + return rpcMetadata; + } + + foreach (var metadata in metadataArg.Split(',')) + { + var parts = metadata.Split(':'); + if (parts.Length != 3) + { + throw new ArgumentException($"Invalid metadata: \"{metadata}\""); + } + var rpc = ParseRpc(parts[0]); + var key = parts[1]; + var value = parts[2]; + + var md = new Metadata { {key, value} }; + + if (rpcMetadata.ContainsKey(rpc)) + { + var existingMetadata = rpcMetadata[rpc]; + foreach (var entry in md) + { + existingMetadata.Add(entry); + } + } + else + { + rpcMetadata.Add(rpc, md); + } + } + return rpcMetadata; + } + } + + internal class StatsWatcher + { + private readonly object myLock = new object(); + private readonly AtomicCounter rpcIdGenerator = new AtomicCounter(0); + + private long? firstAcceptedRpcId; + private int numRpcsWanted; + private int rpcsCompleted; + private int rpcsNoHostname; + private Dictionary rpcsByHostname; + private Dictionary> rpcsByMethod; + + public AtomicCounter RpcIdGenerator => rpcIdGenerator; + + public StatsWatcher() + { + Reset(); + } + + public void OnRpcComplete(long rpcId, XdsInteropClient.RpcType rpcType, string responseHostname) + { + lock (myLock) + { + if (!firstAcceptedRpcId.HasValue || rpcId < firstAcceptedRpcId || rpcId >= firstAcceptedRpcId + numRpcsWanted) + { + return; + } + + if (string.IsNullOrEmpty(responseHostname)) + { + rpcsNoHostname ++; + } + else + { + // update rpcsByHostname + if (!rpcsByHostname.ContainsKey(responseHostname)) + { + rpcsByHostname[responseHostname] = 0; + } + rpcsByHostname[responseHostname] += 1; + + // update rpcsByMethod + var method = rpcType.ToString(); + if (!rpcsByMethod.ContainsKey(method)) + { + rpcsByMethod[method] = new Dictionary(); + } + if (!rpcsByMethod[method].ContainsKey(responseHostname)) + { + rpcsByMethod[method][responseHostname] = 0; + } + rpcsByMethod[method][responseHostname] += 1; + } + rpcsCompleted += 1; + + if (rpcsCompleted >= numRpcsWanted) + { + Monitor.Pulse(myLock); + } + } + } + + public void Reset() + { + lock (myLock) + { + firstAcceptedRpcId = null; + numRpcsWanted = 0; + rpcsCompleted = 0; + rpcsNoHostname = 0; + rpcsByHostname = new Dictionary(); + rpcsByMethod = new Dictionary>(); + } + } + + public LoadBalancerStatsResponse WaitForRpcStatsResponse(int rpcsWanted, int timeoutSec) + { + lock (myLock) + { + if (firstAcceptedRpcId.HasValue) + { + throw new InvalidOperationException("StateWatcher is already collecting stats."); + } + // we are only interested in the next numRpcsWanted RPCs + firstAcceptedRpcId = rpcIdGenerator.Count + 1; + numRpcsWanted = rpcsWanted; + + var deadline = DateTime.UtcNow.AddSeconds(timeoutSec); + while (true) + { + var timeoutMillis = Math.Max((int)(deadline - DateTime.UtcNow).TotalMilliseconds, 0); + if (!Monitor.Wait(myLock, timeoutMillis) || rpcsCompleted >= rpcsWanted) + { + // we collected enough RPCs, or timed out waiting + var response = new LoadBalancerStatsResponse { NumFailures = rpcsNoHostname }; + response.RpcsByPeer.Add(rpcsByHostname); + + response.RpcsByMethod.Clear(); + foreach (var methodEntry in rpcsByMethod) + { + var rpcsByPeer = new LoadBalancerStatsResponse.Types.RpcsByPeer(); + rpcsByPeer.RpcsByPeer_.Add(methodEntry.Value); + response.RpcsByMethod[methodEntry.Key] = rpcsByPeer; + } + Reset(); + return response; + } + } + } + } + } + + /// + /// Implementation of LoadBalancerStatsService server + /// + internal class LoadBalancerStatsServiceImpl : LoadBalancerStatsService.LoadBalancerStatsServiceBase + { + StatsWatcher statsWatcher; + + public LoadBalancerStatsServiceImpl(StatsWatcher statsWatcher) + { + this.statsWatcher = statsWatcher; + } + + public override async Task GetClientStats(LoadBalancerStatsRequest request, ServerCallContext context) + { + // run as a task to avoid blocking + var response = await Task.Run(() => statsWatcher.WaitForRpcStatsResponse(request.NumRpcs, request.TimeoutSec)); + Console.WriteLine($"Returning stats {response} (num of requested RPCs: {request.NumRpcs})"); + return response; + } + } +} diff --git a/src/csharp/Grpc.IntegrationTesting/XdsInteropClientTest.cs b/src/csharp/Grpc.IntegrationTesting/XdsInteropClientTest.cs new file mode 100644 index 00000000..4025d806 --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/XdsInteropClientTest.cs @@ -0,0 +1,174 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Testing; +using NUnit.Framework; + +namespace Grpc.IntegrationTesting +{ + public class XdsInteropClientTest + { + const string Host = "localhost"; + + BackendServiceImpl backendService; + + Server backendServer; + Server lbStatsServer; + Channel lbStatsChannel; + LoadBalancerStatsService.LoadBalancerStatsServiceClient lbStatsClient; + + XdsInteropClient xdsInteropClient; + + [OneTimeSetUp] + public void Init() + { + backendService = new BackendServiceImpl(); + + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + backendServer = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { TestService.BindService(backendService) }, + Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } + }; + backendServer.Start(); + + xdsInteropClient = new XdsInteropClient(new XdsInteropClient.ClientOptions + { + NumChannels = 1, + Qps = 1, + RpcTimeoutSec = 10, + Rpc = "UnaryCall", + Server = $"{Host}:{backendServer.Ports.Single().BoundPort}", + }); + + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + lbStatsServer = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { LoadBalancerStatsService.BindService(new LoadBalancerStatsServiceImpl(xdsInteropClient.StatsWatcher)) }, + Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } + }; + lbStatsServer.Start(); + + int port = lbStatsServer.Ports.Single().BoundPort; + lbStatsChannel = new Channel(Host, port, ChannelCredentials.Insecure); + lbStatsClient = new LoadBalancerStatsService.LoadBalancerStatsServiceClient(lbStatsChannel); + } + + [OneTimeTearDown] + public void Cleanup() + { + lbStatsChannel.ShutdownAsync().Wait(); + lbStatsServer.ShutdownAsync().Wait(); + backendServer.ShutdownAsync().Wait(); + } + + [Test] + public async Task SmokeTest() + { + string backendName = "backend1"; + backendService.UnaryHandler = (request, context) => + { + return Task.FromResult(new SimpleResponse { Hostname = backendName }); + }; + + var cancellationTokenSource = new CancellationTokenSource(); + var runChannelsTask = xdsInteropClient.RunChannelsAsync(cancellationTokenSource.Token); + + var stats = await lbStatsClient.GetClientStatsAsync(new LoadBalancerStatsRequest + { + NumRpcs = 5, + TimeoutSec = 10, + }, deadline: DateTime.UtcNow.AddSeconds(30)); + + Assert.AreEqual(0, stats.NumFailures); + Assert.AreEqual(backendName, stats.RpcsByPeer.Keys.Single()); + Assert.AreEqual(5, stats.RpcsByPeer[backendName]); + Assert.AreEqual("UnaryCall", stats.RpcsByMethod.Keys.Single()); + Assert.AreEqual(backendName, stats.RpcsByMethod["UnaryCall"].RpcsByPeer_.Keys.Single()); + Assert.AreEqual(5, stats.RpcsByMethod["UnaryCall"].RpcsByPeer_[backendName]); + + await Task.Delay(100); + + var stats2 = await lbStatsClient.GetClientStatsAsync(new LoadBalancerStatsRequest + { + NumRpcs = 3, + TimeoutSec = 10, + }, deadline: DateTime.UtcNow.AddSeconds(30)); + + Assert.AreEqual(0, stats2.NumFailures); + Assert.AreEqual(backendName, stats2.RpcsByPeer.Keys.Single()); + Assert.AreEqual(3, stats2.RpcsByPeer[backendName]); + Assert.AreEqual("UnaryCall", stats2.RpcsByMethod.Keys.Single()); + Assert.AreEqual(backendName, stats2.RpcsByMethod["UnaryCall"].RpcsByPeer_.Keys.Single()); + Assert.AreEqual(3, stats2.RpcsByMethod["UnaryCall"].RpcsByPeer_[backendName]); + + cancellationTokenSource.Cancel(); + await runChannelsTask; + } + + [Test] + public async Task HostnameReadFromResponseHeaders() + { + string correctBackendName = "backend1"; + backendService.UnaryHandler = async (request, context) => + { + await context.WriteResponseHeadersAsync(new Metadata { {"hostname", correctBackendName} }); + return new SimpleResponse { Hostname = "wrong_hostname" }; + }; + + var cancellationTokenSource = new CancellationTokenSource(); + var runChannelsTask = xdsInteropClient.RunChannelsAsync(cancellationTokenSource.Token); + + var stats = await lbStatsClient.GetClientStatsAsync(new LoadBalancerStatsRequest + { + NumRpcs = 3, + TimeoutSec = 10, + }, deadline: DateTime.UtcNow.AddSeconds(30)); + + Assert.AreEqual(0, stats.NumFailures); + Assert.AreEqual(correctBackendName, stats.RpcsByPeer.Keys.Single()); + Assert.AreEqual(3, stats.RpcsByPeer[correctBackendName]); + + cancellationTokenSource.Cancel(); + await runChannelsTask; + } + + public class BackendServiceImpl : TestService.TestServiceBase + { + public UnaryServerMethod UnaryHandler { get; set; } + public UnaryServerMethod EmptyHandler { get; set; } + + public override Task UnaryCall(SimpleRequest request, ServerCallContext context) + { + return UnaryHandler(request, context); + } + + public override Task EmptyCall(Empty request, ServerCallContext context) + { + return EmptyHandler(request, context); + } + } + } +} diff --git a/src/csharp/Grpc.Microbenchmarks/AtomicCounterBenchmark.cs b/src/csharp/Grpc.Microbenchmarks/AtomicCounterBenchmark.cs new file mode 100644 index 00000000..03984f40 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/AtomicCounterBenchmark.cs @@ -0,0 +1,52 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Runtime.InteropServices; +using BenchmarkDotNet.Attributes; +using Grpc.Core.Internal; + +namespace Grpc.Microbenchmarks +{ + public class AtomicCounterBenchmark : CommonThreadedBase + { + protected override bool NeedsEnvironment => false; + + // An example of testing scalability of a method that scales perfectly. + // This method provides a baseline for how well can CommonThreadedBase + // measure scalability. + const int Iterations = 20 * 1000 * 1000; // High number to make the overhead of RunConcurrent negligible. + [Benchmark(OperationsPerInvoke = Iterations)] + + public void SharedAtomicCounterIncrement() + { + RunConcurrent(() => { RunBody(); }); + } + + readonly AtomicCounter sharedCounter = new AtomicCounter(); + + private int RunBody() + { + for (int i = 0; i < Iterations; i++) + { + sharedCounter.Increment(); + } + return (int) sharedCounter.Count; + } + } +} diff --git a/src/csharp/Grpc.Microbenchmarks/CommonThreadedBase.cs b/src/csharp/Grpc.Microbenchmarks/CommonThreadedBase.cs new file mode 100644 index 00000000..c42c6481 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/CommonThreadedBase.cs @@ -0,0 +1,129 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using Grpc.Core; + +namespace Grpc.Microbenchmarks +{ + + // common base-type for tests that need to run with some level of concurrency; + // note there's nothing *special* about this type - it is just to save some + // boilerplate + + [ClrJob, CoreJob] // test .NET Core and .NET Framework + [MemoryDiagnoser] // allocations + public abstract class CommonThreadedBase + { + protected virtual bool NeedsEnvironment => true; + + [Params(1, 2, 4, 6)] + public int ThreadCount { get; set; } + + protected GrpcEnvironment Environment { get; private set; } + + private List workers; + + private List> dispatchQueues; + + [GlobalSetup] + public virtual void Setup() + { + dispatchQueues = new List>(); + workers = new List(); + for (int i = 0; i < ThreadCount; i++) + { + var dispatchQueue = new BlockingCollection(); + var thread = new Thread(new ThreadStart(() => WorkerThreadBody(dispatchQueue))); + thread.Name = string.Format("threaded benchmark worker {0}", i); + thread.Start(); + workers.Add(thread); + dispatchQueues.Add(dispatchQueue); + } + + if (NeedsEnvironment) Environment = GrpcEnvironment.AddRef(); + } + + [GlobalCleanup] + public virtual void Cleanup() + { + for (int i = 0; i < ThreadCount; i++) + { + dispatchQueues[i].Add(null); // null action request termination of the worker thread. + workers[i].Join(); + } + + if (Environment != null) + { + Environment = null; + GrpcEnvironment.ReleaseAsync().Wait(); + } + } + + /// + /// Runs the operation in parallel (once on each worker thread). + /// This method tries to incur as little + /// overhead as possible, but there is some inherent overhead + /// that is hard to avoid (thread hop etc.). Therefore it is strongly + /// recommended that the benchmarked operation runs long enough to + /// make this overhead negligible. + /// + protected void RunConcurrent(Action operation) + { + var workItemTasks = new Task[ThreadCount]; + for (int i = 0; i < ThreadCount; i++) + { + var tcs = new TaskCompletionSource(); + var workItem = new Action(() => + { + try + { + operation(); + tcs.SetResult(null); + } + catch (Exception e) + { + tcs.SetException(e); + } + }); + workItemTasks[i] = tcs.Task; + dispatchQueues[i].Add(workItem); + } + Task.WaitAll(workItemTasks); + } + + private void WorkerThreadBody(BlockingCollection dispatchQueue) + { + while(true) + { + var workItem = dispatchQueue.Take(); + if (workItem == null) + { + // stop the worker if null action was provided + break; + } + workItem(); + } + } + } +} diff --git a/src/csharp/Grpc.Microbenchmarks/CompletionRegistryBenchmark.cs b/src/csharp/Grpc.Microbenchmarks/CompletionRegistryBenchmark.cs new file mode 100644 index 00000000..9426882b --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/CompletionRegistryBenchmark.cs @@ -0,0 +1,55 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using BenchmarkDotNet.Attributes; +using Grpc.Core.Internal; + +namespace Grpc.Microbenchmarks +{ + public class CompletionRegistryBenchmark : CommonThreadedBase + { + [Params(false, true)] + public bool UseSharedRegistry { get; set; } + + const int Iterations = 5 * 1000 * 1000; // High number to make the overhead of RunConcurrent negligible. + [Benchmark(OperationsPerInvoke = Iterations)] + public void RegisterExtract() + { + CompletionRegistry sharedRegistry = UseSharedRegistry ? new CompletionRegistry(Environment, () => BatchContextSafeHandle.Create(), () => RequestCallContextSafeHandle.Create()) : null; + RunConcurrent(() => + { + RunBody(sharedRegistry); + }); + } + + private void RunBody(CompletionRegistry optionalSharedRegistry) + { + var completionRegistry = optionalSharedRegistry ?? new CompletionRegistry(Environment, () => throw new NotImplementedException(), () => throw new NotImplementedException()); + var ctx = BatchContextSafeHandle.Create(); + + for (int i = 0; i < Iterations; i++) + { + completionRegistry.Register(ctx.Handle, ctx); + var callback = completionRegistry.Extract(ctx.Handle); + // NOTE: we are not calling the callback to avoid disposing ctx. + } + ctx.Recycle(); + } + } +} diff --git a/src/csharp/Grpc.Microbenchmarks/PInvokeByteArrayBenchmark.cs b/src/csharp/Grpc.Microbenchmarks/PInvokeByteArrayBenchmark.cs new file mode 100644 index 00000000..1ede7453 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/PInvokeByteArrayBenchmark.cs @@ -0,0 +1,54 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Runtime.InteropServices; +using BenchmarkDotNet.Attributes; +using Grpc.Core.Internal; + +namespace Grpc.Microbenchmarks +{ + public class PInvokeByteArrayBenchmark : CommonThreadedBase + { + static readonly NativeMethods Native = NativeMethods.Get(); + + protected override bool NeedsEnvironment => false; + + + [Params(0)] + public int PayloadSize { get; set; } + + const int Iterations = 5 * 1000 * 1000; // High number to make the overhead of RunConcurrent negligible. + [Benchmark(OperationsPerInvoke = Iterations)] + public void AllocFree() + { + RunConcurrent(RunBody); + } + + private void RunBody() + { + var payload = new byte[PayloadSize]; + for (int i = 0; i < Iterations; i++) + { + var gcHandle = GCHandle.Alloc(payload, GCHandleType.Pinned); + var payloadPtr = gcHandle.AddrOfPinnedObject(); + Native.grpcsharp_test_nop(payloadPtr); + gcHandle.Free(); + } + } + } +} diff --git a/src/csharp/Grpc.Microbenchmarks/PingBenchmark.cs b/src/csharp/Grpc.Microbenchmarks/PingBenchmark.cs new file mode 100644 index 00000000..cbcf5d36 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/PingBenchmark.cs @@ -0,0 +1,102 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using Grpc.Core; + +namespace Grpc.Microbenchmarks +{ + // this test creates a real server and client, measuring the inherent inbuilt + // platform overheads; the marshallers **DO NOT ALLOCATE**, so any allocations + // are from the framework, not the messages themselves + + // important: allocs are not reliable on .NET Core until .NET Core 3, since + // this test involves multiple threads + + [ClrJob, CoreJob] // test .NET Core and .NET Framework + [MemoryDiagnoser] // allocations + public class PingBenchmark + { + private static readonly Task CompletedString = Task.FromResult(""); + private static readonly byte[] EmptyBlob = new byte[0]; + private static readonly Marshaller EmptyMarshaller = new Marshaller(_ => EmptyBlob, _ => ""); + private static readonly Method PingMethod = new Method(MethodType.Unary, nameof(PingBenchmark), "Ping", EmptyMarshaller, EmptyMarshaller); + + + [Benchmark] + public async ValueTask PingAsync() + { + using (var result = client.PingAsync("", new CallOptions())) + { + return await result.ResponseAsync; + } + } + + [Benchmark] + public string Ping() + { + return client.Ping("", new CallOptions()); + } + + private Task ServerMethod(string request, ServerCallContext context) + { + return CompletedString; + } + + Server server; + Channel channel; + PingClient client; + + [GlobalSetup] + public async Task Setup() + { + // create server + server = new Server { + Ports = { new ServerPort("localhost", 10042, ServerCredentials.Insecure) }, + Services = { ServerServiceDefinition.CreateBuilder().AddMethod(PingMethod, ServerMethod).Build() }, + }; + server.Start(); + + // create client + channel = new Channel("localhost", 10042, ChannelCredentials.Insecure); + await channel.ConnectAsync(); + client = new PingClient(new DefaultCallInvoker(channel)); + } + + [GlobalCleanup] + public async Task Cleanup() + { + await channel.ShutdownAsync(); + await server.ShutdownAsync(); + } + + class PingClient : ClientBase + { + public PingClient(CallInvoker callInvoker) : base(callInvoker) { } + public AsyncUnaryCall PingAsync(string request, CallOptions options) + { + return CallInvoker.AsyncUnaryCall(PingMethod, null, options, request); + } + public string Ping(string request, CallOptions options) + { + return CallInvoker.BlockingUnaryCall(PingMethod, null, options, request); + } + } + } +} diff --git a/src/csharp/Grpc.Microbenchmarks/Program.cs b/src/csharp/Grpc.Microbenchmarks/Program.cs new file mode 100644 index 00000000..71e549f7 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/Program.cs @@ -0,0 +1,33 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using BenchmarkDotNet.Running; + +namespace Grpc.Microbenchmarks +{ + class Program + { + // typical usage: dotnet run -c Release -f netcoreapp2.1 + // (this will profile both .net core and .net framework; for some reason + // if you start from "-f net461", it goes horribly wrong) + public static void Main(string[] args) + { + BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args); + } + } +} diff --git a/src/csharp/Grpc.Microbenchmarks/ScalabityExampleBenchmark.cs b/src/csharp/Grpc.Microbenchmarks/ScalabityExampleBenchmark.cs new file mode 100644 index 00000000..1ef117c8 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/ScalabityExampleBenchmark.cs @@ -0,0 +1,56 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Runtime.InteropServices; +using BenchmarkDotNet.Attributes; +using Grpc.Core.Internal; + +namespace Grpc.Microbenchmarks +{ + public class ScalabilityExampleBenchmark : CommonThreadedBase + { + protected override bool NeedsEnvironment => false; + + // An example of testing scalability of a method that scales perfectly. + // This method provides a baseline for how well can CommonThreadedBase + // measure scalability. + const int Iterations = 50 * 1000 * 1000; // High number to make the overhead of RunConcurrent negligible. + [Benchmark(OperationsPerInvoke = Iterations)] + public void PerfectScalingExample() + { + RunConcurrent(() => { RunBody(); }); + } + + private int RunBody() + { + int result = 0; + for (int i = 0; i < Iterations; i++) + { + // perform some operation that is completely independent from + // other threads and therefore should scale perfectly if given + // a dedicated thread. + for (int j = 0; j < 100; j++) + { + result = result ^ i ^ j ; + } + } + return result; + } + } +} diff --git a/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs b/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs new file mode 100644 index 00000000..f850a0a0 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/SendMessageBenchmark.cs @@ -0,0 +1,91 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using BenchmarkDotNet.Attributes; +using Grpc.Core; +using Grpc.Core.Internal; + +namespace Grpc.Microbenchmarks +{ + public class SendMessageBenchmark : CommonThreadedBase + { + static readonly NativeMethods Native = NativeMethods.Get(); + + public override void Setup() + { + Native.grpcsharp_test_override_method("grpcsharp_call_start_batch", "nop"); + base.Setup(); + } + + [Params(0)] + public int PayloadSize { get; set; } + + const int Iterations = 5 * 1000 * 1000; // High number to make the overhead of RunConcurrent negligible. + [Benchmark(OperationsPerInvoke = Iterations)] + public void SendMessage() + { + RunConcurrent(RunBody); + } + + private void RunBody() + { + var completionRegistry = new CompletionRegistry(Environment, () => Environment.BatchContextPool.Lease(), () => throw new NotImplementedException()); + var cq = CompletionQueueSafeHandle.CreateAsync(completionRegistry); + var call = CreateFakeCall(cq); + + var sendCompletionCallback = new NopSendCompletionCallback(); + var sliceBuffer = SliceBufferSafeHandle.Create(); + var writeFlags = default(WriteFlags); + + for (int i = 0; i < Iterations; i++) + { + // SendMessage steals the slices from the slice buffer, so we need to repopulate in each iteration. + sliceBuffer.Reset(); + sliceBuffer.GetSpan(PayloadSize); + sliceBuffer.Advance(PayloadSize); + + call.StartSendMessage(sendCompletionCallback, sliceBuffer, writeFlags, false); + var callback = completionRegistry.Extract(completionRegistry.LastRegisteredKey); + callback.OnComplete(true); + } + sliceBuffer.Dispose(); + cq.Dispose(); + } + + private static CallSafeHandle CreateFakeCall(CompletionQueueSafeHandle cq) + { + var call = CallSafeHandle.CreateFake(new IntPtr(0xdead), cq); + bool success = false; + while (!success) + { + // avoid calling destroy on a nonexistent grpc_call pointer + call.DangerousAddRef(ref success); + } + return call; + } + + private class NopSendCompletionCallback : ISendCompletionCallback + { + public void OnSendCompletion(bool success) + { + // NOP + } + } + } +} diff --git a/src/csharp/Grpc.Microbenchmarks/UnaryCallOverheadBenchmark.cs b/src/csharp/Grpc.Microbenchmarks/UnaryCallOverheadBenchmark.cs new file mode 100644 index 00000000..fe193b73 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/UnaryCallOverheadBenchmark.cs @@ -0,0 +1,104 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using Grpc.Core; +using Grpc.Core.Internal; +using System; + +namespace Grpc.Microbenchmarks +{ + // this test measures the overhead of C# wrapping layer when invoking calls; + // the marshallers **DO NOT ALLOCATE**, so any allocations + // are from the framework, not the messages themselves + + [ClrJob, CoreJob] // test .NET Core and .NET Framework + [MemoryDiagnoser] // allocations + public class UnaryCallOverheadBenchmark + { + private static readonly Task CompletedString = Task.FromResult(""); + private static readonly Marshaller IdentityMarshaller = new Marshaller(msg => msg, payload => payload); + private static readonly Method PingMethod = new Method(MethodType.Unary, nameof(PingBenchmark), "Ping", IdentityMarshaller, IdentityMarshaller); + + private int payloadSize; + private byte[] payload; + + // size of payload that is sent as request and received as response. + [Params(0, 1, 10, 100, 1000)] + public int PayloadSize + { + get { return payloadSize; } + set + { + payloadSize = value; + payload = new byte[value]; + } + } + + [Benchmark] + public byte[] SyncUnaryCallOverhead() + { + return client.Ping(payload, new CallOptions()); + } + + Channel channel; + PingClient client; + + [GlobalSetup] + public void Setup() + { + // create client, the channel will actually never connect because call logic will be short-circuited + channel = new Channel("localhost", 10042, ChannelCredentials.Insecure); + client = new PingClient(new DefaultCallInvoker(channel)); + + var native = NativeMethods.Get(); + + // replace the implementation of a native method with a fake + NativeMethods.Delegates.grpcsharp_call_start_unary_delegate fakeCallStartUnary = (CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags) => { + return native.grpcsharp_test_call_start_unary_echo(call, ctx, sendBuffer, writeFlags, metadataArray, metadataFlags); + }; + native.GetType().GetField(nameof(native.grpcsharp_call_start_unary)).SetValue(native, fakeCallStartUnary); + + NativeMethods.Delegates.grpcsharp_completion_queue_pluck_delegate fakeCqPluck = (CompletionQueueSafeHandle cq, IntPtr tag) => { + return new CompletionQueueEvent { + type = CompletionQueueEvent.CompletionType.OpComplete, + success = 1, + tag = tag + }; + }; + native.GetType().GetField(nameof(native.grpcsharp_completion_queue_pluck)).SetValue(native, fakeCqPluck); + } + + [GlobalCleanup] + public async Task Cleanup() + { + await channel.ShutdownAsync(); + } + + class PingClient : ClientBase + { + public PingClient(CallInvoker callInvoker) : base(callInvoker) { } + + public byte[] Ping(byte[] request, CallOptions options) + { + return CallInvoker.BlockingUnaryCall(PingMethod, null, options, request); + } + } + } +} diff --git a/src/csharp/Grpc.Microbenchmarks/Utf8Decode.cs b/src/csharp/Grpc.Microbenchmarks/Utf8Decode.cs new file mode 100644 index 00000000..70bbae6f --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/Utf8Decode.cs @@ -0,0 +1,70 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Text; +using BenchmarkDotNet.Attributes; +using Grpc.Core.Internal; + +namespace Grpc.Microbenchmarks +{ + [ClrJob, CoreJob] // test .NET Core and .NET Framework + [MemoryDiagnoser] // allocations + public class Utf8Decode + { + [Params(0, 1, 4, 128, 1024)] + public int PayloadSize + { + get { return payloadSize; } + set + { + payloadSize = value; + payload = Invent(value); + } + } + + private int payloadSize; + private byte[] payload; + + static byte[] Invent(int length) + { + var rand = new Random(Seed: length); + var chars = new char[length]; + for(int i = 0; i < chars.Length; i++) + { + chars[i] = (char)rand.Next(32, 300); + } + return Encoding.UTF8.GetBytes(chars); + } + + const int Iterations = 1000; + [Benchmark(OperationsPerInvoke = Iterations)] + public unsafe void Decode() + { + fixed (byte* ptr = payload) + { + var iPtr = new IntPtr(ptr); + for (int i = 0; i < Iterations; i++) + { + MarshalUtils.PtrToStringUTF8(iPtr, payload.Length); + } + } + } + } +} diff --git a/src/csharp/Grpc.Microbenchmarks/Utf8Encode.cs b/src/csharp/Grpc.Microbenchmarks/Utf8Encode.cs new file mode 100644 index 00000000..8aa2e968 --- /dev/null +++ b/src/csharp/Grpc.Microbenchmarks/Utf8Encode.cs @@ -0,0 +1,126 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using BenchmarkDotNet.Attributes; +using Grpc.Core; +using Grpc.Core.Internal; + +namespace Grpc.Microbenchmarks +{ + [ClrJob, CoreJob] // test .NET Core and .NET Framework + [MemoryDiagnoser] // allocations + public class Utf8Encode : ISendStatusFromServerCompletionCallback + { + [Params(0, 1, 4, 128, 1024)] + public int PayloadSize + { + get { return payloadSize; } + set + { + payloadSize = value; + status = new Status(StatusCode.OK, Invent(value)); + } + } + + private int payloadSize; + private Status status; + + static string Invent(int length) + { + var rand = new Random(Seed: length); + var chars = new char[length]; + for(int i = 0; i < chars.Length; i++) + { + chars[i] = (char)rand.Next(32, 300); + } + return new string(chars); + } + + private GrpcEnvironment environment; + private CompletionRegistry completionRegistry; + [GlobalSetup] + public void Setup() + { + var native = NativeMethods.Get(); + + // nop the native-call via reflection + NativeMethods.Delegates.grpcsharp_call_send_status_from_server_delegate nop = (CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, SliceBufferSafeHandle optionalSendBuffer, WriteFlags writeFlags) => { + completionRegistry.Extract(ctx.Handle).OnComplete(true); // drain the dictionary as we go + return CallError.OK; + }; + native.GetType().GetField(nameof(native.grpcsharp_call_send_status_from_server)).SetValue(native, nop); + + environment = GrpcEnvironment.AddRef(); + metadata = MetadataArraySafeHandle.Create(Metadata.Empty); + completionRegistry = new CompletionRegistry(environment, () => environment.BatchContextPool.Lease(), () => throw new NotImplementedException()); + var cq = CompletionQueueSafeHandle.CreateAsync(completionRegistry); + call = CreateFakeCall(cq); + } + + private static CallSafeHandle CreateFakeCall(CompletionQueueSafeHandle cq) + { + var call = CallSafeHandle.CreateFake(new IntPtr(0xdead), cq); + bool success = false; + while (!success) + { + // avoid calling destroy on a nonexistent grpc_call pointer + call.DangerousAddRef(ref success); + } + return call; + } + + [GlobalCleanup] + public void Cleanup() + { + try + { + metadata?.Dispose(); + metadata = null; + call?.Dispose(); + call = null; + + if (environment != null) + { + environment = null; + // cleanup seems... unreliable on CLR + // GrpcEnvironment.ReleaseAsync().Wait(1000); + } + } + catch (Exception ex) + { + Console.Error.WriteLine(ex.Message); + } + } + private CallSafeHandle call; + private MetadataArraySafeHandle metadata; + + const int Iterations = 1000; + [Benchmark(OperationsPerInvoke = Iterations)] + public unsafe void SendStatus() + { + for (int i = 0; i < Iterations; i++) + { + call.StartSendStatusFromServer(this, status, metadata, false, SliceBufferSafeHandle.NullInstance, WriteFlags.NoCompress); + } + } + + void ISendStatusFromServerCompletionCallback.OnSendStatusFromServerCompletion(bool success) { } + } +} diff --git a/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs b/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs new file mode 100644 index 00000000..de4b4af6 --- /dev/null +++ b/src/csharp/Grpc.Reflection.Tests/NUnitMain.cs @@ -0,0 +1,40 @@ +#region Copyright notice and license + +// Copyright 2016 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Reflection; +using Grpc.Core; +using Grpc.Core.Logging; +using NUnit.Common; +using NUnitLite; + +namespace Grpc.Reflection.Tests +{ + /// + /// Provides entry point for NUnitLite + /// + public class NUnitMain + { + public static int Main(string[] args) + { + // Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406. + GrpcEnvironment.SetLogger(new ConsoleLogger()); + return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args); + } + } +} diff --git a/src/csharp/Grpc.Reflection.Tests/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Reflection.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..07d61c88 --- /dev/null +++ b/src/csharp/Grpc.Reflection.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.Reflection.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.Reflection.Tests/ReflectionClientServerTest.cs b/src/csharp/Grpc.Reflection.Tests/ReflectionClientServerTest.cs new file mode 100644 index 00000000..b77f2456 --- /dev/null +++ b/src/csharp/Grpc.Reflection.Tests/ReflectionClientServerTest.cs @@ -0,0 +1,140 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Reflection; +using Grpc.Reflection.V1Alpha; +using NUnit.Framework; + +namespace Grpc.Reflection.Tests +{ + /// + /// Reflection client talks to reflection server. + /// + public class ReflectionClientServerTest + { + const string Host = "localhost"; + Server server; + Channel channel; + ServerReflection.ServerReflectionClient client; + ReflectionServiceImpl serviceImpl; + + [OneTimeSetUp] + public void Init() + { + serviceImpl = new ReflectionServiceImpl(ServerReflection.Descriptor); + + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { ServerReflection.BindService(serviceImpl) }, + Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } } + }; + server.Start(); + channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure); + + client = new ServerReflection.ServerReflectionClient(channel); + } + + [OneTimeTearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public async Task FileByFilename_NotFound() + { + var response = await SingleRequestAsync(new ServerReflectionRequest + { + FileByFilename = "somepackage/nonexistent.proto" + }); + Assert.AreEqual((int)StatusCode.NotFound, response.ErrorResponse.ErrorCode); + } + + [Test] + public async Task FileByFilename() + { + var response = await SingleRequestAsync(new ServerReflectionRequest + { + FileByFilename = "grpc/reflection/v1alpha/reflection.proto" + }); + Assert.AreEqual(1, response.FileDescriptorResponse.FileDescriptorProto.Count); + Assert.AreEqual(ReflectionReflection.Descriptor.SerializedData, response.FileDescriptorResponse.FileDescriptorProto[0]); + } + + [Test] + public async Task FileContainingSymbol() + { + var response = await SingleRequestAsync(new ServerReflectionRequest + { + FileContainingSymbol = "grpc.reflection.v1alpha.ServerReflection" + }); + Assert.AreEqual(1, response.FileDescriptorResponse.FileDescriptorProto.Count); + Assert.AreEqual(ReflectionReflection.Descriptor.SerializedData, response.FileDescriptorResponse.FileDescriptorProto[0]); + } + + [Test] + public async Task FileContainingSymbol_NotFound() + { + var response = await SingleRequestAsync(new ServerReflectionRequest + { + FileContainingSymbol = "somepackage.Nonexistent" + }); + Assert.AreEqual((int)StatusCode.NotFound, response.ErrorResponse.ErrorCode); + } + + [Test] + public async Task ListServices() + { + var response = await SingleRequestAsync(new ServerReflectionRequest + { + ListServices = "" + }); + Assert.AreEqual(1, response.ListServicesResponse.Service.Count); + Assert.AreEqual(ServerReflection.Descriptor.FullName, response.ListServicesResponse.Service[0].Name); + } + + [Test] + public async Task FileContainingExtension() + { + var response = await SingleRequestAsync(new ServerReflectionRequest + { + FileContainingExtension = new ExtensionRequest() + }); + Assert.AreEqual((int)StatusCode.Unimplemented, response.ErrorResponse.ErrorCode); + } + + private async Task SingleRequestAsync(ServerReflectionRequest request) + { + var call = client.ServerReflectionInfo(); + await call.RequestStream.WriteAsync(request); + Assert.IsTrue(await call.ResponseStream.MoveNext()); + + var response = call.ResponseStream.Current; + await call.RequestStream.CompleteAsync(); + Assert.IsFalse(await call.ResponseStream.MoveNext()); + return response; + } + } +} diff --git a/src/csharp/Grpc.Reflection.Tests/SymbolRegistryTest.cs b/src/csharp/Grpc.Reflection.Tests/SymbolRegistryTest.cs new file mode 100644 index 00000000..3045a8cd --- /dev/null +++ b/src/csharp/Grpc.Reflection.Tests/SymbolRegistryTest.cs @@ -0,0 +1,48 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion + +using Grpc.Reflection; +using Grpc.Reflection.V1Alpha; +using NUnit.Framework; + + +namespace Grpc.Reflection.Tests +{ + /// + /// Tests for ReflectionServiceImpl + /// + public class SymbolRegistryTest + { + SymbolRegistry registry = SymbolRegistry.FromFiles(new[] { ReflectionReflection.Descriptor, Google.Protobuf.WellKnownTypes.Duration.Descriptor.File }); + + [Test] + public void FileByName() + { + Assert.AreSame(Google.Protobuf.WellKnownTypes.Duration.Descriptor.File, registry.FileByName("google/protobuf/duration.proto")); + Assert.IsNull(registry.FileByName("somepackage/nonexistent.proto")); + } + + [Test] + public void FileContainingSymbol() + { + Assert.AreSame(Google.Protobuf.WellKnownTypes.Duration.Descriptor.File, registry.FileContainingSymbol("google.protobuf.Duration")); + Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo")); // method + Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflection")); // service + Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflectionRequest")); // message + Assert.IsNull(registry.FileContainingSymbol("somepackage.Nonexistent")); + } + } +} diff --git a/src/csharp/Grpc.Reflection/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Reflection/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..fc94f841 --- /dev/null +++ b/src/csharp/Grpc.Reflection/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("Grpc.Reflection")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Google Inc. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] diff --git a/src/csharp/Grpc.Reflection/Reflection.cs b/src/csharp/Grpc.Reflection/Reflection.cs new file mode 100644 index 00000000..ce4b28ba --- /dev/null +++ b/src/csharp/Grpc.Reflection/Reflection.cs @@ -0,0 +1,2290 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: grpc/reflection/v1alpha/reflection.proto +// +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Grpc.Reflection.V1Alpha { + + /// Holder for reflection information generated from grpc/reflection/v1alpha/reflection.proto + public static partial class ReflectionReflection { + + #region Descriptor + /// File descriptor for grpc/reflection/v1alpha/reflection.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static ReflectionReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CihncnBjL3JlZmxlY3Rpb24vdjFhbHBoYS9yZWZsZWN0aW9uLnByb3RvEhdn", + "cnBjLnJlZmxlY3Rpb24udjFhbHBoYSKKAgoXU2VydmVyUmVmbGVjdGlvblJl", + "cXVlc3QSDAoEaG9zdBgBIAEoCRIaChBmaWxlX2J5X2ZpbGVuYW1lGAMgASgJ", + "SAASIAoWZmlsZV9jb250YWluaW5nX3N5bWJvbBgEIAEoCUgAEk4KGWZpbGVf", + "Y29udGFpbmluZ19leHRlbnNpb24YBSABKAsyKS5ncnBjLnJlZmxlY3Rpb24u", + "djFhbHBoYS5FeHRlbnNpb25SZXF1ZXN0SAASJwodYWxsX2V4dGVuc2lvbl9u", + "dW1iZXJzX29mX3R5cGUYBiABKAlIABIXCg1saXN0X3NlcnZpY2VzGAcgASgJ", + "SABCEQoPbWVzc2FnZV9yZXF1ZXN0IkUKEEV4dGVuc2lvblJlcXVlc3QSFwoP", + "Y29udGFpbmluZ190eXBlGAEgASgJEhgKEGV4dGVuc2lvbl9udW1iZXIYAiAB", + "KAUi0QMKGFNlcnZlclJlZmxlY3Rpb25SZXNwb25zZRISCgp2YWxpZF9ob3N0", + "GAEgASgJEkoKEG9yaWdpbmFsX3JlcXVlc3QYAiABKAsyMC5ncnBjLnJlZmxl", + "Y3Rpb24udjFhbHBoYS5TZXJ2ZXJSZWZsZWN0aW9uUmVxdWVzdBJTChhmaWxl", + "X2Rlc2NyaXB0b3JfcmVzcG9uc2UYBCABKAsyLy5ncnBjLnJlZmxlY3Rpb24u", + "djFhbHBoYS5GaWxlRGVzY3JpcHRvclJlc3BvbnNlSAASWgoeYWxsX2V4dGVu", + "c2lvbl9udW1iZXJzX3Jlc3BvbnNlGAUgASgLMjAuZ3JwYy5yZWZsZWN0aW9u", + "LnYxYWxwaGEuRXh0ZW5zaW9uTnVtYmVyUmVzcG9uc2VIABJOChZsaXN0X3Nl", + "cnZpY2VzX3Jlc3BvbnNlGAYgASgLMiwuZ3JwYy5yZWZsZWN0aW9uLnYxYWxw", + "aGEuTGlzdFNlcnZpY2VSZXNwb25zZUgAEkAKDmVycm9yX3Jlc3BvbnNlGAcg", + "ASgLMiYuZ3JwYy5yZWZsZWN0aW9uLnYxYWxwaGEuRXJyb3JSZXNwb25zZUgA", + "QhIKEG1lc3NhZ2VfcmVzcG9uc2UiNwoWRmlsZURlc2NyaXB0b3JSZXNwb25z", + "ZRIdChVmaWxlX2Rlc2NyaXB0b3JfcHJvdG8YASADKAwiSwoXRXh0ZW5zaW9u", + "TnVtYmVyUmVzcG9uc2USFgoOYmFzZV90eXBlX25hbWUYASABKAkSGAoQZXh0", + "ZW5zaW9uX251bWJlchgCIAMoBSJQChNMaXN0U2VydmljZVJlc3BvbnNlEjkK", + "B3NlcnZpY2UYASADKAsyKC5ncnBjLnJlZmxlY3Rpb24udjFhbHBoYS5TZXJ2", + "aWNlUmVzcG9uc2UiHwoPU2VydmljZVJlc3BvbnNlEgwKBG5hbWUYASABKAki", + "OgoNRXJyb3JSZXNwb25zZRISCgplcnJvcl9jb2RlGAEgASgFEhUKDWVycm9y", + "X21lc3NhZ2UYAiABKAkykwEKEFNlcnZlclJlZmxlY3Rpb24SfwoUU2VydmVy", + "UmVmbGVjdGlvbkluZm8SMC5ncnBjLnJlZmxlY3Rpb24udjFhbHBoYS5TZXJ2", + "ZXJSZWZsZWN0aW9uUmVxdWVzdBoxLmdycGMucmVmbGVjdGlvbi52MWFscGhh", + "LlNlcnZlclJlZmxlY3Rpb25SZXNwb25zZSgBMAFiBnByb3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ServerReflectionRequest), global::Grpc.Reflection.V1Alpha.ServerReflectionRequest.Parser, new[]{ "Host", "FileByFilename", "FileContainingSymbol", "FileContainingExtension", "AllExtensionNumbersOfType", "ListServices" }, new[]{ "MessageRequest" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ExtensionRequest), global::Grpc.Reflection.V1Alpha.ExtensionRequest.Parser, new[]{ "ContainingType", "ExtensionNumber" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ServerReflectionResponse), global::Grpc.Reflection.V1Alpha.ServerReflectionResponse.Parser, new[]{ "ValidHost", "OriginalRequest", "FileDescriptorResponse", "AllExtensionNumbersResponse", "ListServicesResponse", "ErrorResponse" }, new[]{ "MessageResponse" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.FileDescriptorResponse), global::Grpc.Reflection.V1Alpha.FileDescriptorResponse.Parser, new[]{ "FileDescriptorProto" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse), global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse.Parser, new[]{ "BaseTypeName", "ExtensionNumber" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ListServiceResponse), global::Grpc.Reflection.V1Alpha.ListServiceResponse.Parser, new[]{ "Service" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ServiceResponse), global::Grpc.Reflection.V1Alpha.ServiceResponse.Parser, new[]{ "Name" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Reflection.V1Alpha.ErrorResponse), global::Grpc.Reflection.V1Alpha.ErrorResponse.Parser, new[]{ "ErrorCode", "ErrorMessage" }, null, null, null, null) + })); + } + #endregion + + } + #region Messages + /// + /// The message sent by the client when calling ServerReflectionInfo method. + /// + public sealed partial class ServerReflectionRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServerReflectionRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerReflectionRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerReflectionRequest(ServerReflectionRequest other) : this() { + host_ = other.host_; + switch (other.MessageRequestCase) { + case MessageRequestOneofCase.FileByFilename: + FileByFilename = other.FileByFilename; + break; + case MessageRequestOneofCase.FileContainingSymbol: + FileContainingSymbol = other.FileContainingSymbol; + break; + case MessageRequestOneofCase.FileContainingExtension: + FileContainingExtension = other.FileContainingExtension.Clone(); + break; + case MessageRequestOneofCase.AllExtensionNumbersOfType: + AllExtensionNumbersOfType = other.AllExtensionNumbersOfType; + break; + case MessageRequestOneofCase.ListServices: + ListServices = other.ListServices; + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerReflectionRequest Clone() { + return new ServerReflectionRequest(this); + } + + /// Field number for the "host" field. + public const int HostFieldNumber = 1; + private string host_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Host { + get { return host_; } + set { + host_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "file_by_filename" field. + public const int FileByFilenameFieldNumber = 3; + /// + /// Find a proto file by the file name. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string FileByFilename { + get { return messageRequestCase_ == MessageRequestOneofCase.FileByFilename ? (string) messageRequest_ : ""; } + set { + messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + messageRequestCase_ = MessageRequestOneofCase.FileByFilename; + } + } + + /// Field number for the "file_containing_symbol" field. + public const int FileContainingSymbolFieldNumber = 4; + /// + /// Find the proto file that declares the given fully-qualified symbol name. + /// This field should be a fully-qualified symbol name + /// (e.g. <package>.<service>[.<method>] or <package>.<type>). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string FileContainingSymbol { + get { return messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol ? (string) messageRequest_ : ""; } + set { + messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + messageRequestCase_ = MessageRequestOneofCase.FileContainingSymbol; + } + } + + /// Field number for the "file_containing_extension" field. + public const int FileContainingExtensionFieldNumber = 5; + /// + /// Find the proto file which defines an extension extending the given + /// message type with the given field number. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Reflection.V1Alpha.ExtensionRequest FileContainingExtension { + get { return messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension ? (global::Grpc.Reflection.V1Alpha.ExtensionRequest) messageRequest_ : null; } + set { + messageRequest_ = value; + messageRequestCase_ = value == null ? MessageRequestOneofCase.None : MessageRequestOneofCase.FileContainingExtension; + } + } + + /// Field number for the "all_extension_numbers_of_type" field. + public const int AllExtensionNumbersOfTypeFieldNumber = 6; + /// + /// Finds the tag numbers used by all known extensions of the given message + /// type, and appends them to ExtensionNumberResponse in an undefined order. + /// Its corresponding method is best-effort: it's not guaranteed that the + /// reflection service will implement this method, and it's not guaranteed + /// that this method will provide all extensions. Returns + /// StatusCode::UNIMPLEMENTED if it's not implemented. + /// This field should be a fully-qualified type name. The format is + /// <package>.<type> + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string AllExtensionNumbersOfType { + get { return messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType ? (string) messageRequest_ : ""; } + set { + messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + messageRequestCase_ = MessageRequestOneofCase.AllExtensionNumbersOfType; + } + } + + /// Field number for the "list_services" field. + public const int ListServicesFieldNumber = 7; + /// + /// List the full names of registered services. The content will not be + /// checked. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ListServices { + get { return messageRequestCase_ == MessageRequestOneofCase.ListServices ? (string) messageRequest_ : ""; } + set { + messageRequest_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + messageRequestCase_ = MessageRequestOneofCase.ListServices; + } + } + + private object messageRequest_; + /// Enum of possible cases for the "message_request" oneof. + public enum MessageRequestOneofCase { + None = 0, + FileByFilename = 3, + FileContainingSymbol = 4, + FileContainingExtension = 5, + AllExtensionNumbersOfType = 6, + ListServices = 7, + } + private MessageRequestOneofCase messageRequestCase_ = MessageRequestOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public MessageRequestOneofCase MessageRequestCase { + get { return messageRequestCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearMessageRequest() { + messageRequestCase_ = MessageRequestOneofCase.None; + messageRequest_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ServerReflectionRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ServerReflectionRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Host != other.Host) return false; + if (FileByFilename != other.FileByFilename) return false; + if (FileContainingSymbol != other.FileContainingSymbol) return false; + if (!object.Equals(FileContainingExtension, other.FileContainingExtension)) return false; + if (AllExtensionNumbersOfType != other.AllExtensionNumbersOfType) return false; + if (ListServices != other.ListServices) return false; + if (MessageRequestCase != other.MessageRequestCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Host.Length != 0) hash ^= Host.GetHashCode(); + if (messageRequestCase_ == MessageRequestOneofCase.FileByFilename) hash ^= FileByFilename.GetHashCode(); + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol) hash ^= FileContainingSymbol.GetHashCode(); + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) hash ^= FileContainingExtension.GetHashCode(); + if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) hash ^= AllExtensionNumbersOfType.GetHashCode(); + if (messageRequestCase_ == MessageRequestOneofCase.ListServices) hash ^= ListServices.GetHashCode(); + hash ^= (int) messageRequestCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Host.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Host); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileByFilename) { + output.WriteRawTag(26); + output.WriteString(FileByFilename); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol) { + output.WriteRawTag(34); + output.WriteString(FileContainingSymbol); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) { + output.WriteRawTag(42); + output.WriteMessage(FileContainingExtension); + } + if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) { + output.WriteRawTag(50); + output.WriteString(AllExtensionNumbersOfType); + } + if (messageRequestCase_ == MessageRequestOneofCase.ListServices) { + output.WriteRawTag(58); + output.WriteString(ListServices); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Host.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Host); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileByFilename) { + output.WriteRawTag(26); + output.WriteString(FileByFilename); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol) { + output.WriteRawTag(34); + output.WriteString(FileContainingSymbol); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) { + output.WriteRawTag(42); + output.WriteMessage(FileContainingExtension); + } + if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) { + output.WriteRawTag(50); + output.WriteString(AllExtensionNumbersOfType); + } + if (messageRequestCase_ == MessageRequestOneofCase.ListServices) { + output.WriteRawTag(58); + output.WriteString(ListServices); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Host.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Host); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileByFilename) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FileByFilename); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingSymbol) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(FileContainingSymbol); + } + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(FileContainingExtension); + } + if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(AllExtensionNumbersOfType); + } + if (messageRequestCase_ == MessageRequestOneofCase.ListServices) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ListServices); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ServerReflectionRequest other) { + if (other == null) { + return; + } + if (other.Host.Length != 0) { + Host = other.Host; + } + switch (other.MessageRequestCase) { + case MessageRequestOneofCase.FileByFilename: + FileByFilename = other.FileByFilename; + break; + case MessageRequestOneofCase.FileContainingSymbol: + FileContainingSymbol = other.FileContainingSymbol; + break; + case MessageRequestOneofCase.FileContainingExtension: + if (FileContainingExtension == null) { + FileContainingExtension = new global::Grpc.Reflection.V1Alpha.ExtensionRequest(); + } + FileContainingExtension.MergeFrom(other.FileContainingExtension); + break; + case MessageRequestOneofCase.AllExtensionNumbersOfType: + AllExtensionNumbersOfType = other.AllExtensionNumbersOfType; + break; + case MessageRequestOneofCase.ListServices: + ListServices = other.ListServices; + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Host = input.ReadString(); + break; + } + case 26: { + FileByFilename = input.ReadString(); + break; + } + case 34: { + FileContainingSymbol = input.ReadString(); + break; + } + case 42: { + global::Grpc.Reflection.V1Alpha.ExtensionRequest subBuilder = new global::Grpc.Reflection.V1Alpha.ExtensionRequest(); + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) { + subBuilder.MergeFrom(FileContainingExtension); + } + input.ReadMessage(subBuilder); + FileContainingExtension = subBuilder; + break; + } + case 50: { + AllExtensionNumbersOfType = input.ReadString(); + break; + } + case 58: { + ListServices = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Host = input.ReadString(); + break; + } + case 26: { + FileByFilename = input.ReadString(); + break; + } + case 34: { + FileContainingSymbol = input.ReadString(); + break; + } + case 42: { + global::Grpc.Reflection.V1Alpha.ExtensionRequest subBuilder = new global::Grpc.Reflection.V1Alpha.ExtensionRequest(); + if (messageRequestCase_ == MessageRequestOneofCase.FileContainingExtension) { + subBuilder.MergeFrom(FileContainingExtension); + } + input.ReadMessage(subBuilder); + FileContainingExtension = subBuilder; + break; + } + case 50: { + AllExtensionNumbersOfType = input.ReadString(); + break; + } + case 58: { + ListServices = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// The type name and extension number sent by the client when requesting + /// file_containing_extension. + /// + public sealed partial class ExtensionRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ExtensionRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ExtensionRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ExtensionRequest(ExtensionRequest other) : this() { + containingType_ = other.containingType_; + extensionNumber_ = other.extensionNumber_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ExtensionRequest Clone() { + return new ExtensionRequest(this); + } + + /// Field number for the "containing_type" field. + public const int ContainingTypeFieldNumber = 1; + private string containingType_ = ""; + /// + /// Fully-qualified type name. The format should be <package>.<type> + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ContainingType { + get { return containingType_; } + set { + containingType_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "extension_number" field. + public const int ExtensionNumberFieldNumber = 2; + private int extensionNumber_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ExtensionNumber { + get { return extensionNumber_; } + set { + extensionNumber_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ExtensionRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ExtensionRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ContainingType != other.ContainingType) return false; + if (ExtensionNumber != other.ExtensionNumber) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (ContainingType.Length != 0) hash ^= ContainingType.GetHashCode(); + if (ExtensionNumber != 0) hash ^= ExtensionNumber.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (ContainingType.Length != 0) { + output.WriteRawTag(10); + output.WriteString(ContainingType); + } + if (ExtensionNumber != 0) { + output.WriteRawTag(16); + output.WriteInt32(ExtensionNumber); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (ContainingType.Length != 0) { + output.WriteRawTag(10); + output.WriteString(ContainingType); + } + if (ExtensionNumber != 0) { + output.WriteRawTag(16); + output.WriteInt32(ExtensionNumber); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (ContainingType.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ContainingType); + } + if (ExtensionNumber != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ExtensionNumber); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ExtensionRequest other) { + if (other == null) { + return; + } + if (other.ContainingType.Length != 0) { + ContainingType = other.ContainingType; + } + if (other.ExtensionNumber != 0) { + ExtensionNumber = other.ExtensionNumber; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + ContainingType = input.ReadString(); + break; + } + case 16: { + ExtensionNumber = input.ReadInt32(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + ContainingType = input.ReadString(); + break; + } + case 16: { + ExtensionNumber = input.ReadInt32(); + break; + } + } + } + } + #endif + + } + + /// + /// The message sent by the server to answer ServerReflectionInfo method. + /// + public sealed partial class ServerReflectionResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServerReflectionResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerReflectionResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerReflectionResponse(ServerReflectionResponse other) : this() { + validHost_ = other.validHost_; + originalRequest_ = other.originalRequest_ != null ? other.originalRequest_.Clone() : null; + switch (other.MessageResponseCase) { + case MessageResponseOneofCase.FileDescriptorResponse: + FileDescriptorResponse = other.FileDescriptorResponse.Clone(); + break; + case MessageResponseOneofCase.AllExtensionNumbersResponse: + AllExtensionNumbersResponse = other.AllExtensionNumbersResponse.Clone(); + break; + case MessageResponseOneofCase.ListServicesResponse: + ListServicesResponse = other.ListServicesResponse.Clone(); + break; + case MessageResponseOneofCase.ErrorResponse: + ErrorResponse = other.ErrorResponse.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServerReflectionResponse Clone() { + return new ServerReflectionResponse(this); + } + + /// Field number for the "valid_host" field. + public const int ValidHostFieldNumber = 1; + private string validHost_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ValidHost { + get { return validHost_; } + set { + validHost_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "original_request" field. + public const int OriginalRequestFieldNumber = 2; + private global::Grpc.Reflection.V1Alpha.ServerReflectionRequest originalRequest_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Reflection.V1Alpha.ServerReflectionRequest OriginalRequest { + get { return originalRequest_; } + set { + originalRequest_ = value; + } + } + + /// Field number for the "file_descriptor_response" field. + public const int FileDescriptorResponseFieldNumber = 4; + /// + /// This message is used to answer file_by_filename, file_containing_symbol, + /// file_containing_extension requests with transitive dependencies. As + /// the repeated label is not allowed in oneof fields, we use a + /// FileDescriptorResponse message to encapsulate the repeated fields. + /// The reflection service is allowed to avoid sending FileDescriptorProtos + /// that were previously sent in response to earlier requests in the stream. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Reflection.V1Alpha.FileDescriptorResponse FileDescriptorResponse { + get { return messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse ? (global::Grpc.Reflection.V1Alpha.FileDescriptorResponse) messageResponse_ : null; } + set { + messageResponse_ = value; + messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.FileDescriptorResponse; + } + } + + /// Field number for the "all_extension_numbers_response" field. + public const int AllExtensionNumbersResponseFieldNumber = 5; + /// + /// This message is used to answer all_extension_numbers_of_type requst. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse AllExtensionNumbersResponse { + get { return messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse ? (global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse) messageResponse_ : null; } + set { + messageResponse_ = value; + messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.AllExtensionNumbersResponse; + } + } + + /// Field number for the "list_services_response" field. + public const int ListServicesResponseFieldNumber = 6; + /// + /// This message is used to answer list_services request. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Reflection.V1Alpha.ListServiceResponse ListServicesResponse { + get { return messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse ? (global::Grpc.Reflection.V1Alpha.ListServiceResponse) messageResponse_ : null; } + set { + messageResponse_ = value; + messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.ListServicesResponse; + } + } + + /// Field number for the "error_response" field. + public const int ErrorResponseFieldNumber = 7; + /// + /// This message is used when an error occurs. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Grpc.Reflection.V1Alpha.ErrorResponse ErrorResponse { + get { return messageResponseCase_ == MessageResponseOneofCase.ErrorResponse ? (global::Grpc.Reflection.V1Alpha.ErrorResponse) messageResponse_ : null; } + set { + messageResponse_ = value; + messageResponseCase_ = value == null ? MessageResponseOneofCase.None : MessageResponseOneofCase.ErrorResponse; + } + } + + private object messageResponse_; + /// Enum of possible cases for the "message_response" oneof. + public enum MessageResponseOneofCase { + None = 0, + FileDescriptorResponse = 4, + AllExtensionNumbersResponse = 5, + ListServicesResponse = 6, + ErrorResponse = 7, + } + private MessageResponseOneofCase messageResponseCase_ = MessageResponseOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public MessageResponseOneofCase MessageResponseCase { + get { return messageResponseCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearMessageResponse() { + messageResponseCase_ = MessageResponseOneofCase.None; + messageResponse_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ServerReflectionResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ServerReflectionResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ValidHost != other.ValidHost) return false; + if (!object.Equals(OriginalRequest, other.OriginalRequest)) return false; + if (!object.Equals(FileDescriptorResponse, other.FileDescriptorResponse)) return false; + if (!object.Equals(AllExtensionNumbersResponse, other.AllExtensionNumbersResponse)) return false; + if (!object.Equals(ListServicesResponse, other.ListServicesResponse)) return false; + if (!object.Equals(ErrorResponse, other.ErrorResponse)) return false; + if (MessageResponseCase != other.MessageResponseCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (ValidHost.Length != 0) hash ^= ValidHost.GetHashCode(); + if (originalRequest_ != null) hash ^= OriginalRequest.GetHashCode(); + if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) hash ^= FileDescriptorResponse.GetHashCode(); + if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) hash ^= AllExtensionNumbersResponse.GetHashCode(); + if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) hash ^= ListServicesResponse.GetHashCode(); + if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) hash ^= ErrorResponse.GetHashCode(); + hash ^= (int) messageResponseCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (ValidHost.Length != 0) { + output.WriteRawTag(10); + output.WriteString(ValidHost); + } + if (originalRequest_ != null) { + output.WriteRawTag(18); + output.WriteMessage(OriginalRequest); + } + if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) { + output.WriteRawTag(34); + output.WriteMessage(FileDescriptorResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) { + output.WriteRawTag(42); + output.WriteMessage(AllExtensionNumbersResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) { + output.WriteRawTag(50); + output.WriteMessage(ListServicesResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) { + output.WriteRawTag(58); + output.WriteMessage(ErrorResponse); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (ValidHost.Length != 0) { + output.WriteRawTag(10); + output.WriteString(ValidHost); + } + if (originalRequest_ != null) { + output.WriteRawTag(18); + output.WriteMessage(OriginalRequest); + } + if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) { + output.WriteRawTag(34); + output.WriteMessage(FileDescriptorResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) { + output.WriteRawTag(42); + output.WriteMessage(AllExtensionNumbersResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) { + output.WriteRawTag(50); + output.WriteMessage(ListServicesResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) { + output.WriteRawTag(58); + output.WriteMessage(ErrorResponse); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (ValidHost.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ValidHost); + } + if (originalRequest_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(OriginalRequest); + } + if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(FileDescriptorResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(AllExtensionNumbersResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ListServicesResponse); + } + if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ErrorResponse); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ServerReflectionResponse other) { + if (other == null) { + return; + } + if (other.ValidHost.Length != 0) { + ValidHost = other.ValidHost; + } + if (other.originalRequest_ != null) { + if (originalRequest_ == null) { + OriginalRequest = new global::Grpc.Reflection.V1Alpha.ServerReflectionRequest(); + } + OriginalRequest.MergeFrom(other.OriginalRequest); + } + switch (other.MessageResponseCase) { + case MessageResponseOneofCase.FileDescriptorResponse: + if (FileDescriptorResponse == null) { + FileDescriptorResponse = new global::Grpc.Reflection.V1Alpha.FileDescriptorResponse(); + } + FileDescriptorResponse.MergeFrom(other.FileDescriptorResponse); + break; + case MessageResponseOneofCase.AllExtensionNumbersResponse: + if (AllExtensionNumbersResponse == null) { + AllExtensionNumbersResponse = new global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse(); + } + AllExtensionNumbersResponse.MergeFrom(other.AllExtensionNumbersResponse); + break; + case MessageResponseOneofCase.ListServicesResponse: + if (ListServicesResponse == null) { + ListServicesResponse = new global::Grpc.Reflection.V1Alpha.ListServiceResponse(); + } + ListServicesResponse.MergeFrom(other.ListServicesResponse); + break; + case MessageResponseOneofCase.ErrorResponse: + if (ErrorResponse == null) { + ErrorResponse = new global::Grpc.Reflection.V1Alpha.ErrorResponse(); + } + ErrorResponse.MergeFrom(other.ErrorResponse); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + ValidHost = input.ReadString(); + break; + } + case 18: { + if (originalRequest_ == null) { + OriginalRequest = new global::Grpc.Reflection.V1Alpha.ServerReflectionRequest(); + } + input.ReadMessage(OriginalRequest); + break; + } + case 34: { + global::Grpc.Reflection.V1Alpha.FileDescriptorResponse subBuilder = new global::Grpc.Reflection.V1Alpha.FileDescriptorResponse(); + if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) { + subBuilder.MergeFrom(FileDescriptorResponse); + } + input.ReadMessage(subBuilder); + FileDescriptorResponse = subBuilder; + break; + } + case 42: { + global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse(); + if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) { + subBuilder.MergeFrom(AllExtensionNumbersResponse); + } + input.ReadMessage(subBuilder); + AllExtensionNumbersResponse = subBuilder; + break; + } + case 50: { + global::Grpc.Reflection.V1Alpha.ListServiceResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ListServiceResponse(); + if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) { + subBuilder.MergeFrom(ListServicesResponse); + } + input.ReadMessage(subBuilder); + ListServicesResponse = subBuilder; + break; + } + case 58: { + global::Grpc.Reflection.V1Alpha.ErrorResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ErrorResponse(); + if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) { + subBuilder.MergeFrom(ErrorResponse); + } + input.ReadMessage(subBuilder); + ErrorResponse = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + ValidHost = input.ReadString(); + break; + } + case 18: { + if (originalRequest_ == null) { + OriginalRequest = new global::Grpc.Reflection.V1Alpha.ServerReflectionRequest(); + } + input.ReadMessage(OriginalRequest); + break; + } + case 34: { + global::Grpc.Reflection.V1Alpha.FileDescriptorResponse subBuilder = new global::Grpc.Reflection.V1Alpha.FileDescriptorResponse(); + if (messageResponseCase_ == MessageResponseOneofCase.FileDescriptorResponse) { + subBuilder.MergeFrom(FileDescriptorResponse); + } + input.ReadMessage(subBuilder); + FileDescriptorResponse = subBuilder; + break; + } + case 42: { + global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ExtensionNumberResponse(); + if (messageResponseCase_ == MessageResponseOneofCase.AllExtensionNumbersResponse) { + subBuilder.MergeFrom(AllExtensionNumbersResponse); + } + input.ReadMessage(subBuilder); + AllExtensionNumbersResponse = subBuilder; + break; + } + case 50: { + global::Grpc.Reflection.V1Alpha.ListServiceResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ListServiceResponse(); + if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) { + subBuilder.MergeFrom(ListServicesResponse); + } + input.ReadMessage(subBuilder); + ListServicesResponse = subBuilder; + break; + } + case 58: { + global::Grpc.Reflection.V1Alpha.ErrorResponse subBuilder = new global::Grpc.Reflection.V1Alpha.ErrorResponse(); + if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) { + subBuilder.MergeFrom(ErrorResponse); + } + input.ReadMessage(subBuilder); + ErrorResponse = subBuilder; + break; + } + } + } + } + #endif + + } + + /// + /// Serialized FileDescriptorProto messages sent by the server answering + /// a file_by_filename, file_containing_symbol, or file_containing_extension + /// request. + /// + public sealed partial class FileDescriptorResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FileDescriptorResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public FileDescriptorResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public FileDescriptorResponse(FileDescriptorResponse other) : this() { + fileDescriptorProto_ = other.fileDescriptorProto_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public FileDescriptorResponse Clone() { + return new FileDescriptorResponse(this); + } + + /// Field number for the "file_descriptor_proto" field. + public const int FileDescriptorProtoFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_fileDescriptorProto_codec + = pb::FieldCodec.ForBytes(10); + private readonly pbc::RepeatedField fileDescriptorProto_ = new pbc::RepeatedField(); + /// + /// Serialized FileDescriptorProto messages. We avoid taking a dependency on + /// descriptor.proto, which uses proto2 only features, by making them opaque + /// bytes instead. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField FileDescriptorProto { + get { return fileDescriptorProto_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as FileDescriptorResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(FileDescriptorResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!fileDescriptorProto_.Equals(other.fileDescriptorProto_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + hash ^= fileDescriptorProto_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + fileDescriptorProto_.WriteTo(output, _repeated_fileDescriptorProto_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + fileDescriptorProto_.WriteTo(ref output, _repeated_fileDescriptorProto_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + size += fileDescriptorProto_.CalculateSize(_repeated_fileDescriptorProto_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(FileDescriptorResponse other) { + if (other == null) { + return; + } + fileDescriptorProto_.Add(other.fileDescriptorProto_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + fileDescriptorProto_.AddEntriesFrom(input, _repeated_fileDescriptorProto_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + fileDescriptorProto_.AddEntriesFrom(ref input, _repeated_fileDescriptorProto_codec); + break; + } + } + } + } + #endif + + } + + /// + /// A list of extension numbers sent by the server answering + /// all_extension_numbers_of_type request. + /// + public sealed partial class ExtensionNumberResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ExtensionNumberResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ExtensionNumberResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ExtensionNumberResponse(ExtensionNumberResponse other) : this() { + baseTypeName_ = other.baseTypeName_; + extensionNumber_ = other.extensionNumber_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ExtensionNumberResponse Clone() { + return new ExtensionNumberResponse(this); + } + + /// Field number for the "base_type_name" field. + public const int BaseTypeNameFieldNumber = 1; + private string baseTypeName_ = ""; + /// + /// Full name of the base type, including the package name. The format + /// is <package>.<type> + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string BaseTypeName { + get { return baseTypeName_; } + set { + baseTypeName_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "extension_number" field. + public const int ExtensionNumberFieldNumber = 2; + private static readonly pb::FieldCodec _repeated_extensionNumber_codec + = pb::FieldCodec.ForInt32(18); + private readonly pbc::RepeatedField extensionNumber_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField ExtensionNumber { + get { return extensionNumber_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ExtensionNumberResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ExtensionNumberResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (BaseTypeName != other.BaseTypeName) return false; + if(!extensionNumber_.Equals(other.extensionNumber_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (BaseTypeName.Length != 0) hash ^= BaseTypeName.GetHashCode(); + hash ^= extensionNumber_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (BaseTypeName.Length != 0) { + output.WriteRawTag(10); + output.WriteString(BaseTypeName); + } + extensionNumber_.WriteTo(output, _repeated_extensionNumber_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (BaseTypeName.Length != 0) { + output.WriteRawTag(10); + output.WriteString(BaseTypeName); + } + extensionNumber_.WriteTo(ref output, _repeated_extensionNumber_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (BaseTypeName.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(BaseTypeName); + } + size += extensionNumber_.CalculateSize(_repeated_extensionNumber_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ExtensionNumberResponse other) { + if (other == null) { + return; + } + if (other.BaseTypeName.Length != 0) { + BaseTypeName = other.BaseTypeName; + } + extensionNumber_.Add(other.extensionNumber_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + BaseTypeName = input.ReadString(); + break; + } + case 18: + case 16: { + extensionNumber_.AddEntriesFrom(input, _repeated_extensionNumber_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + BaseTypeName = input.ReadString(); + break; + } + case 18: + case 16: { + extensionNumber_.AddEntriesFrom(ref input, _repeated_extensionNumber_codec); + break; + } + } + } + } + #endif + + } + + /// + /// A list of ServiceResponse sent by the server answering list_services request. + /// + public sealed partial class ListServiceResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ListServiceResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ListServiceResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ListServiceResponse(ListServiceResponse other) : this() { + service_ = other.service_.Clone(); + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ListServiceResponse Clone() { + return new ListServiceResponse(this); + } + + /// Field number for the "service" field. + public const int ServiceFieldNumber = 1; + private static readonly pb::FieldCodec _repeated_service_codec + = pb::FieldCodec.ForMessage(10, global::Grpc.Reflection.V1Alpha.ServiceResponse.Parser); + private readonly pbc::RepeatedField service_ = new pbc::RepeatedField(); + /// + /// The information of each service may be expanded in the future, so we use + /// ServiceResponse message to encapsulate it. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Service { + get { return service_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ListServiceResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ListServiceResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if(!service_.Equals(other.service_)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + hash ^= service_.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + service_.WriteTo(output, _repeated_service_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + service_.WriteTo(ref output, _repeated_service_codec); + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + size += service_.CalculateSize(_repeated_service_codec); + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ListServiceResponse other) { + if (other == null) { + return; + } + service_.Add(other.service_); + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + service_.AddEntriesFrom(input, _repeated_service_codec); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + service_.AddEntriesFrom(ref input, _repeated_service_codec); + break; + } + } + } + } + #endif + + } + + /// + /// The information of a single service used by ListServiceResponse to answer + /// list_services request. + /// + public sealed partial class ServiceResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ServiceResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[6]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServiceResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServiceResponse(ServiceResponse other) : this() { + name_ = other.name_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ServiceResponse Clone() { + return new ServiceResponse(this); + } + + /// Field number for the "name" field. + public const int NameFieldNumber = 1; + private string name_ = ""; + /// + /// Full name of a registered service, including its package name. The format + /// is <package>.<service> + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Name { + get { return name_; } + set { + name_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ServiceResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ServiceResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Name != other.Name) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Name.Length != 0) hash ^= Name.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Name.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Name); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Name.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Name); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ServiceResponse other) { + if (other == null) { + return; + } + if (other.Name.Length != 0) { + Name = other.Name; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Name = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Name = input.ReadString(); + break; + } + } + } + } + #endif + + } + + /// + /// The error code and error message sent by the server when an error occurs. + /// + public sealed partial class ErrorResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ErrorResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.MessageTypes[7]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ErrorResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ErrorResponse(ErrorResponse other) : this() { + errorCode_ = other.errorCode_; + errorMessage_ = other.errorMessage_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ErrorResponse Clone() { + return new ErrorResponse(this); + } + + /// Field number for the "error_code" field. + public const int ErrorCodeFieldNumber = 1; + private int errorCode_; + /// + /// This field uses the error codes defined in grpc::StatusCode. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int ErrorCode { + get { return errorCode_; } + set { + errorCode_ = value; + } + } + + /// Field number for the "error_message" field. + public const int ErrorMessageFieldNumber = 2; + private string errorMessage_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ErrorMessage { + get { return errorMessage_; } + set { + errorMessage_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ErrorResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ErrorResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ErrorCode != other.ErrorCode) return false; + if (ErrorMessage != other.ErrorMessage) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (ErrorCode != 0) hash ^= ErrorCode.GetHashCode(); + if (ErrorMessage.Length != 0) hash ^= ErrorMessage.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (ErrorCode != 0) { + output.WriteRawTag(8); + output.WriteInt32(ErrorCode); + } + if (ErrorMessage.Length != 0) { + output.WriteRawTag(18); + output.WriteString(ErrorMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (ErrorCode != 0) { + output.WriteRawTag(8); + output.WriteInt32(ErrorCode); + } + if (ErrorMessage.Length != 0) { + output.WriteRawTag(18); + output.WriteString(ErrorMessage); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (ErrorCode != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ErrorCode); + } + if (ErrorMessage.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ErrorMessage); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ErrorResponse other) { + if (other == null) { + return; + } + if (other.ErrorCode != 0) { + ErrorCode = other.ErrorCode; + } + if (other.ErrorMessage.Length != 0) { + ErrorMessage = other.ErrorMessage; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + ErrorCode = input.ReadInt32(); + break; + } + case 18: { + ErrorMessage = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + ErrorCode = input.ReadInt32(); + break; + } + case 18: { + ErrorMessage = input.ReadString(); + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs new file mode 100644 index 00000000..2dd819ee --- /dev/null +++ b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs @@ -0,0 +1,184 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: grpc/reflection/v1alpha/reflection.proto +// +// Original file comments: +// Copyright 2016 gRPC authors. +// +// 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. +// +// Service exported by server reflection +// +#pragma warning disable 0414, 1591 +#region Designer generated code + +using grpc = global::Grpc.Core; + +namespace Grpc.Reflection.V1Alpha { + public static partial class ServerReflection + { + static readonly string __ServiceName = "grpc.reflection.v1alpha.ServerReflection"; + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context) + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (message is global::Google.Protobuf.IBufferMessage) + { + context.SetPayloadLength(message.CalculateSize()); + global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter()); + context.Complete(); + return; + } + #endif + context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static class __Helper_MessageCache + { + public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static T __Helper_DeserializeMessage(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser parser) where T : global::Google.Protobuf.IMessage + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (__Helper_MessageCache.IsBufferMessage) + { + return parser.ParseFrom(context.PayloadAsReadOnlySequence()); + } + #endif + return parser.ParseFrom(context.PayloadAsNewBuffer()); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_reflection_v1alpha_ServerReflectionRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Reflection.V1Alpha.ServerReflectionRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_grpc_reflection_v1alpha_ServerReflectionResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse.Parser)); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_ServerReflectionInfo = new grpc::Method( + grpc::MethodType.DuplexStreaming, + __ServiceName, + "ServerReflectionInfo", + __Marshaller_grpc_reflection_v1alpha_ServerReflectionRequest, + __Marshaller_grpc_reflection_v1alpha_ServerReflectionResponse); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.Services[0]; } + } + + /// Base class for server-side implementations of ServerReflection + [grpc::BindServiceMethod(typeof(ServerReflection), "BindService")] + public abstract partial class ServerReflectionBase + { + /// + /// The reflection service is structured as a bidirectional stream, ensuring + /// all related requests go to a single server. + /// + /// Used for reading requests from the client. + /// Used for sending responses back to the client. + /// The context of the server-side call handler being invoked. + /// A task indicating completion of the handler. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::System.Threading.Tasks.Task ServerReflectionInfo(grpc::IAsyncStreamReader requestStream, grpc::IServerStreamWriter responseStream, grpc::ServerCallContext context) + { + throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, "")); + } + + } + + /// Client for ServerReflection + public partial class ServerReflectionClient : grpc::ClientBase + { + /// Creates a new client for ServerReflection + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public ServerReflectionClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for ServerReflection that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public ServerReflectionClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected ServerReflectionClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected ServerReflectionClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + /// + /// The reflection service is structured as a bidirectional stream, ensuring + /// all related requests go to a single server. + /// + /// The initial metadata to send with the call. This parameter is optional. + /// An optional deadline for the call. The call will be cancelled if deadline is hit. + /// An optional token for canceling the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall ServerReflectionInfo(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return ServerReflectionInfo(new grpc::CallOptions(headers, deadline, cancellationToken)); + } + /// + /// The reflection service is structured as a bidirectional stream, ensuring + /// all related requests go to a single server. + /// + /// The options for the call. + /// The call object. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall ServerReflectionInfo(grpc::CallOptions options) + { + return CallInvoker.AsyncDuplexStreamingCall(__Method_ServerReflectionInfo, null, options); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override ServerReflectionClient NewInstance(ClientBaseConfiguration configuration) + { + return new ServerReflectionClient(configuration); + } + } + + /// Creates service definition that can be registered with a server + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static grpc::ServerServiceDefinition BindService(ServerReflectionBase serviceImpl) + { + return grpc::ServerServiceDefinition.CreateBuilder() + .AddMethod(__Method_ServerReflectionInfo, serviceImpl.ServerReflectionInfo).Build(); + } + + /// Register service method with a service binder with or without implementation. Useful when customizing the service binding logic. + /// Note: this method is part of an experimental API that can change or be removed without any prior notice. + /// Service methods will be bound by calling AddMethod on this object. + /// An object implementing the server-side handling logic. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public static void BindService(grpc::ServiceBinderBase serviceBinder, ServerReflectionBase serviceImpl) + { + serviceBinder.AddMethod(__Method_ServerReflectionInfo, serviceImpl == null ? null : new grpc::DuplexStreamingServerMethod(serviceImpl.ServerReflectionInfo)); + } + + } +} +#endregion diff --git a/src/csharp/Grpc.Reflection/ReflectionServiceImpl.cs b/src/csharp/Grpc.Reflection/ReflectionServiceImpl.cs new file mode 100644 index 00000000..1eaf10bf --- /dev/null +++ b/src/csharp/Grpc.Reflection/ReflectionServiceImpl.cs @@ -0,0 +1,161 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Core.Utils; +using Grpc.Reflection.V1Alpha; +using Google.Protobuf.Reflection; + +namespace Grpc.Reflection +{ + /// + /// Implementation of server reflection service. + /// + public class ReflectionServiceImpl : Grpc.Reflection.V1Alpha.ServerReflection.ServerReflectionBase + { + readonly List services; + readonly SymbolRegistry symbolRegistry; + + /// + /// Creates a new instance of ReflectionServiceIml. + /// + public ReflectionServiceImpl(IEnumerable services, SymbolRegistry symbolRegistry) + { + this.services = new List(services); + this.symbolRegistry = symbolRegistry; + } + + /// + /// Creates a new instance of ReflectionServiceIml. + /// + public ReflectionServiceImpl(IEnumerable serviceDescriptors) + { + this.services = new List(serviceDescriptors.Select((serviceDescriptor) => serviceDescriptor.FullName)); + this.symbolRegistry = SymbolRegistry.FromFiles(serviceDescriptors.Select((serviceDescriptor) => serviceDescriptor.File)); + } + + /// + /// Creates a new instance of ReflectionServiceIml. + /// + public ReflectionServiceImpl(params ServiceDescriptor[] serviceDescriptors) : this((IEnumerable) serviceDescriptors) + { + } + + /// + /// Processes a stream of server reflection requests. + /// + public override async Task ServerReflectionInfo(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) + { + while (await requestStream.MoveNext()) + { + var response = ProcessRequest(requestStream.Current); + await responseStream.WriteAsync(response); + } + } + + ServerReflectionResponse ProcessRequest(ServerReflectionRequest request) + { + switch (request.MessageRequestCase) + { + case ServerReflectionRequest.MessageRequestOneofCase.FileByFilename: + return FileByFilename(request.FileByFilename); + case ServerReflectionRequest.MessageRequestOneofCase.FileContainingSymbol: + return FileContainingSymbol(request.FileContainingSymbol); + case ServerReflectionRequest.MessageRequestOneofCase.ListServices: + return ListServices(); + case ServerReflectionRequest.MessageRequestOneofCase.AllExtensionNumbersOfType: + case ServerReflectionRequest.MessageRequestOneofCase.FileContainingExtension: + default: + return CreateErrorResponse(StatusCode.Unimplemented, "Request type not supported by C# reflection service."); + } + } + + ServerReflectionResponse FileByFilename(string filename) + { + FileDescriptor file = symbolRegistry.FileByName(filename); + if (file == null) + { + return CreateErrorResponse(StatusCode.NotFound, "File not found."); + } + + var transitiveDependencies = new HashSet(); + CollectTransitiveDependencies(file, transitiveDependencies); + + return new ServerReflectionResponse + { + FileDescriptorResponse = new FileDescriptorResponse { FileDescriptorProto = { transitiveDependencies.Select((d) => d.SerializedData) } } + }; + } + + ServerReflectionResponse FileContainingSymbol(string symbol) + { + FileDescriptor file = symbolRegistry.FileContainingSymbol(symbol); + if (file == null) + { + return CreateErrorResponse(StatusCode.NotFound, "Symbol not found."); + } + + var transitiveDependencies = new HashSet(); + CollectTransitiveDependencies(file, transitiveDependencies); + + return new ServerReflectionResponse + { + FileDescriptorResponse = new FileDescriptorResponse { FileDescriptorProto = { transitiveDependencies.Select((d) => d.SerializedData) } } + }; + } + + ServerReflectionResponse ListServices() + { + var serviceResponses = new ListServiceResponse(); + foreach (string serviceName in services) + { + serviceResponses.Service.Add(new ServiceResponse { Name = serviceName }); + } + + return new ServerReflectionResponse + { + ListServicesResponse = serviceResponses + }; + } + + ServerReflectionResponse CreateErrorResponse(StatusCode status, string message) + { + return new ServerReflectionResponse + { + ErrorResponse = new ErrorResponse { ErrorCode = (int) status, ErrorMessage = message } + }; + } + + void CollectTransitiveDependencies(FileDescriptor descriptor, HashSet pool) + { + pool.Add(descriptor); + foreach (var dependency in descriptor.Dependencies) + { + if (pool.Add(dependency)) + { + // descriptors cannot have circular dependencies + CollectTransitiveDependencies(dependency, pool); + } + } + } + } +} diff --git a/src/csharp/Grpc.Reflection/SymbolRegistry.cs b/src/csharp/Grpc.Reflection/SymbolRegistry.cs new file mode 100644 index 00000000..76e0b01d --- /dev/null +++ b/src/csharp/Grpc.Reflection/SymbolRegistry.cs @@ -0,0 +1,145 @@ +#region Copyright notice and license +// Copyright 2015 gRPC authors. +// +// 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. +#endregion + +using System.Collections.Generic; +using Grpc.Core.Utils; +using Google.Protobuf.Reflection; + +namespace Grpc.Reflection +{ + /// Registry of protobuf symbols + public class SymbolRegistry + { + private readonly Dictionary filesByName; + private readonly Dictionary filesBySymbol; + + private SymbolRegistry(Dictionary filesByName, Dictionary filesBySymbol) + { + this.filesByName = new Dictionary(filesByName); + this.filesBySymbol = new Dictionary(filesBySymbol); + } + + /// + /// Creates a symbol registry from the specified set of file descriptors. + /// + /// The set of files to include in the registry. Must not contain null values. + /// A symbol registry for the given files. + public static SymbolRegistry FromFiles(IEnumerable fileDescriptors) + { + GrpcPreconditions.CheckNotNull(fileDescriptors); + var builder = new Builder(); + foreach (var file in fileDescriptors) + { + builder.AddFile(file); + } + return builder.Build(); + } + + /// + /// Gets file descriptor for given file name (including package path). Returns null if not found. + /// + public FileDescriptor FileByName(string filename) + { + FileDescriptor file; + filesByName.TryGetValue(filename, out file); + return file; + } + + /// + /// Gets file descriptor that contains definition of given symbol full name (including package path). Returns null if not found. + /// + public FileDescriptor FileContainingSymbol(string symbol) + { + FileDescriptor file; + filesBySymbol.TryGetValue(symbol, out file); + return file; + } + + /// + /// Builder class which isn't exposed, but acts as a convenient alternative to passing round two dictionaries in recursive calls. + /// + private class Builder + { + private readonly Dictionary filesByName; + private readonly Dictionary filesBySymbol; + + + internal Builder() + { + filesByName = new Dictionary(); + filesBySymbol = new Dictionary(); + } + + internal void AddFile(FileDescriptor fileDescriptor) + { + if (filesByName.ContainsKey(fileDescriptor.Name)) + { + return; + } + filesByName.Add(fileDescriptor.Name, fileDescriptor); + + foreach (var dependency in fileDescriptor.Dependencies) + { + AddFile(dependency); + } + foreach (var enumeration in fileDescriptor.EnumTypes) + { + AddEnum(enumeration); + } + foreach (var message in fileDescriptor.MessageTypes) + { + AddMessage(message); + } + foreach (var service in fileDescriptor.Services) + { + AddService(service); + } + } + + private void AddEnum(EnumDescriptor enumDescriptor) + { + filesBySymbol[enumDescriptor.FullName] = enumDescriptor.File; + } + + private void AddMessage(MessageDescriptor messageDescriptor) + { + foreach (var nestedEnum in messageDescriptor.EnumTypes) + { + AddEnum(nestedEnum); + } + foreach (var nestedType in messageDescriptor.NestedTypes) + { + AddMessage(nestedType); + } + filesBySymbol[messageDescriptor.FullName] = messageDescriptor.File; + } + + private void AddService(ServiceDescriptor serviceDescriptor) + { + foreach (var method in serviceDescriptor.Methods) + { + filesBySymbol[method.FullName] = method.File; + } + filesBySymbol[serviceDescriptor.FullName] = serviceDescriptor.File; + } + + internal SymbolRegistry Build() + { + return new SymbolRegistry(filesByName, filesBySymbol); + } + } + } +} diff --git a/src/csharp/Grpc.Tools.Tests/CSharpGeneratorTest.cs b/src/csharp/Grpc.Tools.Tests/CSharpGeneratorTest.cs new file mode 100644 index 00000000..c53f0bdf --- /dev/null +++ b/src/csharp/Grpc.Tools.Tests/CSharpGeneratorTest.cs @@ -0,0 +1,98 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using NUnit.Framework; + +namespace Grpc.Tools.Tests +{ + public class CSharpGeneratorTest : GeneratorTest + { + GeneratorServices _generator; + + [SetUp] + public new void SetUp() + { + _generator = GeneratorServices.GetForLanguage("CSharp", _log); + } + + [TestCase("foo.proto", "Foo.cs", "FooGrpc.cs")] + [TestCase("sub/foo.proto", "Foo.cs", "FooGrpc.cs")] + [TestCase("one_two.proto", "OneTwo.cs", "OneTwoGrpc.cs")] + [TestCase("ONE_TWO.proto", "ONETWO.cs", "ONETWOGrpc.cs")] + [TestCase("one.two.proto", "OneTwo.cs", "One.twoGrpc.cs")] + [TestCase("one123two.proto", "One123Two.cs", "One123twoGrpc.cs")] + [TestCase("__one_two!.proto", "OneTwo.cs", "OneTwo!Grpc.cs")] + [TestCase("one(two).proto", "OneTwo.cs", "One(two)Grpc.cs")] + [TestCase("one_(two).proto", "OneTwo.cs", "One(two)Grpc.cs")] + [TestCase("one two.proto", "OneTwo.cs", "One twoGrpc.cs")] + [TestCase("one_ two.proto", "OneTwo.cs", "One twoGrpc.cs")] + [TestCase("one .proto", "One.cs", "One Grpc.cs")] + public void NameMangling(string proto, string expectCs, string expectGrpcCs) + { + var poss = _generator.GetPossibleOutputs(Utils.MakeItem(proto, "grpcservices", "both")); + Assert.AreEqual(2, poss.Length); + Assert.Contains(expectCs, poss); + Assert.Contains(expectGrpcCs, poss); + } + + [Test] + public void NoGrpcOneOutput() + { + var poss = _generator.GetPossibleOutputs(Utils.MakeItem("foo.proto")); + Assert.AreEqual(1, poss.Length); + } + + [TestCase("none")] + [TestCase("")] + public void GrpcNoneOneOutput(string grpc) + { + var item = Utils.MakeItem("foo.proto", "grpcservices", grpc); + var poss = _generator.GetPossibleOutputs(item); + Assert.AreEqual(1, poss.Length); + } + + [TestCase("client")] + [TestCase("server")] + [TestCase("both")] + public void GrpcEnabledTwoOutputs(string grpc) + { + var item = Utils.MakeItem("foo.proto", "grpcservices", grpc); + var poss = _generator.GetPossibleOutputs(item); + Assert.AreEqual(2, poss.Length); + } + + [Test] + public void OutputDirMetadataRecognized() + { + var item = Utils.MakeItem("foo.proto", "OutputDir", "out"); + var poss = _generator.GetPossibleOutputs(item); + Assert.AreEqual(1, poss.Length); + Assert.That(poss[0], Is.EqualTo("out/Foo.cs") | Is.EqualTo("out\\Foo.cs")); + } + + [Test] + public void OutputDirPatched() + { + var item = Utils.MakeItem("sub/foo.proto", "OutputDir", "out"); + var output = _generator.PatchOutputDirectory(item); + var poss = _generator.GetPossibleOutputs(output); + Assert.AreEqual(1, poss.Length); + Assert.That(poss[0], Is.EqualTo("out/sub/Foo.cs") | Is.EqualTo("out\\sub\\Foo.cs")); + } + }; +} diff --git a/src/csharp/Grpc.Tools.Tests/CppGeneratorTest.cs b/src/csharp/Grpc.Tools.Tests/CppGeneratorTest.cs new file mode 100644 index 00000000..37e8f323 --- /dev/null +++ b/src/csharp/Grpc.Tools.Tests/CppGeneratorTest.cs @@ -0,0 +1,88 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System.IO; +using NUnit.Framework; + +namespace Grpc.Tools.Tests +{ + public class CppGeneratorTest : GeneratorTest + { + GeneratorServices _generator; + + [SetUp] + public new void SetUp() + { + _generator = GeneratorServices.GetForLanguage("Cpp", _log); + } + + [TestCase("foo.proto", "", "foo")] + [TestCase("foo.proto", ".", "foo")] + [TestCase("foo.proto", "./", "foo")] + [TestCase("sub/foo.proto", "", "sub/foo")] + [TestCase("root/sub/foo.proto", "root", "sub/foo")] + [TestCase("root/sub/foo.proto", "root", "sub/foo")] + [TestCase("/root/sub/foo.proto", "/root", "sub/foo")] + public void RelativeDirectoryCompute(string proto, string root, string expectStem) + { + if (Path.DirectorySeparatorChar == '\\') + expectStem = expectStem.Replace('/', '\\'); + var poss = _generator.GetPossibleOutputs(Utils.MakeItem(proto, "ProtoRoot", root)); + Assert.AreEqual(2, poss.Length); + Assert.Contains(expectStem + ".pb.cc", poss); + Assert.Contains(expectStem + ".pb.h", poss); + } + + [Test] + public void NoGrpcTwoOutputs() + { + var poss = _generator.GetPossibleOutputs(Utils.MakeItem("foo.proto")); + Assert.AreEqual(2, poss.Length); + } + + [TestCase("false")] + [TestCase("")] + public void GrpcDisabledTwoOutput(string grpc) + { + var item = Utils.MakeItem("foo.proto", "grpcservices", grpc); + var poss = _generator.GetPossibleOutputs(item); + Assert.AreEqual(2, poss.Length); + } + + [TestCase("true")] + public void GrpcEnabledFourOutputs(string grpc) + { + var item = Utils.MakeItem("foo.proto", "grpcservices", grpc); + var poss = _generator.GetPossibleOutputs(item); + Assert.AreEqual(4, poss.Length); + Assert.Contains("foo.pb.cc", poss); + Assert.Contains("foo.pb.h", poss); + Assert.Contains("foo.grpc.pb.cc", poss); + Assert.Contains("foo.grpc.pb.h", poss); + } + + [Test] + public void OutputDirMetadataRecognized() + { + var item = Utils.MakeItem("foo.proto", "OutputDir", "out"); + var poss = _generator.GetPossibleOutputs(item); + Assert.AreEqual(2, poss.Length); + Assert.That(Path.GetDirectoryName(poss[0]), Is.EqualTo("out")); + } + }; +} diff --git a/src/csharp/Grpc.Tools.Tests/DepFileUtilTest.cs b/src/csharp/Grpc.Tools.Tests/DepFileUtilTest.cs new file mode 100644 index 00000000..4da62f57 --- /dev/null +++ b/src/csharp/Grpc.Tools.Tests/DepFileUtilTest.cs @@ -0,0 +1,174 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System.IO; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using NUnit.Framework; + +namespace Grpc.Tools.Tests +{ + public class DepFileUtilTest + { + + [Test] + public void HashString64Hex_IsSane() + { + string hashFoo1 = DepFileUtil.HashString64Hex("foo"); + string hashEmpty = DepFileUtil.HashString64Hex(""); + string hashFoo2 = DepFileUtil.HashString64Hex("foo"); + + StringAssert.IsMatch("^[a-f0-9]{16}$", hashFoo1); + Assert.AreEqual(hashFoo1, hashFoo2); + Assert.AreNotEqual(hashFoo1, hashEmpty); + } + + [Test] + public void GetDepFilenameForProto_IsSane() + { + StringAssert.IsMatch(@"^out[\\/][a-f0-9]{16}_foo.protodep$", + DepFileUtil.GetDepFilenameForProto("out", "foo.proto")); + StringAssert.IsMatch(@"^[a-f0-9]{16}_foo.protodep$", + DepFileUtil.GetDepFilenameForProto("", "foo.proto")); + } + + [Test] + public void GetDepFilenameForProto_HashesDir() + { + string PickHash(string fname) => + DepFileUtil.GetDepFilenameForProto("", fname).Substring(0, 16); + + string same1 = PickHash("dir1/dir2/foo.proto"); + string same2 = PickHash("dir1/dir2/proto.foo"); + string same3 = PickHash("dir1/dir2/proto"); + string same4 = PickHash("dir1/dir2/.proto"); + string unsame1 = PickHash("dir2/foo.proto"); + string unsame2 = PickHash("/dir2/foo.proto"); + + Assert.AreEqual(same1, same2); + Assert.AreEqual(same1, same3); + Assert.AreEqual(same1, same4); + Assert.AreNotEqual(same1, unsame1); + Assert.AreNotEqual(unsame1, unsame2); + } + + [Test] + public void GetOutputDirWithHash_IsSane() + { + StringAssert.IsMatch(@"^out[\\/][a-f0-9]{16}$", + DepFileUtil.GetOutputDirWithHash("out", "foo.proto")); + StringAssert.IsMatch(@"^[a-f0-9]{16}$", + DepFileUtil.GetOutputDirWithHash("", "foo.proto")); + } + + [Test] + public void GetOutputDirWithHash_HashesDir() + { + string PickHash(string fname) => DepFileUtil.GetOutputDirWithHash("", fname); + + string same1 = PickHash("dir1/dir2/foo.proto"); + string same2 = PickHash("dir1/dir2/proto.foo"); + string same3 = PickHash("dir1/dir2/proto"); + string same4 = PickHash("dir1/dir2/.proto"); + string unsame1 = PickHash("dir2/foo.proto"); + string unsame2 = PickHash("/dir2/foo.proto"); + + Assert.AreEqual(same1, same2); + Assert.AreEqual(same1, same3); + Assert.AreEqual(same1, same4); + Assert.AreNotEqual(same1, unsame1); + Assert.AreNotEqual(unsame1, unsame2); + } + + ////////////////////////////////////////////////////////////////////////// + // Full file reading tests + + // Generated by protoc on Windows. Slashes vary. + const string depFile1 = + @"C:\projects\foo\src\./foo.grpc.pb.cc \ +C:\projects\foo\src\./foo.grpc.pb.h \ +C:\projects\foo\src\./foo.pb.cc \ + C:\projects\foo\src\./foo.pb.h: C:/usr/include/google/protobuf/wrappers.proto\ + C:/usr/include/google/protobuf/any.proto\ +C:/usr/include/google/protobuf/source_context.proto\ + C:/usr/include/google/protobuf/type.proto\ + foo.proto"; + + // This has a nasty output directory with a space. + const string depFile2 = + @"obj\Release x64\net45\/Foo.cs \ +obj\Release x64\net45\/FooGrpc.cs: C:/usr/include/google/protobuf/wrappers.proto\ + C:/projects/foo/src//foo.proto"; + + [Test] + public void ReadDependencyInput_FullFile1() + { + string[] deps = ReadDependencyInputFromFileData(depFile1, "foo.proto"); + + Assert.NotNull(deps); + Assert.That(deps, Has.Length.InRange(4, 5)); // foo.proto may or may not be listed. + Assert.That(deps, Has.One.EndsWith("wrappers.proto")); + Assert.That(deps, Has.One.EndsWith("type.proto")); + Assert.That(deps, Has.None.StartWith(" ")); + } + + [Test] + public void ReadDependencyInput_FullFile2() + { + string[] deps = ReadDependencyInputFromFileData(depFile2, "C:/projects/foo/src/foo.proto"); + + Assert.NotNull(deps); + Assert.That(deps, Has.Length.InRange(1, 2)); + Assert.That(deps, Has.One.EndsWith("wrappers.proto")); + Assert.That(deps, Has.None.StartWith(" ")); + } + + [Test] + public void ReadDependencyInput_FullFileUnparsable() + { + string[] deps = ReadDependencyInputFromFileData("a:/foo.proto", "/foo.proto"); + Assert.NotNull(deps); + Assert.Zero(deps.Length); + } + + // NB in our tests files are put into the temp directory but all have + // different names. Avoid adding files with the same directory path and + // name, or add reasonable handling for it if required. Tests are run in + // parallel and will collide otherwise. + private string[] ReadDependencyInputFromFileData(string fileData, string protoName) + { + string tempPath = Path.GetTempPath(); + string tempfile = DepFileUtil.GetDepFilenameForProto(tempPath, protoName); + try + { + File.WriteAllText(tempfile, fileData); + var mockEng = new Moq.Mock(); + var log = new TaskLoggingHelper(mockEng.Object, "x"); + return DepFileUtil.ReadDependencyInputs(tempPath, protoName, log); + } + finally + { + try + { + File.Delete(tempfile); + } + catch { } + } + } + }; +} diff --git a/src/csharp/Grpc.Tools.Tests/GeneratorTest.cs b/src/csharp/Grpc.Tools.Tests/GeneratorTest.cs new file mode 100644 index 00000000..5ccce90a --- /dev/null +++ b/src/csharp/Grpc.Tools.Tests/GeneratorTest.cs @@ -0,0 +1,55 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Moq; +using NUnit.Framework; + +namespace Grpc.Tools.Tests +{ + public class GeneratorTest + { + protected Mock _mockEngine; + protected TaskLoggingHelper _log; + + [SetUp] + public void SetUp() + { + _mockEngine = new Mock(); + _log = new TaskLoggingHelper(_mockEngine.Object, "phony"); + } + + [TestCase("csharp")] + [TestCase("CSharp")] + [TestCase("cpp")] + public void ValidLanguages(string lang) + { + Assert.IsNotNull(GeneratorServices.GetForLanguage(lang, _log)); + _mockEngine.Verify(me => me.LogErrorEvent(It.IsAny()), Times.Never); + } + + [TestCase("")] + [TestCase("COBOL")] + public void InvalidLanguages(string lang) + { + Assert.IsNull(GeneratorServices.GetForLanguage(lang, _log)); + _mockEngine.Verify(me => me.LogErrorEvent(It.IsAny()), Times.Once); + } + }; +} diff --git a/src/csharp/Grpc.Tools.Tests/MsBuildAssemblyHelper.cs b/src/csharp/Grpc.Tools.Tests/MsBuildAssemblyHelper.cs new file mode 100644 index 00000000..8ca941b7 --- /dev/null +++ b/src/csharp/Grpc.Tools.Tests/MsBuildAssemblyHelper.cs @@ -0,0 +1,71 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using NUnitLite; +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace Grpc.Tools.Tests +{ + static class MsBuildAssemblyHelper + { + [DllImport("__Internal")] + extern static void mono_set_assemblies_path(string path); + + public static void TweakAssemblyPathIfOnMono() + { + // Below is a hack to allow the tests to run under Mono Framework build. + // Mono unfortunately comes with broken Microsoft.Build.* assemblies installed in + // the GAC, so we need to tweak the assembly search path to make sure the right + // msbuild assemblies are loaded (and the tests work). +#if NET45 + // only run this under .NET framework; under mono + bool isMono = Type.GetType("Mono.Runtime") != null; + if (isMono) + { + var mscorlibDir = Path.GetDirectoryName(typeof(Array).Assembly.Location); + // Construct the location of MsBuild assemblies from the location of mscorlib assembly. + var msbuildToolPath = Path.Combine(mscorlibDir, "..", "msbuild", "Current", "bin"); + + if (!Directory.Exists(msbuildToolPath)) + { + // with older versions of mono for Mac (e.g. mono 5.16.0 which is currently + // installed on the kokoro mac workers) the "Current" symlink doesn't exist + // so also try specifying the msbuild version explicitly + msbuildToolPath = Path.Combine(mscorlibDir, "..", "msbuild", "15.0", "bin"); + } + + // To make sure we've constructed the right path, make sure the assemblies we're interested + // in are there. + foreach(var assemblyName in new [] {"Microsoft.Build.Framework.dll", "Microsoft.Build.Utilities.v4.0.dll", "Microsoft.Build.Utilities.Core.dll"}) + { + if (!File.Exists(Path.Combine(msbuildToolPath, assemblyName))) + { + throw new InvalidOperationException($"Could not locate assembly {assemblyName} under {msbuildToolPath}"); + } + } + // Normally the assembly search path can be changed by MONO_PATH environment variable, but it needs to be done + // before the process starts. The following internal method allows us to do the same thing. + mono_set_assemblies_path(msbuildToolPath); + } +#endif + } + } +} diff --git a/src/csharp/Grpc.Tools.Tests/NUnitMain.cs b/src/csharp/Grpc.Tools.Tests/NUnitMain.cs new file mode 100644 index 00000000..7e0c7489 --- /dev/null +++ b/src/csharp/Grpc.Tools.Tests/NUnitMain.cs @@ -0,0 +1,32 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using NUnitLite; + +namespace Grpc.Tools.Tests +{ + static class NUnitMain + { + public static int Main(string[] args) + { + MsBuildAssemblyHelper.TweakAssemblyPathIfOnMono(); + return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args); + } + } +} diff --git a/src/csharp/Grpc.Tools.Tests/ProtoCompileBasicTest.cs b/src/csharp/Grpc.Tools.Tests/ProtoCompileBasicTest.cs new file mode 100644 index 00000000..ca850c59 --- /dev/null +++ b/src/csharp/Grpc.Tools.Tests/ProtoCompileBasicTest.cs @@ -0,0 +1,84 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System.Collections.Generic; +using System.Linq; +using System.Reflection; // UWYU: Object.GetType() extension. +using Microsoft.Build.Framework; +using Moq; +using NUnit.Framework; + +namespace Grpc.Tools.Tests +{ + public class ProtoCompileBasicTest + { + // Mock task class that stops right before invoking protoc. + public class ProtoCompileTestable : ProtoCompile + { + public string LastPathToTool { get; private set; } + public string[] LastResponseFile { get; private set; } + public List StdErrMessages { get; } = new List(); + + protected override int ExecuteTool(string pathToTool, + string response, + string commandLine) + { + // We should never be using command line commands. + Assert.That(commandLine, Is.Null | Is.Empty); + + // Must receive a path to tool + Assert.That(pathToTool, Is.Not.Null & Is.Not.Empty); + Assert.That(response, Is.Not.Null & Does.EndWith("\n")); + + LastPathToTool = pathToTool; + LastResponseFile = response.Remove(response.Length - 1).Split('\n'); + + foreach (string message in StdErrMessages) + { + LogEventsFromTextOutput(message, MessageImportance.High); + } + + // Do not run the tool, but pretend it ran successfully. + return StdErrMessages.Any() ? -1 : 0; + } + }; + + protected Mock _mockEngine; + protected ProtoCompileTestable _task; + + [SetUp] + public void SetUp() + { + _mockEngine = new Mock(); + _task = new ProtoCompileTestable { + BuildEngine = _mockEngine.Object + }; + } + + [TestCase("Protobuf")] + [TestCase("Generator")] + [TestCase("OutputDir")] + [Description("We trust MSBuild to initialize these properties.")] + public void RequiredAttributePresentOnProperty(string prop) + { + var pinfo = _task.GetType()?.GetProperty(prop); + Assert.NotNull(pinfo); + Assert.That(pinfo, Has.Attribute()); + } + }; +} diff --git a/src/csharp/Grpc.Tools.Tests/ProtoCompileCommandLineGeneratorTest.cs b/src/csharp/Grpc.Tools.Tests/ProtoCompileCommandLineGeneratorTest.cs new file mode 100644 index 00000000..89c6b274 --- /dev/null +++ b/src/csharp/Grpc.Tools.Tests/ProtoCompileCommandLineGeneratorTest.cs @@ -0,0 +1,269 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System.IO; +using Microsoft.Build.Framework; +using Moq; +using NUnit.Framework; + +namespace Grpc.Tools.Tests +{ + public class ProtoCompileCommandLineGeneratorTest : ProtoCompileBasicTest + { + [SetUp] + public new void SetUp() + { + _task.Generator = "csharp"; + _task.OutputDir = "outdir"; + _task.Protobuf = Utils.MakeSimpleItems("a.proto"); + } + + void ExecuteExpectSuccess() + { + _mockEngine + .Setup(me => me.LogErrorEvent(It.IsAny())) + .Callback((BuildErrorEventArgs e) => + Assert.Fail($"Error logged by build engine:\n{e.Message}")); + bool result = _task.Execute(); + Assert.IsTrue(result); + } + + [Test] + public void MinimalCompile() + { + ExecuteExpectSuccess(); + Assert.That(_task.LastPathToTool, Does.Match(@"protoc(.exe)?$")); + Assert.That(_task.LastResponseFile, Is.EqualTo(new[] { + "--csharp_out=outdir", "--error_format=msvs", "a.proto" })); + } + + [Test] + public void CompileTwoFiles() + { + _task.Protobuf = Utils.MakeSimpleItems("a.proto", "foo/b.proto"); + ExecuteExpectSuccess(); + Assert.That(_task.LastResponseFile, Is.EqualTo(new[] { + "--csharp_out=outdir", "--error_format=msvs", "a.proto", "foo/b.proto" })); + } + + [Test] + public void CompileWithProtoPaths() + { + _task.ProtoPath = new[] { "/path1", "/path2" }; + ExecuteExpectSuccess(); + Assert.That(_task.LastResponseFile, Is.EqualTo(new[] { + "--csharp_out=outdir", "--proto_path=/path1", + "--proto_path=/path2", "--error_format=msvs", "a.proto" })); + } + + [TestCase("Cpp")] + [TestCase("CSharp")] + [TestCase("Java")] + [TestCase("Javanano")] + [TestCase("Js")] + [TestCase("Objc")] + [TestCase("Php")] + [TestCase("Python")] + [TestCase("Ruby")] + public void CompileWithOptions(string gen) + { + _task.Generator = gen; + _task.OutputOptions = new[] { "foo", "bar" }; + ExecuteExpectSuccess(); + gen = gen.ToLowerInvariant(); + Assert.That(_task.LastResponseFile, Is.EqualTo(new[] { + $"--{gen}_out=outdir", $"--{gen}_opt=foo,bar", "--error_format=msvs", "a.proto" })); + } + + [Test] + public void OutputDependencyFile() + { + _task.DependencyOut = "foo/my.protodep"; + // Task fails trying to read the non-generated file; we ignore that. + _task.Execute(); + Assert.That(_task.LastResponseFile, + Does.Contain("--dependency_out=foo/my.protodep")); + } + + [Test] + public void OutputDependencyWithProtoDepDir() + { + _task.ProtoDepDir = "foo"; + // Task fails trying to read the non-generated file; we ignore that. + _task.Execute(); + Assert.That(_task.LastResponseFile, + Has.One.Match(@"^--dependency_out=foo[/\\].+_a.protodep$")); + } + + [Test] + public void GenerateGrpc() + { + _task.GrpcPluginExe = "/foo/grpcgen"; + ExecuteExpectSuccess(); + Assert.That(_task.LastResponseFile, Is.SupersetOf(new[] { + "--csharp_out=outdir", "--grpc_out=outdir", + "--plugin=protoc-gen-grpc=/foo/grpcgen" })); + } + + [Test] + public void GenerateGrpcWithOutDir() + { + _task.GrpcPluginExe = "/foo/grpcgen"; + _task.GrpcOutputDir = "gen-out"; + ExecuteExpectSuccess(); + Assert.That(_task.LastResponseFile, Is.SupersetOf(new[] { + "--csharp_out=outdir", "--grpc_out=gen-out" })); + } + + [Test] + public void GenerateGrpcWithOptions() + { + _task.GrpcPluginExe = "/foo/grpcgen"; + _task.GrpcOutputOptions = new[] { "baz", "quux" }; + ExecuteExpectSuccess(); + Assert.That(_task.LastResponseFile, + Does.Contain("--grpc_opt=baz,quux")); + } + + [Test] + public void AdditionalProtocArguments() + { + _task.AdditionalProtocArguments = new[] { "--experimental_allow_proto3_optional" }; + ExecuteExpectSuccess(); + Assert.That(_task.LastResponseFile, + Does.Contain("--experimental_allow_proto3_optional")); + } + + [Test] + public void DirectoryArgumentsSlashTrimmed() + { + _task.GrpcPluginExe = "/foo/grpcgen"; + _task.GrpcOutputDir = "gen-out/"; + _task.OutputDir = "outdir/"; + _task.ProtoPath = new[] { "/path1/", "/path2/" }; + ExecuteExpectSuccess(); + Assert.That(_task.LastResponseFile, Is.SupersetOf(new[] { + "--proto_path=/path1", "--proto_path=/path2", + "--csharp_out=outdir", "--grpc_out=gen-out" })); + } + + [TestCase(".", ".")] + [TestCase("/", "/")] + [TestCase("//", "/")] + [TestCase("/foo/", "/foo")] + [TestCase("/foo", "/foo")] + [TestCase("foo/", "foo")] + [TestCase("foo//", "foo")] + [TestCase("foo/\\", "foo")] + [TestCase("foo\\/", "foo")] + [TestCase("C:\\foo", "C:\\foo")] + [TestCase("C:", "C:")] + [TestCase("C:\\", "C:\\")] + [TestCase("C:\\\\", "C:\\")] + public void DirectorySlashTrimmingCases(string given, string expect) + { + if (Path.DirectorySeparatorChar == '/') + expect = expect.Replace('\\', '/'); + _task.OutputDir = given; + ExecuteExpectSuccess(); + Assert.That(_task.LastResponseFile, + Does.Contain("--csharp_out=" + expect)); + } + + [TestCase( + "../Protos/greet.proto(19) : warning in column=5 : warning : When enum name is stripped and label is PascalCased (Zero) this value label conflicts with Zero.", + "../Protos/greet.proto", + 19, + 5, + "warning : When enum name is stripped and label is PascalCased (Zero) this value label conflicts with Zero.")] + [TestCase( + "../Protos/greet.proto: warning: Import google/protobuf/empty.proto but not used.", + "../Protos/greet.proto", + 0, + 0, + "Import google/protobuf/empty.proto but not used.")] + [TestCase("../Protos/greet.proto(14) : error in column=10: \"name\" is already defined in \"Greet.HelloRequest\".", null, 0, 0, null)] + [TestCase("../Protos/greet.proto: Import \"google / protobuf / empty.proto\" was listed twice.", null, 0, 0, null)] + public void WarningsParsed(string stderr, string file, int line, int col, string message) + { + _task.StdErrMessages.Add(stderr); + + _mockEngine + .Setup(me => me.LogWarningEvent(It.IsAny())) + .Callback((BuildWarningEventArgs e) => { + if (file != null) + { + Assert.AreEqual(file, e.File); + Assert.AreEqual(line, e.LineNumber); + Assert.AreEqual(col, e.ColumnNumber); + Assert.AreEqual(message, e.Message); + } + else + { + Assert.Fail($"Error logged by build engine:\n{e.Message}"); + } + }); + + bool result = _task.Execute(); + Assert.IsFalse(result); + } + + [TestCase( + "../Protos/greet.proto(14) : error in column=10: \"name\" is already defined in \"Greet.HelloRequest\".", + "../Protos/greet.proto", + 14, + 10, + "\"name\" is already defined in \"Greet.HelloRequest\".")] + [TestCase( + "../Protos/greet.proto: Import \"google / protobuf / empty.proto\" was listed twice.", + "../Protos/greet.proto", + 0, + 0, + "Import \"google / protobuf / empty.proto\" was listed twice.")] + [TestCase("../Protos/greet.proto(19) : warning in column=5 : warning : When enum name is stripped and label is PascalCased (Zero) this value label conflicts with Zero.", null, 0, 0, null)] + [TestCase("../Protos/greet.proto: warning: Import google/protobuf/empty.proto but not used.", null, 0, 0, null)] + public void ErrorsParsed(string stderr, string file, int line, int col, string message) + { + _task.StdErrMessages.Add(stderr); + + _mockEngine + .Setup(me => me.LogErrorEvent(It.IsAny())) + .Callback((BuildErrorEventArgs e) => { + if (file != null) + { + Assert.AreEqual(file, e.File); + Assert.AreEqual(line, e.LineNumber); + Assert.AreEqual(col, e.ColumnNumber); + Assert.AreEqual(message, e.Message); + } + else + { + // Ignore expected error + // "protoc/protoc.exe" existed with code -1. + if (!e.Message.EndsWith("exited with code -1.")) + { + Assert.Fail($"Error logged by build engine:\n{e.Message}"); + } + } + }); + + bool result = _task.Execute(); + Assert.IsFalse(result); + } + }; +} diff --git a/src/csharp/Grpc.Tools.Tests/ProtoCompileCommandLinePrinterTest.cs b/src/csharp/Grpc.Tools.Tests/ProtoCompileCommandLinePrinterTest.cs new file mode 100644 index 00000000..a11e3462 --- /dev/null +++ b/src/csharp/Grpc.Tools.Tests/ProtoCompileCommandLinePrinterTest.cs @@ -0,0 +1,51 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using Microsoft.Build.Framework; +using Moq; +using NUnit.Framework; + +namespace Grpc.Tools.Tests +{ + public class ProtoCompileCommandLinePrinterTest : ProtoCompileBasicTest + { + [SetUp] + public new void SetUp() + { + _task.Generator = "csharp"; + _task.OutputDir = "outdir"; + _task.Protobuf = Utils.MakeSimpleItems("a.proto"); + + _mockEngine + .Setup(me => me.LogMessageEvent(It.IsAny())) + .Callback((BuildMessageEventArgs e) => + Assert.Fail($"Error logged by build engine:\n{e.Message}")) + .Verifiable("Command line was not output by the task."); + } + + void ExecuteExpectSuccess() + { + _mockEngine + .Setup(me => me.LogErrorEvent(It.IsAny())) + .Callback((BuildErrorEventArgs e) => + Assert.Fail($"Error logged by build engine:\n{e.Message}")); + bool result = _task.Execute(); + Assert.IsTrue(result); + } + }; +} diff --git a/src/csharp/Grpc.Tools.Tests/ProtoToolsPlatformTaskTest.cs b/src/csharp/Grpc.Tools.Tests/ProtoToolsPlatformTaskTest.cs new file mode 100644 index 00000000..e98f6e93 --- /dev/null +++ b/src/csharp/Grpc.Tools.Tests/ProtoToolsPlatformTaskTest.cs @@ -0,0 +1,158 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System.Runtime.InteropServices; // For NETCORE tests. +using Microsoft.Build.Framework; +using Moq; +using NUnit.Framework; + +namespace Grpc.Tools.Tests +{ + public class ProtoToolsPlatformTaskTest + { + ProtoToolsPlatform _task; + int _cpuMatched, _osMatched; + + [OneTimeSetUp] + public void SetUp() + { + var mockEng = new Mock(); + _task = new ProtoToolsPlatform() { BuildEngine = mockEng.Object }; + _task.Execute(); + } + + [OneTimeTearDown] + public void TearDown() + { + Assert.AreEqual(1, _cpuMatched, "CPU type detection failed"); + Assert.AreEqual(1, _osMatched, "OS detection failed"); + } + +#if NETCORE + // PlatformAttribute not yet available in NUnit, coming soon: + // https://github.com/nunit/nunit/pull/3003. + // Use same test case names as under the full framework. + [Test] + public void CpuIsX86() + { + if (RuntimeInformation.OSArchitecture == Architecture.X86) + { + _cpuMatched++; + Assert.AreEqual("x86", _task.Cpu); + } + } + + [Test] + public void CpuIsX64() + { + if (RuntimeInformation.OSArchitecture == Architecture.X64) + { + _cpuMatched++; + Assert.AreEqual("x64", _task.Cpu); + } + } + + [Test] + public void CpuIsArm64() + { + if (RuntimeInformation.OSArchitecture == Architecture.Arm64) + { + _cpuMatched++; + + // On macosx arm64, x64 is used until a native protoc is shipped + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + Assert.AreEqual("x64", _task.Cpu); + } + else + { + Assert.AreEqual("arm64", _task.Cpu); + } + } + } + + [Test] + public void OsIsWindows() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + _osMatched++; + Assert.AreEqual("windows", _task.Os); + } + } + + [Test] + public void OsIsLinux() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + _osMatched++; + Assert.AreEqual("linux", _task.Os); + } + } + + [Test] + public void OsIsMacOsX() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + _osMatched++; + Assert.AreEqual("macosx", _task.Os); + } + } + +#else // !NETCORE, i.e. full framework. + + [Test, Platform("32-Bit")] + public void CpuIsX86() + { + _cpuMatched++; + Assert.AreEqual("x86", _task.Cpu); + } + + [Test, Platform("64-Bit")] + public void CpuIsX64() + { + _cpuMatched++; + Assert.AreEqual("x64", _task.Cpu); + } + + [Test, Platform("Win")] + public void OsIsWindows() + { + _osMatched++; + Assert.AreEqual("windows", _task.Os); + } + + [Test, Platform("Linux")] + public void OsIsLinux() + { + _osMatched++; + Assert.AreEqual("linux", _task.Os); + } + + [Test, Platform("MacOSX")] + public void OsIsMacOsX() + { + _osMatched++; + Assert.AreEqual("macosx", _task.Os); + } + +#endif // NETCORE + }; +} diff --git a/src/csharp/Grpc.Tools.Tests/Utils.cs b/src/csharp/Grpc.Tools.Tests/Utils.cs new file mode 100644 index 00000000..6e0f1cff --- /dev/null +++ b/src/csharp/Grpc.Tools.Tests/Utils.cs @@ -0,0 +1,46 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System.Linq; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Grpc.Tools.Tests +{ + static class Utils + { + // Build an item with a name from args[0] and metadata key-value pairs + // from the rest of args, interleaved. + // This does not do any checking, and expects an odd number of args. + public static ITaskItem MakeItem(params string[] args) + { + var item = new TaskItem(args[0]); + for (int i = 1; i < args.Length; i += 2) + { + item.SetMetadata(args[i], args[i + 1]); + } + return item; + } + + // Return an array of items from given itemspecs. + public static ITaskItem[] MakeSimpleItems(params string[] specs) + { + return specs.Select(s => new TaskItem(s)).ToArray(); + } + }; +} diff --git a/src/csharp/Grpc.Tools/Common.cs b/src/csharp/Grpc.Tools/Common.cs new file mode 100644 index 00000000..90624d6c --- /dev/null +++ b/src/csharp/Grpc.Tools/Common.cs @@ -0,0 +1,73 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; +using Grpc.Core.Internal; + +namespace Grpc.Tools +{ + // Metadata names (MSBuild item attributes) that we refer to often. + static class Metadata + { + // On output dependency lists. + public static string Source = "Source"; + // On Protobuf items. + public static string ProtoRoot = "ProtoRoot"; + public static string OutputDir = "OutputDir"; + public static string GrpcServices = "GrpcServices"; + public static string GrpcOutputDir = "GrpcOutputDir"; + }; + + // A few flags used to control the behavior under various platforms. + internal static class Platform + { + public static readonly CommonPlatformDetection.OSKind Os = CommonPlatformDetection.GetOSKind(); + + public static readonly CommonPlatformDetection.CpuArchitecture Cpu = CommonPlatformDetection.GetProcessArchitecture(); + + // This is not necessarily true, but good enough. BCL lacks a per-FS + // API to determine file case sensitivity. + public static bool IsFsCaseInsensitive => Os == CommonPlatformDetection.OSKind.Windows; + public static bool IsWindows => Os == CommonPlatformDetection.OSKind.Windows; + }; + + // Exception handling helpers. + static class Exceptions + { + // Returns true iff the exception indicates an error from an I/O call. See + // https://github.com/Microsoft/msbuild/blob/v15.4.8.50001/src/Shared/ExceptionHandling.cs#L101 + static public bool IsIoRelated(Exception ex) => + ex is IOException || + (ex is ArgumentException && !(ex is ArgumentNullException)) || + ex is SecurityException || + ex is UnauthorizedAccessException || + ex is NotSupportedException; + }; + + // String helpers. + static class Strings + { + // Compare string to argument using OrdinalIgnoreCase comparison. + public static bool EqualNoCase(this string a, string b) => + string.Equals(a, b, StringComparison.OrdinalIgnoreCase); + } +} diff --git a/src/csharp/Grpc.Tools/DepFileUtil.cs b/src/csharp/Grpc.Tools/DepFileUtil.cs new file mode 100644 index 00000000..c17f4553 --- /dev/null +++ b/src/csharp/Grpc.Tools/DepFileUtil.cs @@ -0,0 +1,305 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Grpc.Tools +{ + internal static class DepFileUtil + { + /* + Sample dependency files. Notable features we have to deal with: + * Slash doubling, must normalize them. + * Spaces in file names. Cannot just "unwrap" the line on backslash at eof; + rather, treat every line as containing one file name except for one with + the ':' separator, as containing exactly two. + * Deal with ':' also being drive letter separator (second example). + + obj\Release\net45\/Foo.cs \ + obj\Release\net45\/FooGrpc.cs: C:/foo/include/google/protobuf/wrappers.proto\ + C:/projects/foo/src//foo.proto + + C:\projects\foo\src\./foo.grpc.pb.cc \ + C:\projects\foo\src\./foo.grpc.pb.h \ + C:\projects\foo\src\./foo.pb.cc \ + C:\projects\foo\src\./foo.pb.h: C:/foo/include/google/protobuf/wrappers.proto\ + C:/foo/include/google/protobuf/any.proto\ + C:/foo/include/google/protobuf/source_context.proto\ + C:/foo/include/google/protobuf/type.proto\ + foo.proto + */ + + /// + /// Read file names from the dependency file to the right of ':' + /// + /// Relative path to the dependency cache, e. g. "out" + /// Relative path to the proto item, e. g. "foo/file.proto" + /// A for logging + /// + /// Array of the proto file input dependencies as written by protoc, or empty + /// array if the dependency file does not exist or cannot be parsed. + /// + public static string[] ReadDependencyInputs(string protoDepDir, string proto, + TaskLoggingHelper log) + { + string depFilename = GetDepFilenameForProto(protoDepDir, proto); + string[] lines = ReadDepFileLines(depFilename, false, log); + if (lines.Length == 0) + { + return lines; + } + + var result = new List(); + bool skip = true; + foreach (string line in lines) + { + // Start at the only line separating dependency outputs from inputs. + int ix = skip ? FindLineSeparator(line) : -1; + skip = skip && ix < 0; + if (skip) { continue; } + string file = ExtractFilenameFromLine(line, ix + 1, line.Length); + if (file == "") + { + log.LogMessage(MessageImportance.Low, + $"Skipping unparsable dependency file {depFilename}.\nLine with error: '{line}'"); + return new string[0]; + } + + // Do not bend over backwards trying not to include a proto into its + // own list of dependencies. Since a file is not older than self, + // it is safe to add; this is purely a memory optimization. + if (file != proto) + { + result.Add(file); + } + } + return result.ToArray(); + } + + /// + /// Read file names from the dependency file to the left of ':' + /// + /// Path to dependency file written by protoc + /// A for logging + /// + /// Array of the protoc-generated outputs from the given dependency file + /// written by protoc, or empty array if the file does not exist or cannot + /// be parsed. + /// + /// + /// Since this is called after a protoc invocation, an unparsable or missing + /// file causes an error-level message to be logged. + /// + public static string[] ReadDependencyOutputs(string depFilename, + TaskLoggingHelper log) + { + string[] lines = ReadDepFileLines(depFilename, true, log); + if (lines.Length == 0) + { + return lines; + } + + var result = new List(); + foreach (string line in lines) + { + int ix = FindLineSeparator(line); + string file = ExtractFilenameFromLine(line, 0, ix >= 0 ? ix : line.Length); + if (file == "") + { + log.LogError("Unable to parse generated dependency file {0}.\n" + + "Line with error: '{1}'", depFilename, line); + return new string[0]; + } + result.Add(file); + + // If this is the line with the separator, do not read further. + if (ix >= 0) { break; } + } + return result.ToArray(); + } + + /// + /// Construct relative dependency file name from directory hash and file name + /// + /// Relative path to the dependency cache, e. g. "out" + /// Relative path to the proto item, e. g. "foo/file.proto" + /// + /// Full relative path to the dependency file, e. g. + /// "out/deadbeef12345678_file.protodep" + /// + /// + /// See for notes on directory hash. + /// + public static string GetDepFilenameForProto(string protoDepDir, string proto) + { + string dirhash = GetDirectoryHash(proto); + string filename = Path.GetFileNameWithoutExtension(proto); + return Path.Combine(protoDepDir, $"{dirhash}_{filename}.protodep"); + } + + /// + /// Construct relative output directory with directory hash + /// + /// Relative path to the output directory, e. g. "out" + /// Relative path to the proto item, e. g. "foo/file.proto" + /// + /// Full relative path to the directory, e. g. "out/deadbeef12345678" + /// + /// + /// See for notes on directory hash. + /// + public static string GetOutputDirWithHash(string outputDir, string proto) + { + string dirhash = GetDirectoryHash(proto); + return Path.Combine(outputDir, dirhash); + } + + /// + /// Construct the directory hash from a relative file name + /// + /// Relative path to the proto item, e. g. "foo/file.proto" + /// + /// Directory hash based on the file name, e. g. "deadbeef12345678" + /// + /// + /// Since a project may contain proto files with the same filename but in different + /// directories, a unique directory for the generated files is constructed based on the + /// proto file names directory. The directory path can be arbitrary, for example, + /// it can be outside of the project, or an absolute path including a drive letter, + /// or a UNC network path. A name constructed from such a path by, for example, + /// replacing disallowed name characters with an underscore, may well be over + /// filesystem's allowed path length, since it will be located under the project + /// and solution directories, which are also some level deep from the root. + /// Instead of creating long and unwieldy names for these proto sources, we cache + /// the full path of the name without the filename, as in e. g. "foo/file.proto" + /// will yield the name "deadbeef12345678", where that is a presumed hash value + /// of the string "foo". This allows the path to be short, unique (up to a hash + /// collision), and still allowing the user to guess their provenance. + /// + private static string GetDirectoryHash(string proto) + { + string dirname = Path.GetDirectoryName(proto); + if (Platform.IsFsCaseInsensitive) + { + dirname = dirname.ToLowerInvariant(); + } + + return HashString64Hex(dirname); + } + + // Get a 64-bit hash for a directory string. We treat it as if it were + // unique, since there are not so many distinct proto paths in a project. + // We take the first 64 bit of the string SHA1. + // Internal for tests access only. + internal static string HashString64Hex(string str) + { + using (var sha1 = System.Security.Cryptography.SHA1.Create()) + { + byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(str)); + var hashstr = new StringBuilder(16); + for (int i = 0; i < 8; i++) + { + hashstr.Append(hash[i].ToString("x2")); + } + return hashstr.ToString(); + } + } + + // Extract filename between 'beg' (inclusive) and 'end' (exclusive) from + // line 'line', skipping over trailing and leading whitespace, and, when + // 'end' is immediately past end of line 'line', also final '\' (used + // as a line continuation token in the dep file). + // Returns an empty string if the filename cannot be extracted. + static string ExtractFilenameFromLine(string line, int beg, int end) + { + while (beg < end && char.IsWhiteSpace(line[beg])) beg++; + if (beg < end && end == line.Length && line[end - 1] == '\\') end--; + while (beg < end && char.IsWhiteSpace(line[end - 1])) end--; + if (beg == end) return ""; + + string filename = line.Substring(beg, end - beg); + try + { + // Normalize file name. + return Path.Combine(Path.GetDirectoryName(filename), Path.GetFileName(filename)); + } + catch (Exception ex) when (Exceptions.IsIoRelated(ex)) + { + return ""; + } + } + + // Finds the index of the ':' separating dependency clauses in the line, + // not taking Windows drive spec into account. Returns the index of the + // separating ':', or -1 if no separator found. + static int FindLineSeparator(string line) + { + // Mind this case where the first ':' is not separator: + // C:\foo\bar\.pb.h: C:/protobuf/wrappers.proto\ + int ix = line.IndexOf(':'); + if (ix <= 0 || ix == line.Length - 1 + || (line[ix + 1] != '/' && line[ix + 1] != '\\') + || !char.IsLetter(line[ix - 1])) + { + return ix; // Not a windows drive: no letter before ':', or no '\' after. + } + for (int j = ix - 1; --j >= 0;) + { + if (!char.IsWhiteSpace(line[j])) + { + return ix; // Not space or BOL only before "X:/". + } + } + return line.IndexOf(':', ix + 1); + } + + // Read entire dependency file. The 'required' parameter controls error + // logging behavior in case the file not found. We require this file when + // compiling, but reading it is optional when computing dependencies. + static string[] ReadDepFileLines(string filename, bool required, + TaskLoggingHelper log) + { + try + { + var result = File.ReadAllLines(filename); + if (!required) + { + log.LogMessage(MessageImportance.Low, $"Using dependency file {filename}"); + } + return result; + } + catch (Exception ex) when (Exceptions.IsIoRelated(ex)) + { + if (required) + { + log.LogError($"Unable to load {filename}: {ex.GetType().Name}: {ex.Message}"); + } + else + { + log.LogMessage(MessageImportance.Low, $"Skipping {filename}: {ex.Message}"); + } + return new string[0]; + } + } + }; +} diff --git a/src/csharp/Grpc.Tools/GeneratorServices.cs b/src/csharp/Grpc.Tools/GeneratorServices.cs new file mode 100644 index 00000000..0608bb9d --- /dev/null +++ b/src/csharp/Grpc.Tools/GeneratorServices.cs @@ -0,0 +1,239 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System.IO; +using System.Text; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Grpc.Tools +{ + // Abstract class for language-specific analysis behavior, such + // as guessing the generated files the same way protoc does. + internal abstract class GeneratorServices + { + protected readonly TaskLoggingHelper Log; + protected GeneratorServices(TaskLoggingHelper log) { Log = log; } + + // Obtain a service for the given language (csharp, cpp). + public static GeneratorServices GetForLanguage(string lang, TaskLoggingHelper log) + { + if (lang.EqualNoCase("csharp")) { return new CSharpGeneratorServices(log); } + if (lang.EqualNoCase("cpp")) { return new CppGeneratorServices(log); } + + log.LogError("Invalid value '{0}' for task property 'Generator'. " + + "Supported generator languages: CSharp, Cpp.", lang); + return null; + } + + // Guess whether item's metadata suggests gRPC stub generation. + // When "gRPCServices" is not defined, assume gRPC is not used. + // When defined, C# uses "none" to skip gRPC, C++ uses "false", so + // recognize both. Since the value is tightly coupled to the scripts, + // we do not try to validate the value; scripts take care of that. + // It is safe to assume that gRPC is requested for any other value. + protected bool GrpcOutputPossible(ITaskItem proto) + { + string gsm = proto.GetMetadata(Metadata.GrpcServices); + return !gsm.EqualNoCase("") && !gsm.EqualNoCase("none") + && !gsm.EqualNoCase("false"); + } + + // Update OutputDir and GrpcOutputDir for the item and all subsequent + // targets using this item. This should only be done if the real + // output directories for protoc should be modified. + public virtual ITaskItem PatchOutputDirectory(ITaskItem protoItem) + { + // Nothing to do + return protoItem; + } + + public abstract string[] GetPossibleOutputs(ITaskItem protoItem); + + // Calculate part of proto path relative to root. Protoc is very picky + // about them matching exactly, so can be we. Expect root be exact prefix + // to proto, minus some slash normalization. + protected static string GetRelativeDir(string root, string proto, TaskLoggingHelper log) + { + string protoDir = Path.GetDirectoryName(proto); + string rootDir = EndWithSlash(Path.GetDirectoryName(EndWithSlash(root))); + if (rootDir == s_dotSlash) + { + // Special case, otherwise we can return "./" instead of "" below! + return protoDir; + } + if (Platform.IsFsCaseInsensitive) + { + protoDir = protoDir.ToLowerInvariant(); + rootDir = rootDir.ToLowerInvariant(); + } + protoDir = EndWithSlash(protoDir); + if (!protoDir.StartsWith(rootDir)) + { + log.LogWarning("Protobuf item '{0}' has the ProtoRoot metadata '{1}' " + + "which is not prefix to its path. Cannot compute relative path.", + proto, root); + return ""; + } + return protoDir.Substring(rootDir.Length); + } + + // './' or '.\', normalized per system. + protected static string s_dotSlash = "." + Path.DirectorySeparatorChar; + + protected static string EndWithSlash(string str) + { + if (str == "") + { + return s_dotSlash; + } + + if (str[str.Length - 1] != '\\' && str[str.Length - 1] != '/') + { + return str + Path.DirectorySeparatorChar; + } + + return str; + } + }; + + // C# generator services. + internal class CSharpGeneratorServices : GeneratorServices + { + public CSharpGeneratorServices(TaskLoggingHelper log) : base(log) { } + + public override ITaskItem PatchOutputDirectory(ITaskItem protoItem) + { + var outputItem = new TaskItem(protoItem); + string root = outputItem.GetMetadata(Metadata.ProtoRoot); + string proto = outputItem.ItemSpec; + string relative = GetRelativeDir(root, proto, Log); + + string outdir = outputItem.GetMetadata(Metadata.OutputDir); + string pathStem = Path.Combine(outdir, relative); + outputItem.SetMetadata(Metadata.OutputDir, pathStem); + + // Override outdir if GrpcOutputDir present, default to proto output. + string grpcdir = outputItem.GetMetadata(Metadata.GrpcOutputDir); + if (grpcdir != "") + { + pathStem = Path.Combine(grpcdir, relative); + } + outputItem.SetMetadata(Metadata.GrpcOutputDir, pathStem); + return outputItem; + } + + public override string[] GetPossibleOutputs(ITaskItem protoItem) + { + bool doGrpc = GrpcOutputPossible(protoItem); + var outputs = new string[doGrpc ? 2 : 1]; + string proto = protoItem.ItemSpec; + string basename = Path.GetFileNameWithoutExtension(proto); + string outdir = protoItem.GetMetadata(Metadata.OutputDir); + string filename = LowerUnderscoreToUpperCamelProtocWay(basename); + outputs[0] = Path.Combine(outdir, filename) + ".cs"; + + if (doGrpc) + { + string grpcdir = protoItem.GetMetadata(Metadata.GrpcOutputDir); + filename = LowerUnderscoreToUpperCamelGrpcWay(basename); + outputs[1] = Path.Combine(grpcdir, filename) + "Grpc.cs"; + } + return outputs; + } + + // This is how the gRPC codegen currently construct its output filename. + // See src/compiler/generator_helpers.h:118. + string LowerUnderscoreToUpperCamelGrpcWay(string str) + { + var result = new StringBuilder(str.Length, str.Length); + bool cap = true; + foreach (char c in str) + { + if (c == '_') + { + cap = true; + } + else if (cap) + { + result.Append(char.ToUpperInvariant(c)); + cap = false; + } + else + { + result.Append(c); + } + } + return result.ToString(); + } + + // This is how the protoc codegen constructs its output filename. + // See protobuf/compiler/csharp/csharp_helpers.cc:137. + // Note that protoc explicitly discards non-ASCII letters. + string LowerUnderscoreToUpperCamelProtocWay(string str) + { + var result = new StringBuilder(str.Length, str.Length); + bool cap = true; + foreach (char c in str) + { + char upperC = char.ToUpperInvariant(c); + bool isAsciiLetter = 'A' <= upperC && upperC <= 'Z'; + if (isAsciiLetter || ('0' <= c && c <= '9')) + { + result.Append(cap ? upperC : c); + } + cap = !isAsciiLetter; + } + return result.ToString(); + } + }; + + // C++ generator services. + internal class CppGeneratorServices : GeneratorServices + { + public CppGeneratorServices(TaskLoggingHelper log) : base(log) { } + + public override string[] GetPossibleOutputs(ITaskItem protoItem) + { + bool doGrpc = GrpcOutputPossible(protoItem); + string root = protoItem.GetMetadata(Metadata.ProtoRoot); + string proto = protoItem.ItemSpec; + string filename = Path.GetFileNameWithoutExtension(proto); + // E. g., ("foo/", "foo/bar/x.proto") => "bar" + string relative = GetRelativeDir(root, proto, Log); + + var outputs = new string[doGrpc ? 4 : 2]; + string outdir = protoItem.GetMetadata(Metadata.OutputDir); + string fileStem = Path.Combine(outdir, relative, filename); + outputs[0] = fileStem + ".pb.cc"; + outputs[1] = fileStem + ".pb.h"; + if (doGrpc) + { + // Override outdir if GrpcOutputDir present, default to proto output. + outdir = protoItem.GetMetadata(Metadata.GrpcOutputDir); + if (outdir != "") + { + fileStem = Path.Combine(outdir, relative, filename); + } + outputs[2] = fileStem + ".grpc.pb.cc"; + outputs[3] = fileStem + ".grpc.pb.h"; + } + return outputs; + } + } +} diff --git a/src/csharp/Grpc.Tools/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Tools/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..4c64e5b6 --- /dev/null +++ b/src/csharp/Grpc.Tools/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ + +#region Copyright notice and license + +// Copyright 2020 The gRPC Authors +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Grpc.Tools.Tests,PublicKey=" + + "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" + + "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" + + "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" + + "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")] diff --git a/src/csharp/Grpc.Tools/ProtoCompile.cs b/src/csharp/Grpc.Tools/ProtoCompile.cs new file mode 100644 index 00000000..7d7bd922 --- /dev/null +++ b/src/csharp/Grpc.Tools/ProtoCompile.cs @@ -0,0 +1,588 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Grpc.Tools +{ + /// + /// Run Google proto compiler (protoc). + /// + /// After a successful run, the task reads the dependency file if specified + /// to be saved by the compiler, and returns its output files. + /// + /// This task (unlike PrepareProtoCompile) does not attempt to guess anything + /// about language-specific behavior of protoc, and therefore can be used for + /// any language outputs. + /// + public class ProtoCompile : ToolTask + { + /* + + Usage: /home/kkm/work/protobuf/src/.libs/lt-protoc [OPTION] PROTO_FILES + Parse PROTO_FILES and generate output based on the options given: + -IPATH, --proto_path=PATH Specify the directory in which to search for + imports. May be specified multiple times; + directories will be searched in order. If not + given, the current working directory is used. + --version Show version info and exit. + -h, --help Show this text and exit. + --encode=MESSAGE_TYPE Read a text-format message of the given type + from standard input and write it in binary + to standard output. The message type must + be defined in PROTO_FILES or their imports. + --decode=MESSAGE_TYPE Read a binary message of the given type from + standard input and write it in text format + to standard output. The message type must + be defined in PROTO_FILES or their imports. + --decode_raw Read an arbitrary protocol message from + standard input and write the raw tag/value + pairs in text format to standard output. No + PROTO_FILES should be given when using this + flag. + --descriptor_set_in=FILES Specifies a delimited list of FILES + each containing a FileDescriptorSet (a + protocol buffer defined in descriptor.proto). + The FileDescriptor for each of the PROTO_FILES + provided will be loaded from these + FileDescriptorSets. If a FileDescriptor + appears multiple times, the first occurrence + will be used. + -oFILE, Writes a FileDescriptorSet (a protocol buffer, + --descriptor_set_out=FILE defined in descriptor.proto) containing all of + the input files to FILE. + --include_imports When using --descriptor_set_out, also include + all dependencies of the input files in the + set, so that the set is self-contained. + --include_source_info When using --descriptor_set_out, do not strip + SourceCodeInfo from the FileDescriptorProto. + This results in vastly larger descriptors that + include information about the original + location of each decl in the source file as + well as surrounding comments. + --dependency_out=FILE Write a dependency output file in the format + expected by make. This writes the transitive + set of input file paths to FILE + --error_format=FORMAT Set the format in which to print errors. + FORMAT may be 'gcc' (the default) or 'msvs' + (Microsoft Visual Studio format). + --print_free_field_numbers Print the free field numbers of the messages + defined in the given proto files. Groups share + the same field number space with the parent + message. Extension ranges are counted as + occupied fields numbers. + + --plugin=EXECUTABLE Specifies a plugin executable to use. + Normally, protoc searches the PATH for + plugins, but you may specify additional + executables not in the path using this flag. + Additionally, EXECUTABLE may be of the form + NAME=PATH, in which case the given plugin name + is mapped to the given executable even if + the executable's own name differs. + --cpp_out=OUT_DIR Generate C++ header and source. + --csharp_out=OUT_DIR Generate C# source file. + --java_out=OUT_DIR Generate Java source file. + --javanano_out=OUT_DIR Generate Java Nano source file. + --js_out=OUT_DIR Generate JavaScript source. + --objc_out=OUT_DIR Generate Objective C header and source. + --php_out=OUT_DIR Generate PHP source file. + --python_out=OUT_DIR Generate Python source file. + --ruby_out=OUT_DIR Generate Ruby source file. + @ Read options and filenames from file. If a + relative file path is specified, the file + will be searched in the working directory. + The --proto_path option will not affect how + this argument file is searched. Content of + the file will be expanded in the position of + @ as in the argument list. Note + that shell expansion is not applied to the + content of the file (i.e., you cannot use + quotes, wildcards, escapes, commands, etc.). + Each line corresponds to a single argument, + even if it contains spaces. + */ + static string[] s_supportedGenerators = new[] { "cpp", "csharp", "java", + "javanano", "js", "objc", + "php", "python", "ruby" }; + + static readonly TimeSpan s_regexTimeout = TimeSpan.FromMilliseconds(100); + + static readonly List s_errorListFilters = new List() + { + // Example warning with location + //../Protos/greet.proto(19) : warning in column=5 : warning : When enum name is stripped and label is PascalCased (Zero), + // this value label conflicts with Zero. This will make the proto fail to compile for some languages, such as C#. + new ErrorListFilter + { + Pattern = new Regex( + pattern: "^(?'FILENAME'.+?)\\((?'LINE'\\d+)\\) ?: ?warning in column=(?'COLUMN'\\d+) ?: ?(?'TEXT'.*)", + options: RegexOptions.Compiled | RegexOptions.IgnoreCase, + matchTimeout: s_regexTimeout), + LogAction = (log, match) => + { + int.TryParse(match.Groups["LINE"].Value, out var line); + int.TryParse(match.Groups["COLUMN"].Value, out var column); + + log.LogWarning( + subcategory: null, + warningCode: null, + helpKeyword: null, + file: match.Groups["FILENAME"].Value, + lineNumber: line, + columnNumber: column, + endLineNumber: 0, + endColumnNumber: 0, + message: match.Groups["TEXT"].Value); + } + }, + + // Example error with location + //../Protos/greet.proto(14) : error in column=10: "name" is already defined in "Greet.HelloRequest". + new ErrorListFilter + { + Pattern = new Regex( + pattern: "^(?'FILENAME'.+?)\\((?'LINE'\\d+)\\) ?: ?error in column=(?'COLUMN'\\d+) ?: ?(?'TEXT'.*)", + options: RegexOptions.Compiled | RegexOptions.IgnoreCase, + matchTimeout: s_regexTimeout), + LogAction = (log, match) => + { + int.TryParse(match.Groups["LINE"].Value, out var line); + int.TryParse(match.Groups["COLUMN"].Value, out var column); + + log.LogError( + subcategory: null, + errorCode: null, + helpKeyword: null, + file: match.Groups["FILENAME"].Value, + lineNumber: line, + columnNumber: column, + endLineNumber: 0, + endColumnNumber: 0, + message: match.Groups["TEXT"].Value); + } + }, + + // Example warning without location + //../Protos/greet.proto: warning: Import google/protobuf/empty.proto but not used. + new ErrorListFilter + { + Pattern = new Regex( + pattern: "^(?'FILENAME'.+?): ?warning: ?(?'TEXT'.*)", + options: RegexOptions.Compiled | RegexOptions.IgnoreCase, + matchTimeout: s_regexTimeout), + LogAction = (log, match) => + { + log.LogWarning( + subcategory: null, + warningCode: null, + helpKeyword: null, + file: match.Groups["FILENAME"].Value, + lineNumber: 0, + columnNumber: 0, + endLineNumber: 0, + endColumnNumber: 0, + message: match.Groups["TEXT"].Value); + } + }, + + // Example error without location + //../Protos/greet.proto: Import "google/protobuf/empty.proto" was listed twice. + new ErrorListFilter + { + Pattern = new Regex( + pattern: "^(?'FILENAME'.+?): ?(?'TEXT'.*)", + options: RegexOptions.Compiled | RegexOptions.IgnoreCase, + matchTimeout: s_regexTimeout), + LogAction = (log, match) => + { + log.LogError( + subcategory: null, + errorCode: null, + helpKeyword: null, + file: match.Groups["FILENAME"].Value, + lineNumber: 0, + columnNumber: 0, + endLineNumber: 0, + endColumnNumber: 0, + message: match.Groups["TEXT"].Value); + } + } + }; + + /// + /// Code generator. + /// + [Required] + public string Generator { get; set; } + + /// + /// Protobuf files to compile. + /// + [Required] + public ITaskItem[] Protobuf { get; set; } + + /// + /// Directory where protoc dependency files are cached. If provided, dependency + /// output filename is autogenerated from source directory hash and file name. + /// Mutually exclusive with DependencyOut. + /// Switch: --dependency_out (with autogenerated file name). + /// + public string ProtoDepDir { get; set; } + + /// + /// Dependency file full name. Mutually exclusive with ProtoDepDir. + /// Autogenerated file name is available in this property after execution. + /// Switch: --dependency_out. + /// + [Output] + public string DependencyOut { get; set; } + + /// + /// The directories to search for imports. Directories will be searched + /// in order. If not given, the current working directory is used. + /// Switch: --proto_path. + /// + public string[] ProtoPath { get; set; } + + /// + /// Generated code directory. The generator property determines the language. + /// Switch: --GEN_out= (for different generators GEN, e.g. --csharp_out). + /// + [Required] + public string OutputDir { get; set; } + + /// + /// Codegen options. See also OptionsFromMetadata. + /// Switch: --GEN_opt= (for different generators GEN, e.g. --csharp_opt). + /// + public string[] OutputOptions { get; set; } + + /// + /// Additional arguments that will be passed unmodified to protoc (and before any file names). + /// For example, "--experimental_allow_proto3_optional" + /// + public string[] AdditionalProtocArguments { get; set; } + + /// + /// Full path to the gRPC plugin executable. If specified, gRPC generation + /// is enabled for the files. + /// Switch: --plugin=protoc-gen-grpc= + /// + public string GrpcPluginExe { get; set; } + + /// + /// Generated gRPC directory. The generator property determines the + /// language. If gRPC is enabled but this is not given, OutputDir is used. + /// Switch: --grpc_out= + /// + public string GrpcOutputDir { get; set; } + + /// + /// gRPC Codegen options. See also OptionsFromMetadata. + /// --grpc_opt=opt1,opt2=val (comma-separated). + /// + public string[] GrpcOutputOptions { get; set; } + + /// + /// List of files written in addition to generated outputs. Includes a + /// single item for the dependency file if written. + /// + [Output] + public ITaskItem[] AdditionalFileWrites { get; private set; } + + /// + /// List of language files generated by protoc. Empty unless DependencyOut + /// or ProtoDepDir is set, since the file writes are extracted from protoc + /// dependency output file. + /// + [Output] + public ITaskItem[] GeneratedFiles { get; private set; } + + // Hide this property from MSBuild, we should never use a shell script. + private new bool UseCommandProcessor { get; set; } + + protected override string ToolName => Platform.IsWindows ? "protoc.exe" : "protoc"; + + // Since we never try to really locate protoc.exe somehow, just try ToolExe + // as the full tool location. It will be either just protoc[.exe] from + // ToolName above if not set by the user, or a user-supplied full path. The + // base class will then resolve the former using system PATH. + protected override string GenerateFullPathToTool() => ToolExe; + + // Log protoc errors with the High priority (bold white in MsBuild, + // printed with -v:n, and shown in the Output windows in VS). + protected override MessageImportance StandardErrorLoggingImportance => MessageImportance.High; + + // Called by base class to validate arguments and make them consistent. + protected override bool ValidateParameters() + { + // Part of proto command line switches, must be lowercased. + Generator = Generator.ToLowerInvariant(); + if (!System.Array.Exists(s_supportedGenerators, g => g == Generator)) + { + Log.LogError("Invalid value for Generator='{0}'. Supported generators: {1}", + Generator, string.Join(", ", s_supportedGenerators)); + } + + if (ProtoDepDir != null && DependencyOut != null) + { + Log.LogError("Properties ProtoDepDir and DependencyOut may not be both specified"); + } + + if (Protobuf.Length > 1 && (ProtoDepDir != null || DependencyOut != null)) + { + Log.LogError("Proto compiler currently allows only one input when " + + "--dependency_out is specified (via ProtoDepDir or DependencyOut). " + + "Tracking issue: https://github.com/protocolbuffers/protobuf/pull/3959"); + } + + // Use ProtoDepDir to autogenerate DependencyOut + if (ProtoDepDir != null) + { + DependencyOut = DepFileUtil.GetDepFilenameForProto(ProtoDepDir, Protobuf[0].ItemSpec); + } + + if (GrpcPluginExe == null) + { + GrpcOutputOptions = null; + GrpcOutputDir = null; + } + else if (GrpcOutputDir == null) + { + // Use OutputDir for gRPC output if not specified otherwise by user. + GrpcOutputDir = OutputDir; + } + + return !Log.HasLoggedErrors && base.ValidateParameters(); + } + + // Protoc chokes on BOM, naturally. I would! + static readonly Encoding s_utf8WithoutBom = new UTF8Encoding(false); + protected override Encoding ResponseFileEncoding => s_utf8WithoutBom; + + // Protoc takes one argument per line from the response file, and does not + // require any quoting whatsoever. Otherwise, this is similar to the + // standard CommandLineBuilder + class ProtocResponseFileBuilder + { + StringBuilder _data = new StringBuilder(1000); + public override string ToString() => _data.ToString(); + + // If 'value' is not empty, append '--name=value\n'. + public void AddSwitchMaybe(string name, string value) + { + if (!string.IsNullOrEmpty(value)) + { + _data.Append("--").Append(name).Append("=") + .Append(value).Append('\n'); + } + } + + // Add switch with the 'values' separated by commas, for options. + public void AddSwitchMaybe(string name, string[] values) + { + if (values?.Length > 0) + { + _data.Append("--").Append(name).Append("=") + .Append(string.Join(",", values)).Append('\n'); + } + } + + // Add a positional argument to the file data. + public void AddArg(string arg) + { + _data.Append(arg).Append('\n'); + } + }; + + // Called by the base ToolTask to get response file contents. + protected override string GenerateResponseFileCommands() + { + var cmd = new ProtocResponseFileBuilder(); + cmd.AddSwitchMaybe(Generator + "_out", TrimEndSlash(OutputDir)); + cmd.AddSwitchMaybe(Generator + "_opt", OutputOptions); + cmd.AddSwitchMaybe("plugin=protoc-gen-grpc", GrpcPluginExe); + cmd.AddSwitchMaybe("grpc_out", TrimEndSlash(GrpcOutputDir)); + cmd.AddSwitchMaybe("grpc_opt", GrpcOutputOptions); + if (ProtoPath != null) + { + foreach (string path in ProtoPath) + { + cmd.AddSwitchMaybe("proto_path", TrimEndSlash(path)); + } + } + cmd.AddSwitchMaybe("dependency_out", DependencyOut); + cmd.AddSwitchMaybe("error_format", "msvs"); + + if (AdditionalProtocArguments != null) + { + foreach (var additionalProtocOption in AdditionalProtocArguments) + { + cmd.AddArg(additionalProtocOption); + } + } + + foreach (var proto in Protobuf) + { + cmd.AddArg(proto.ItemSpec); + } + return cmd.ToString(); + } + + // Protoc cannot digest trailing slashes in directory names, + // curiously under Linux, but not in Windows. + static string TrimEndSlash(string dir) + { + if (dir == null || dir.Length <= 1) + { + return dir; + } + string trim = dir.TrimEnd('/', '\\'); + // Do not trim the root slash, drive letter possible. + if (trim.Length == 0) + { + // Slashes all the way down. + return dir.Substring(0, 1); + } + if (trim.Length == 2 && dir.Length > 2 && trim[1] == ':') + { + // We have a drive letter and root, e. g. 'C:\' + return dir.Substring(0, 3); + } + return trim; + } + + // Called by the base class to log tool's command line. + // + // Protoc command file is peculiar, with one argument per line, separated + // by newlines. Unwrap it for log readability into a single line, and also + // quote arguments, lest it look weird and so it may be copied and pasted + // into shell. Since this is for logging only, correct enough is correct. + protected override void LogToolCommand(string cmd) + { + var printer = new StringBuilder(1024); + + // Print 'str' slice into 'printer', wrapping in quotes if contains some + // interesting characters in file names, or if empty string. The list of + // characters requiring quoting is not by any means exhaustive; we are + // just striving to be nice, not guaranteeing to be nice. + var quotable = new[] { ' ', '!', '$', '&', '\'', '^' }; + void PrintQuoting(string str, int start, int count) + { + bool wrap = count == 0 || str.IndexOfAny(quotable, start, count) >= 0; + if (wrap) printer.Append('"'); + printer.Append(str, start, count); + if (wrap) printer.Append('"'); + } + + for (int ib = 0, ie; (ie = cmd.IndexOf('\n', ib)) >= 0; ib = ie + 1) + { + // First line only contains both the program name and the first switch. + // We can rely on at least the '--out_dir' switch being always present. + if (ib == 0) + { + int iep = cmd.IndexOf(" --"); + if (iep > 0) + { + PrintQuoting(cmd, 0, iep); + ib = iep + 1; + } + } + printer.Append(' '); + if (cmd[ib] == '-') + { + // Print switch unquoted, including '=' if any. + int iarg = cmd.IndexOf('=', ib, ie - ib); + if (iarg < 0) + { + // Bare switch without a '='. + printer.Append(cmd, ib, ie - ib); + continue; + } + printer.Append(cmd, ib, iarg + 1 - ib); + ib = iarg + 1; + } + // A positional argument or switch value. + PrintQuoting(cmd, ib, ie - ib); + } + + base.LogToolCommand(printer.ToString()); + } + + protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance) + { + foreach (ErrorListFilter filter in s_errorListFilters) + { + Match match = filter.Pattern.Match(singleLine); + + if (match.Success) + { + filter.LogAction(Log, match); + return; + } + } + + base.LogEventsFromTextOutput(singleLine, messageImportance); + } + + // Main task entry point. + public override bool Execute() + { + base.UseCommandProcessor = false; + + bool ok = base.Execute(); + if (!ok) + { + return false; + } + + // Read dependency output file from the compiler to retrieve the + // definitive list of created files. Report the dependency file + // itself as having been written to. + if (DependencyOut != null) + { + string[] outputs = DepFileUtil.ReadDependencyOutputs(DependencyOut, Log); + if (HasLoggedErrors) + { + return false; + } + + GeneratedFiles = new ITaskItem[outputs.Length]; + for (int i = 0; i < outputs.Length; i++) + { + GeneratedFiles[i] = new TaskItem(outputs[i]); + } + AdditionalFileWrites = new ITaskItem[] { new TaskItem(DependencyOut) }; + } + + return true; + } + + class ErrorListFilter + { + public Regex Pattern { get; set; } + public Action LogAction { get; set; } + } + }; +} diff --git a/src/csharp/Grpc.Tools/ProtoCompilerOutputs.cs b/src/csharp/Grpc.Tools/ProtoCompilerOutputs.cs new file mode 100644 index 00000000..0bd9c86a --- /dev/null +++ b/src/csharp/Grpc.Tools/ProtoCompilerOutputs.cs @@ -0,0 +1,100 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System.Collections.Generic; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Grpc.Tools +{ + public class ProtoCompilerOutputs : Task + { + /// + /// Code generator. Currently supported are "csharp", "cpp". + /// + [Required] + public string Generator { get; set; } + + /// + /// All Proto files in the project. The task computes possible outputs + /// from these proto files, and returns them in the PossibleOutputs list. + /// Not all of these might be actually produced by protoc; this is dealt + /// with later in the ProtoCompile task which returns the list of + /// files actually produced by the compiler. + /// + [Required] + public ITaskItem[] Protobuf { get; set; } + + /// + /// All Proto files in the project. A patched copy of all items from + /// Protobuf that might contain updated OutputDir and GrpcOutputDir + /// attributes. + /// + [Output] + public ITaskItem[] PatchedProtobuf { get; set; } + + /// + /// Output items per each potential output. We do not look at existing + /// cached dependency even if they exist, since file may be refactored, + /// affecting whether or not gRPC code file is generated from a given proto. + /// Instead, all potentially possible generated sources are collected. + /// It is a wise idea to generate empty files later for those potentials + /// that are not actually created by protoc, so the dependency checks + /// result in a minimal recompilation. The Protoc task can output the + /// list of files it actually produces, given right combination of its + /// properties. + /// Output items will have the Source metadata set on them: + /// + /// + [Output] + public ITaskItem[] PossibleOutputs { get; private set; } + + public override bool Execute() + { + var generator = GeneratorServices.GetForLanguage(Generator, Log); + if (generator == null) + { + // Error already logged, just return. + return false; + } + + // Get language-specific possible output. The generator expects certain + // metadata be set on the proto item. + var possible = new List(); + var patched = new List(); + foreach (var proto in Protobuf) + { + var patchedProto = generator.PatchOutputDirectory(proto); + patched.Add(patchedProto); + + var outputs = generator.GetPossibleOutputs(patchedProto); + foreach (string output in outputs) + { + var ti = new TaskItem(output); + ti.SetMetadata(Metadata.Source, patchedProto.ItemSpec); + possible.Add(ti); + } + } + + PatchedProtobuf = patched.ToArray(); + PossibleOutputs = possible.ToArray(); + + return !Log.HasLoggedErrors; + } + }; +} diff --git a/src/csharp/Grpc.Tools/ProtoReadDependencies.cs b/src/csharp/Grpc.Tools/ProtoReadDependencies.cs new file mode 100644 index 00000000..34e1379f --- /dev/null +++ b/src/csharp/Grpc.Tools/ProtoReadDependencies.cs @@ -0,0 +1,78 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using System.Collections.Generic; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Grpc.Tools +{ + public class ProtoReadDependencies : Task + { + /// + /// The collection is used to collect possible additional dependencies + /// of proto files cached under ProtoDepDir. + /// + [Required] + public ITaskItem[] Protobuf { get; set; } + + /// + /// Directory where protoc dependency files are cached. + /// + [Required] + public string ProtoDepDir { get; set; } + + /// + /// Additional items that a proto file depends on. This list may include + /// extra dependencies; we do our best to include as few extra positives + /// as reasonable to avoid missing any. The collection item is the + /// dependency, and its Source metadatum is the dependent proto file, like + /// + /// + [Output] + public ITaskItem[] Dependencies { get; private set; } + + public override bool Execute() + { + // Read dependency files, where available. There might be none, + // just use a best effort. + if (ProtoDepDir != null) + { + var dependencies = new List(); + foreach (var proto in Protobuf) + { + string[] deps = DepFileUtil.ReadDependencyInputs(ProtoDepDir, proto.ItemSpec, Log); + foreach (string dep in deps) + { + var ti = new TaskItem(dep); + ti.SetMetadata(Metadata.Source, proto.ItemSpec); + dependencies.Add(ti); + } + } + Dependencies = dependencies.ToArray(); + } + else + { + Dependencies = new ITaskItem[0]; + } + + return !Log.HasLoggedErrors; + } + }; +} diff --git a/src/csharp/Grpc.Tools/ProtoToolsPlatform.cs b/src/csharp/Grpc.Tools/ProtoToolsPlatform.cs new file mode 100644 index 00000000..2bccb0c3 --- /dev/null +++ b/src/csharp/Grpc.Tools/ProtoToolsPlatform.cs @@ -0,0 +1,72 @@ +#region Copyright notice and license + +// Copyright 2018 gRPC authors. +// +// 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. + +#endregion + +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Grpc.Core.Internal; + +namespace Grpc.Tools +{ + /// + /// A helper task to resolve actual OS type and bitness. + /// + public class ProtoToolsPlatform : Task + { + /// + /// Return one of 'linux', 'macosx' or 'windows'. + /// If the OS is unknown, the property is not set. + /// + [Output] + public string Os { get; set; } + + /// + /// Return one of 'x64', 'x86', 'arm64'. + /// If the CPU is unknown, the property is not set. + /// + [Output] + public string Cpu { get; set; } + + + public override bool Execute() + { + switch (Platform.Os) + { + case CommonPlatformDetection.OSKind.Linux: Os = "linux"; break; + case CommonPlatformDetection.OSKind.MacOSX: Os = "macosx"; break; + case CommonPlatformDetection.OSKind.Windows: Os = "windows"; break; + default: Os = ""; break; + } + + switch (Platform.Cpu) + { + case CommonPlatformDetection.CpuArchitecture.X86: Cpu = "x86"; break; + case CommonPlatformDetection.CpuArchitecture.X64: Cpu = "x64"; break; + case CommonPlatformDetection.CpuArchitecture.Arm64: Cpu = "arm64"; break; + default: Cpu = ""; break; + } + + // Use x64 on macosx arm64 until a native protoc is shipped + if (Os == "macosx" && Cpu == "arm64") + { + Cpu = "x64"; + } + + return true; + } + }; +} diff --git a/test/distrib/csharp/DistribTest/Program.cs b/test/distrib/csharp/DistribTest/Program.cs new file mode 100644 index 00000000..79c10ac3 --- /dev/null +++ b/test/distrib/csharp/DistribTest/Program.cs @@ -0,0 +1,74 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System; +using System.Linq; +using System.Threading.Tasks; +using Grpc.Core; +using Helloworld; + +namespace TestGrpcPackage +{ + class MainClass + { + public static void Main(string[] args) + { + // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 + Server server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) + { + Services = { Greeter.BindService(new GreeterImpl()) }, + Ports = { new ServerPort("localhost", ServerPort.PickUnused, ServerCredentials.Insecure) } + }; + server.Start(); + + Channel channel = new Channel("localhost", server.Ports.Single().BoundPort, ChannelCredentials.Insecure); + + try + { + var client = new Greeter.GreeterClient(channel); + String user = "you"; + + var reply = client.SayHello(new HelloRequest { Name = user }); + Console.WriteLine("Greeting: " + reply.Message); + Console.WriteLine("Success!"); + } + finally + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + } + + // Test that codegen works well in case the .csproj has .proto files + // of the same name, but under different directories (see #17672). + // This method doesn't need to be used, it is enough to check that it builds. + private static object CheckDuplicateProtoFilesAreOk() + { + return new DuplicateProto.MessageFromDuplicateProto(); + } + } + + class GreeterImpl : Greeter.GreeterBase + { + // Server side handler of the SayHello RPC + public override Task SayHello(HelloRequest request, ServerCallContext context) + { + return Task.FromResult(new HelloReply { Message = "Hello " + request.Name }); + } + } +} diff --git a/test/distrib/csharp/DistribTest/Properties/AssemblyInfo.cs b/test/distrib/csharp/DistribTest/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..9159e4fe --- /dev/null +++ b/test/distrib/csharp/DistribTest/Properties/AssemblyInfo.cs @@ -0,0 +1,54 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// 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. + +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DistribTest")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DistribTest")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("68755789-f103-4134-9027-b80a2fc9e21a")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")]