commit
3ff9727a37
135 changed files with 12094 additions and 599 deletions
@ -0,0 +1,141 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
<head><title>Interop Test Result</title></head> |
||||||
|
<body> |
||||||
|
|
||||||
|
<%def name="fill_one_test_result(shortname, resultset)"> |
||||||
|
% if shortname in resultset: |
||||||
|
## Because interop tests does not have runs_per_test flag, each test is |
||||||
|
## run once. So there should only be one element for each result. |
||||||
|
<% result = resultset[shortname][0] %> |
||||||
|
% if result.state == 'PASSED': |
||||||
|
<td bgcolor="green">PASS</td> |
||||||
|
% else: |
||||||
|
<% |
||||||
|
tooltip = '' |
||||||
|
if result.returncode > 0 or result.message: |
||||||
|
if result.returncode > 0: |
||||||
|
tooltip = 'returncode: %d ' % result.returncode |
||||||
|
if result.message: |
||||||
|
tooltip = '%smessage: %s' % (tooltip, result.message) |
||||||
|
%> |
||||||
|
% if result.state == 'FAILED': |
||||||
|
<td bgcolor="red"> |
||||||
|
% if tooltip: |
||||||
|
<a href="#" data-toggle="tooltip" data-placement="auto" title="${tooltip | h}">FAIL</a></td> |
||||||
|
% else: |
||||||
|
FAIL</td> |
||||||
|
% endif |
||||||
|
% elif result.state == 'TIMEOUT': |
||||||
|
<td bgcolor="yellow"> |
||||||
|
% if tooltip: |
||||||
|
<a href="#" data-toggle="tooltip" data-placement="auto" title="${tooltip | h}">TIMEOUT</a></td> |
||||||
|
% else: |
||||||
|
TIMEOUT</td> |
||||||
|
% endif |
||||||
|
% endif |
||||||
|
% endif |
||||||
|
% else: |
||||||
|
<td bgcolor="magenta">Not implemented</td> |
||||||
|
% endif |
||||||
|
</%def> |
||||||
|
|
||||||
|
% if num_failures > 1: |
||||||
|
<p><h2><font color="red">${num_failures} tests failed!</font></h2></p> |
||||||
|
% elif num_failures: |
||||||
|
<p><h2><font color="red">${num_failures} test failed!</font></h2></p> |
||||||
|
% else: |
||||||
|
<p><h2><font color="green">All tests passed!</font></h2></p> |
||||||
|
% endif |
||||||
|
|
||||||
|
% if cloud_to_prod: |
||||||
|
## Each column header is the client language. |
||||||
|
<h2>Cloud to Prod</h2> |
||||||
|
<table style="width:100%" border="1"> |
||||||
|
<tr bgcolor="#00BFFF"> |
||||||
|
<th>Client languages ►<br/>Test Cases ▼</th> |
||||||
|
% for client_lang in client_langs: |
||||||
|
<th>${client_lang}</th> |
||||||
|
% endfor |
||||||
|
</tr> |
||||||
|
% for test_case in test_cases + auth_test_cases: |
||||||
|
<tr><td><b>${test_case}</b></td> |
||||||
|
% for client_lang in client_langs: |
||||||
|
<% |
||||||
|
if test_case in auth_test_cases: |
||||||
|
shortname = 'cloud_to_prod_auth:%s:%s' % (client_lang, test_case) |
||||||
|
else: |
||||||
|
shortname = 'cloud_to_prod:%s:%s' % (client_lang, test_case) |
||||||
|
%> |
||||||
|
${fill_one_test_result(shortname, resultset)} |
||||||
|
% endfor |
||||||
|
</tr> |
||||||
|
% endfor |
||||||
|
</table> |
||||||
|
% endif |
||||||
|
|
||||||
|
% if http2_interop: |
||||||
|
## Each column header is the server language. |
||||||
|
<h2>HTTP/2 Interop</h2> |
||||||
|
<table style="width:100%" border="1"> |
||||||
|
<tr bgcolor="#00BFFF"> |
||||||
|
<th>Servers ►<br/>Test Cases ▼</th> |
||||||
|
% for server_lang in server_langs: |
||||||
|
<th>${server_lang}</th> |
||||||
|
% endfor |
||||||
|
% if cloud_to_prod: |
||||||
|
<th>prod</th> |
||||||
|
% endif |
||||||
|
</tr> |
||||||
|
% for test_case in http2_cases: |
||||||
|
<tr><td><b>${test_case}</b></td> |
||||||
|
## Fill up the cells with test result. |
||||||
|
% for server_lang in server_langs: |
||||||
|
<% |
||||||
|
shortname = 'cloud_to_cloud:http2:%s_server:%s' % ( |
||||||
|
server_lang, test_case) |
||||||
|
%> |
||||||
|
${fill_one_test_result(shortname, resultset)} |
||||||
|
% endfor |
||||||
|
% if cloud_to_prod: |
||||||
|
<% shortname = 'cloud_to_prod:http2:%s' % test_case %> |
||||||
|
${fill_one_test_result(shortname, resultset)} |
||||||
|
% endif |
||||||
|
</tr> |
||||||
|
% endfor |
||||||
|
</table> |
||||||
|
% endif |
||||||
|
|
||||||
|
% if server_langs: |
||||||
|
% for test_case in test_cases: |
||||||
|
## Each column header is the client language. |
||||||
|
<h2>${test_case}</h2> |
||||||
|
<table style="width:100%" border="1"> |
||||||
|
<tr bgcolor="#00BFFF"> |
||||||
|
<th>Client languages ►<br/>Server languages ▼</th> |
||||||
|
% for client_lang in client_langs: |
||||||
|
<th>${client_lang}</th> |
||||||
|
% endfor |
||||||
|
</tr> |
||||||
|
## Each row head is the server language. |
||||||
|
% for server_lang in server_langs: |
||||||
|
<tr> |
||||||
|
<td><b>${server_lang}</b></td> |
||||||
|
% for client_lang in client_langs: |
||||||
|
<% |
||||||
|
shortname = 'cloud_to_cloud:%s:%s_server:%s' % ( |
||||||
|
client_lang, server_lang, test_case) |
||||||
|
%> |
||||||
|
${fill_one_test_result(shortname, resultset)} |
||||||
|
% endfor |
||||||
|
</tr> |
||||||
|
% endfor |
||||||
|
</table> |
||||||
|
% endfor |
||||||
|
% endif |
||||||
|
|
||||||
|
<script> |
||||||
|
$(document).ready(function(){$('[data-toggle="tooltip"]').tooltip();}); |
||||||
|
</script> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,3 @@ |
|||||||
|
bin |
||||||
|
obj |
||||||
|
|
@ -0,0 +1,60 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||||
|
<PropertyGroup> |
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
||||||
|
<ProjectGuid>{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}</ProjectGuid> |
||||||
|
<OutputType>Exe</OutputType> |
||||||
|
<RootNamespace>Grpc.IntegrationTesting.QpsWorker</RootNamespace> |
||||||
|
<AssemblyName>Grpc.IntegrationTesting.QpsWorker</AssemblyName> |
||||||
|
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
||||||
|
<DebugSymbols>true</DebugSymbols> |
||||||
|
<DebugType>full</DebugType> |
||||||
|
<Optimize>false</Optimize> |
||||||
|
<OutputPath>bin\Debug</OutputPath> |
||||||
|
<DefineConstants>DEBUG;</DefineConstants> |
||||||
|
<ErrorReport>prompt</ErrorReport> |
||||||
|
<WarningLevel>4</WarningLevel> |
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
||||||
|
<DebugType>pdbonly</DebugType> |
||||||
|
<Optimize>true</Optimize> |
||||||
|
<OutputPath>bin\Release</OutputPath> |
||||||
|
<ErrorReport>prompt</ErrorReport> |
||||||
|
<WarningLevel>4</WarningLevel> |
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget> |
||||||
|
</PropertyGroup> |
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' "> |
||||||
|
<DebugType>pdbonly</DebugType> |
||||||
|
<Optimize>true</Optimize> |
||||||
|
<OutputPath>bin\ReleaseSigned</OutputPath> |
||||||
|
<ErrorReport>prompt</ErrorReport> |
||||||
|
<WarningLevel>4</WarningLevel> |
||||||
|
<SignAssembly>True</SignAssembly> |
||||||
|
<AssemblyOriginatorKeyFile>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile> |
||||||
|
</PropertyGroup> |
||||||
|
<ItemGroup> |
||||||
|
<Reference Include="System" /> |
||||||
|
</ItemGroup> |
||||||
|
<ItemGroup> |
||||||
|
<Compile Include="..\Grpc.Core\Version.cs"> |
||||||
|
<Link>Version.cs</Link> |
||||||
|
</Compile> |
||||||
|
<Compile Include="Program.cs" /> |
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" /> |
||||||
|
</ItemGroup> |
||||||
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> |
||||||
|
<ItemGroup> |
||||||
|
<ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj"> |
||||||
|
<Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project> |
||||||
|
<Name>Grpc.Core</Name> |
||||||
|
</ProjectReference> |
||||||
|
<ProjectReference Include="..\Grpc.IntegrationTesting\Grpc.IntegrationTesting.csproj"> |
||||||
|
<Project>{C61154BA-DD4A-4838-8420-0162A28925E0}</Project> |
||||||
|
<Name>Grpc.IntegrationTesting</Name> |
||||||
|
</ProjectReference> |
||||||
|
</ItemGroup> |
||||||
|
</Project> |
@ -0,0 +1,76 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
|
||||||
|
// Copyright 2015, Google Inc. |
||||||
|
// All rights reserved. |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
#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 |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Implementation of BenchmarkService server |
||||||
|
/// </summary> |
||||||
|
public class BenchmarkServiceImpl : BenchmarkService.IBenchmarkService |
||||||
|
{ |
||||||
|
private readonly int responseSize; |
||||||
|
|
||||||
|
public BenchmarkServiceImpl(int responseSize) |
||||||
|
{ |
||||||
|
this.responseSize = responseSize; |
||||||
|
} |
||||||
|
|
||||||
|
public Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context) |
||||||
|
{ |
||||||
|
var response = new SimpleResponse { Payload = CreateZerosPayload(responseSize) }; |
||||||
|
return Task.FromResult(response); |
||||||
|
} |
||||||
|
|
||||||
|
public async Task StreamingCall(IAsyncStreamReader<SimpleRequest> requestStream, IServerStreamWriter<SimpleResponse> responseStream, ServerCallContext context) |
||||||
|
{ |
||||||
|
await requestStream.ForEachAsync(async request => |
||||||
|
{ |
||||||
|
var response = new SimpleResponse { Payload = CreateZerosPayload(responseSize) }; |
||||||
|
await responseStream.WriteAsync(response); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
private static Payload CreateZerosPayload(int size) |
||||||
|
{ |
||||||
|
return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,153 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
|
||||||
|
// Copyright 2015, Google Inc. |
||||||
|
// All rights reserved. |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
#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 |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Helper methods to start client runners for performance testing. |
||||||
|
/// </summary> |
||||||
|
public static class ClientRunners |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Creates a started client runner. |
||||||
|
/// </summary> |
||||||
|
public static IClientRunner CreateStarted(ClientConfig config) |
||||||
|
{ |
||||||
|
string target = config.ServerTargets.Single(); |
||||||
|
Grpc.Core.Utils.Preconditions.CheckArgument(config.LoadParams.LoadCase == LoadParams.LoadOneofCase.ClosedLoop); |
||||||
|
|
||||||
|
var credentials = config.SecurityParams != null ? TestCredentials.CreateSslCredentials() : ChannelCredentials.Insecure; |
||||||
|
var channel = new Channel(target, credentials); |
||||||
|
|
||||||
|
switch (config.RpcType) |
||||||
|
{ |
||||||
|
case RpcType.UNARY: |
||||||
|
return new SyncUnaryClientRunner(channel, |
||||||
|
config.PayloadConfig.SimpleParams.ReqSize, |
||||||
|
config.HistogramParams); |
||||||
|
|
||||||
|
case RpcType.STREAMING: |
||||||
|
default: |
||||||
|
throw new ArgumentException("Unsupported RpcType."); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Client that starts synchronous unary calls in a closed loop. |
||||||
|
/// </summary> |
||||||
|
public class SyncUnaryClientRunner : IClientRunner |
||||||
|
{ |
||||||
|
const double SecondsToNanos = 1e9; |
||||||
|
|
||||||
|
readonly Channel channel; |
||||||
|
readonly int payloadSize; |
||||||
|
readonly Histogram histogram; |
||||||
|
|
||||||
|
readonly BenchmarkService.IBenchmarkServiceClient client; |
||||||
|
readonly Task runnerTask; |
||||||
|
readonly CancellationTokenSource stoppedCts; |
||||||
|
readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch(); |
||||||
|
|
||||||
|
public SyncUnaryClientRunner(Channel channel, int payloadSize, HistogramParams histogramParams) |
||||||
|
{ |
||||||
|
this.channel = Grpc.Core.Utils.Preconditions.CheckNotNull(channel); |
||||||
|
this.payloadSize = payloadSize; |
||||||
|
this.histogram = new Histogram(histogramParams.Resolution, histogramParams.MaxPossible); |
||||||
|
|
||||||
|
this.stoppedCts = new CancellationTokenSource(); |
||||||
|
this.client = BenchmarkService.NewClient(channel); |
||||||
|
this.runnerTask = Task.Factory.StartNew(Run, TaskCreationOptions.LongRunning); |
||||||
|
} |
||||||
|
|
||||||
|
public ClientStats GetStats(bool reset) |
||||||
|
{ |
||||||
|
var histogramData = histogram.GetSnapshot(reset); |
||||||
|
var secondsElapsed = wallClockStopwatch.GetElapsedSnapshot(reset).TotalSeconds; |
||||||
|
|
||||||
|
// TODO: populate user time and system time |
||||||
|
return new ClientStats |
||||||
|
{ |
||||||
|
Latencies = histogramData, |
||||||
|
TimeElapsed = secondsElapsed, |
||||||
|
TimeUser = 0, |
||||||
|
TimeSystem = 0 |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
public async Task StopAsync() |
||||||
|
{ |
||||||
|
stoppedCts.Cancel(); |
||||||
|
await runnerTask; |
||||||
|
await channel.ShutdownAsync(); |
||||||
|
} |
||||||
|
|
||||||
|
private void Run() |
||||||
|
{ |
||||||
|
var request = new SimpleRequest |
||||||
|
{ |
||||||
|
Payload = CreateZerosPayload(payloadSize) |
||||||
|
}; |
||||||
|
var stopwatch = new Stopwatch(); |
||||||
|
|
||||||
|
while (!stoppedCts.Token.IsCancellationRequested) |
||||||
|
{ |
||||||
|
stopwatch.Restart(); |
||||||
|
client.UnaryCall(request); |
||||||
|
stopwatch.Stop(); |
||||||
|
|
||||||
|
// spec requires data point in nanoseconds. |
||||||
|
histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static Payload CreateZerosPayload(int size) |
||||||
|
{ |
||||||
|
return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,153 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
|
||||||
|
// Copyright 2015, Google Inc. |
||||||
|
// All rights reserved. |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
#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 |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Basic implementation of histogram based on grpc/support/histogram.h. |
||||||
|
/// </summary> |
||||||
|
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) |
||||||
|
{ |
||||||
|
Grpc.Core.Utils.Preconditions.CheckArgument(resolution > 0); |
||||||
|
Grpc.Core.Utils.Preconditions.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); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets snapshot of stats and reset |
||||||
|
/// </summary> |
||||||
|
public HistogramData GetSnapshot(bool reset = false) |
||||||
|
{ |
||||||
|
lock (myLock) |
||||||
|
{ |
||||||
|
return GetSnapshotUnsafe(reset); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Finds bucket index to which given observation should go. |
||||||
|
/// </summary> |
||||||
|
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 HistogramData GetSnapshotUnsafe(bool reset) |
||||||
|
{ |
||||||
|
var data = new HistogramData |
||||||
|
{ |
||||||
|
Count = count, |
||||||
|
Sum = sum, |
||||||
|
SumOfSquares = sumOfSquares, |
||||||
|
MinSeen = min, |
||||||
|
MaxSeen = max, |
||||||
|
Bucket = { buckets } |
||||||
|
}; |
||||||
|
|
||||||
|
if (reset) |
||||||
|
{ |
||||||
|
ResetUnsafe(); |
||||||
|
} |
||||||
|
|
||||||
|
return data; |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,104 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
|
||||||
|
// Copyright 2015, Google Inc. |
||||||
|
// All rights reserved. |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
#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 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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,67 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
|
||||||
|
// Copyright 2015, Google Inc. |
||||||
|
// All rights reserved. |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
#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 |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Abstract client runner. |
||||||
|
/// </summary> |
||||||
|
public interface IClientRunner |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Gets stats snapshot. |
||||||
|
/// </summary> |
||||||
|
/// <returns>The stats.</returns> |
||||||
|
ClientStats GetStats(bool reset); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously stops the client. |
||||||
|
/// </summary> |
||||||
|
/// <returns>Task that finishes when client has come to a full stop.</returns> |
||||||
|
Task StopAsync(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,72 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
|
||||||
|
// Copyright 2015, Google Inc. |
||||||
|
// All rights reserved. |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
#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 |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Abstract server runner. |
||||||
|
/// </summary> |
||||||
|
public interface IServerRunner |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Port on which the server is listening. |
||||||
|
/// </summary> |
||||||
|
int BoundPort { get; } |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets server stats. |
||||||
|
/// </summary> |
||||||
|
/// <returns>The stats.</returns> |
||||||
|
ServerStats GetStats(bool reset); |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously stops the server. |
||||||
|
/// </summary> |
||||||
|
/// <returns>Task that finishes when server has shutdown.</returns> |
||||||
|
Task StopAsync(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,580 @@ |
|||||||
|
// Generated by the protocol buffer compiler. DO NOT EDIT! |
||||||
|
// source: test/proto/benchmarks/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 { |
||||||
|
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||||
|
public static partial class Payloads { |
||||||
|
|
||||||
|
#region Descriptor |
||||||
|
public static pbr::FileDescriptor Descriptor { |
||||||
|
get { return descriptor; } |
||||||
|
} |
||||||
|
private static pbr::FileDescriptor descriptor; |
||||||
|
|
||||||
|
static Payloads() { |
||||||
|
byte[] descriptorData = global::System.Convert.FromBase64String( |
||||||
|
string.Concat( |
||||||
|
"CiR0ZXN0L3Byb3RvL2JlbmNobWFya3MvcGF5bG9hZHMucHJvdG8SDGdycGMu", |
||||||
|
"dGVzdGluZyI3ChBCeXRlQnVmZmVyUGFyYW1zEhAKCHJlcV9zaXplGAEgASgF", |
||||||
|
"EhEKCXJlc3Bfc2l6ZRgCIAEoBSI4ChFTaW1wbGVQcm90b1BhcmFtcxIQCghy", |
||||||
|
"ZXFfc2l6ZRgBIAEoBRIRCglyZXNwX3NpemUYAiABKAUiFAoSQ29tcGxleFBy", |
||||||
|
"b3RvUGFyYW1zIsoBCg1QYXlsb2FkQ29uZmlnEjgKDmJ5dGVidWZfcGFyYW1z", |
||||||
|
"GAEgASgLMh4uZ3JwYy50ZXN0aW5nLkJ5dGVCdWZmZXJQYXJhbXNIABI4Cg1z", |
||||||
|
"aW1wbGVfcGFyYW1zGAIgASgLMh8uZ3JwYy50ZXN0aW5nLlNpbXBsZVByb3Rv", |
||||||
|
"UGFyYW1zSAASOgoOY29tcGxleF9wYXJhbXMYAyABKAsyIC5ncnBjLnRlc3Rp", |
||||||
|
"bmcuQ29tcGxleFByb3RvUGFyYW1zSABCCQoHcGF5bG9hZGIGcHJvdG8z")); |
||||||
|
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, |
||||||
|
new pbr::FileDescriptor[] { }, |
||||||
|
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { |
||||||
|
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ByteBufferParams), new[]{ "ReqSize", "RespSize" }, null, null, null), |
||||||
|
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleProtoParams), new[]{ "ReqSize", "RespSize" }, null, null, null), |
||||||
|
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ComplexProtoParams), null, null, null, null), |
||||||
|
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.PayloadConfig), new[]{ "BytebufParams", "SimpleParams", "ComplexParams" }, new[]{ "Payload" }, null, null) |
||||||
|
})); |
||||||
|
} |
||||||
|
#endregion |
||||||
|
|
||||||
|
} |
||||||
|
#region Messages |
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||||
|
public sealed partial class ByteBufferParams : pb::IMessage<ByteBufferParams> { |
||||||
|
private static readonly pb::MessageParser<ByteBufferParams> _parser = new pb::MessageParser<ByteBufferParams>(() => new ByteBufferParams()); |
||||||
|
public static pb::MessageParser<ByteBufferParams> Parser { get { return _parser; } } |
||||||
|
|
||||||
|
public static pbr::MessageDescriptor Descriptor { |
||||||
|
get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[0]; } |
||||||
|
} |
||||||
|
|
||||||
|
pbr::MessageDescriptor pb::IMessage.Descriptor { |
||||||
|
get { return Descriptor; } |
||||||
|
} |
||||||
|
|
||||||
|
public ByteBufferParams() { |
||||||
|
OnConstruction(); |
||||||
|
} |
||||||
|
|
||||||
|
partial void OnConstruction(); |
||||||
|
|
||||||
|
public ByteBufferParams(ByteBufferParams other) : this() { |
||||||
|
reqSize_ = other.reqSize_; |
||||||
|
respSize_ = other.respSize_; |
||||||
|
} |
||||||
|
|
||||||
|
public ByteBufferParams Clone() { |
||||||
|
return new ByteBufferParams(this); |
||||||
|
} |
||||||
|
|
||||||
|
public const int ReqSizeFieldNumber = 1; |
||||||
|
private int reqSize_; |
||||||
|
public int ReqSize { |
||||||
|
get { return reqSize_; } |
||||||
|
set { |
||||||
|
reqSize_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public const int RespSizeFieldNumber = 2; |
||||||
|
private int respSize_; |
||||||
|
public int RespSize { |
||||||
|
get { return respSize_; } |
||||||
|
set { |
||||||
|
respSize_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override bool Equals(object other) { |
||||||
|
return Equals(other as ByteBufferParams); |
||||||
|
} |
||||||
|
|
||||||
|
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 true; |
||||||
|
} |
||||||
|
|
||||||
|
public override int GetHashCode() { |
||||||
|
int hash = 1; |
||||||
|
if (ReqSize != 0) hash ^= ReqSize.GetHashCode(); |
||||||
|
if (RespSize != 0) hash ^= RespSize.GetHashCode(); |
||||||
|
return hash; |
||||||
|
} |
||||||
|
|
||||||
|
public override string ToString() { |
||||||
|
return pb::JsonFormatter.Default.Format(this); |
||||||
|
} |
||||||
|
|
||||||
|
public void WriteTo(pb::CodedOutputStream output) { |
||||||
|
if (ReqSize != 0) { |
||||||
|
output.WriteRawTag(8); |
||||||
|
output.WriteInt32(ReqSize); |
||||||
|
} |
||||||
|
if (RespSize != 0) { |
||||||
|
output.WriteRawTag(16); |
||||||
|
output.WriteInt32(RespSize); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public int CalculateSize() { |
||||||
|
int size = 0; |
||||||
|
if (ReqSize != 0) { |
||||||
|
size += 1 + pb::CodedOutputStream.ComputeInt32Size(ReqSize); |
||||||
|
} |
||||||
|
if (RespSize != 0) { |
||||||
|
size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize); |
||||||
|
} |
||||||
|
return size; |
||||||
|
} |
||||||
|
|
||||||
|
public void MergeFrom(ByteBufferParams other) { |
||||||
|
if (other == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (other.ReqSize != 0) { |
||||||
|
ReqSize = other.ReqSize; |
||||||
|
} |
||||||
|
if (other.RespSize != 0) { |
||||||
|
RespSize = other.RespSize; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void MergeFrom(pb::CodedInputStream input) { |
||||||
|
uint tag; |
||||||
|
while ((tag = input.ReadTag()) != 0) { |
||||||
|
switch(tag) { |
||||||
|
default: |
||||||
|
input.SkipLastField(); |
||||||
|
break; |
||||||
|
case 8: { |
||||||
|
ReqSize = input.ReadInt32(); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 16: { |
||||||
|
RespSize = input.ReadInt32(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||||
|
public sealed partial class SimpleProtoParams : pb::IMessage<SimpleProtoParams> { |
||||||
|
private static readonly pb::MessageParser<SimpleProtoParams> _parser = new pb::MessageParser<SimpleProtoParams>(() => new SimpleProtoParams()); |
||||||
|
public static pb::MessageParser<SimpleProtoParams> Parser { get { return _parser; } } |
||||||
|
|
||||||
|
public static pbr::MessageDescriptor Descriptor { |
||||||
|
get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[1]; } |
||||||
|
} |
||||||
|
|
||||||
|
pbr::MessageDescriptor pb::IMessage.Descriptor { |
||||||
|
get { return Descriptor; } |
||||||
|
} |
||||||
|
|
||||||
|
public SimpleProtoParams() { |
||||||
|
OnConstruction(); |
||||||
|
} |
||||||
|
|
||||||
|
partial void OnConstruction(); |
||||||
|
|
||||||
|
public SimpleProtoParams(SimpleProtoParams other) : this() { |
||||||
|
reqSize_ = other.reqSize_; |
||||||
|
respSize_ = other.respSize_; |
||||||
|
} |
||||||
|
|
||||||
|
public SimpleProtoParams Clone() { |
||||||
|
return new SimpleProtoParams(this); |
||||||
|
} |
||||||
|
|
||||||
|
public const int ReqSizeFieldNumber = 1; |
||||||
|
private int reqSize_; |
||||||
|
public int ReqSize { |
||||||
|
get { return reqSize_; } |
||||||
|
set { |
||||||
|
reqSize_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public const int RespSizeFieldNumber = 2; |
||||||
|
private int respSize_; |
||||||
|
public int RespSize { |
||||||
|
get { return respSize_; } |
||||||
|
set { |
||||||
|
respSize_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override bool Equals(object other) { |
||||||
|
return Equals(other as SimpleProtoParams); |
||||||
|
} |
||||||
|
|
||||||
|
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 true; |
||||||
|
} |
||||||
|
|
||||||
|
public override int GetHashCode() { |
||||||
|
int hash = 1; |
||||||
|
if (ReqSize != 0) hash ^= ReqSize.GetHashCode(); |
||||||
|
if (RespSize != 0) hash ^= RespSize.GetHashCode(); |
||||||
|
return hash; |
||||||
|
} |
||||||
|
|
||||||
|
public override string ToString() { |
||||||
|
return pb::JsonFormatter.Default.Format(this); |
||||||
|
} |
||||||
|
|
||||||
|
public void WriteTo(pb::CodedOutputStream output) { |
||||||
|
if (ReqSize != 0) { |
||||||
|
output.WriteRawTag(8); |
||||||
|
output.WriteInt32(ReqSize); |
||||||
|
} |
||||||
|
if (RespSize != 0) { |
||||||
|
output.WriteRawTag(16); |
||||||
|
output.WriteInt32(RespSize); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public int CalculateSize() { |
||||||
|
int size = 0; |
||||||
|
if (ReqSize != 0) { |
||||||
|
size += 1 + pb::CodedOutputStream.ComputeInt32Size(ReqSize); |
||||||
|
} |
||||||
|
if (RespSize != 0) { |
||||||
|
size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize); |
||||||
|
} |
||||||
|
return size; |
||||||
|
} |
||||||
|
|
||||||
|
public void MergeFrom(SimpleProtoParams other) { |
||||||
|
if (other == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (other.ReqSize != 0) { |
||||||
|
ReqSize = other.ReqSize; |
||||||
|
} |
||||||
|
if (other.RespSize != 0) { |
||||||
|
RespSize = other.RespSize; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void MergeFrom(pb::CodedInputStream input) { |
||||||
|
uint tag; |
||||||
|
while ((tag = input.ReadTag()) != 0) { |
||||||
|
switch(tag) { |
||||||
|
default: |
||||||
|
input.SkipLastField(); |
||||||
|
break; |
||||||
|
case 8: { |
||||||
|
ReqSize = input.ReadInt32(); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 16: { |
||||||
|
RespSize = input.ReadInt32(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||||
|
public sealed partial class ComplexProtoParams : pb::IMessage<ComplexProtoParams> { |
||||||
|
private static readonly pb::MessageParser<ComplexProtoParams> _parser = new pb::MessageParser<ComplexProtoParams>(() => new ComplexProtoParams()); |
||||||
|
public static pb::MessageParser<ComplexProtoParams> Parser { get { return _parser; } } |
||||||
|
|
||||||
|
public static pbr::MessageDescriptor Descriptor { |
||||||
|
get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[2]; } |
||||||
|
} |
||||||
|
|
||||||
|
pbr::MessageDescriptor pb::IMessage.Descriptor { |
||||||
|
get { return Descriptor; } |
||||||
|
} |
||||||
|
|
||||||
|
public ComplexProtoParams() { |
||||||
|
OnConstruction(); |
||||||
|
} |
||||||
|
|
||||||
|
partial void OnConstruction(); |
||||||
|
|
||||||
|
public ComplexProtoParams(ComplexProtoParams other) : this() { |
||||||
|
} |
||||||
|
|
||||||
|
public ComplexProtoParams Clone() { |
||||||
|
return new ComplexProtoParams(this); |
||||||
|
} |
||||||
|
|
||||||
|
public override bool Equals(object other) { |
||||||
|
return Equals(other as ComplexProtoParams); |
||||||
|
} |
||||||
|
|
||||||
|
public bool Equals(ComplexProtoParams other) { |
||||||
|
if (ReferenceEquals(other, null)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (ReferenceEquals(other, this)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public override int GetHashCode() { |
||||||
|
int hash = 1; |
||||||
|
return hash; |
||||||
|
} |
||||||
|
|
||||||
|
public override string ToString() { |
||||||
|
return pb::JsonFormatter.Default.Format(this); |
||||||
|
} |
||||||
|
|
||||||
|
public void WriteTo(pb::CodedOutputStream output) { |
||||||
|
} |
||||||
|
|
||||||
|
public int CalculateSize() { |
||||||
|
int size = 0; |
||||||
|
return size; |
||||||
|
} |
||||||
|
|
||||||
|
public void MergeFrom(ComplexProtoParams other) { |
||||||
|
if (other == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void MergeFrom(pb::CodedInputStream input) { |
||||||
|
uint tag; |
||||||
|
while ((tag = input.ReadTag()) != 0) { |
||||||
|
switch(tag) { |
||||||
|
default: |
||||||
|
input.SkipLastField(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||||
|
public sealed partial class PayloadConfig : pb::IMessage<PayloadConfig> { |
||||||
|
private static readonly pb::MessageParser<PayloadConfig> _parser = new pb::MessageParser<PayloadConfig>(() => new PayloadConfig()); |
||||||
|
public static pb::MessageParser<PayloadConfig> Parser { get { return _parser; } } |
||||||
|
|
||||||
|
public static pbr::MessageDescriptor Descriptor { |
||||||
|
get { return global::Grpc.Testing.Payloads.Descriptor.MessageTypes[3]; } |
||||||
|
} |
||||||
|
|
||||||
|
pbr::MessageDescriptor pb::IMessage.Descriptor { |
||||||
|
get { return Descriptor; } |
||||||
|
} |
||||||
|
|
||||||
|
public PayloadConfig() { |
||||||
|
OnConstruction(); |
||||||
|
} |
||||||
|
|
||||||
|
partial void OnConstruction(); |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public PayloadConfig Clone() { |
||||||
|
return new PayloadConfig(this); |
||||||
|
} |
||||||
|
|
||||||
|
public const int BytebufParamsFieldNumber = 1; |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public const int SimpleParamsFieldNumber = 2; |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public const int ComplexParamsFieldNumber = 3; |
||||||
|
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_; |
||||||
|
public enum PayloadOneofCase { |
||||||
|
None = 0, |
||||||
|
BytebufParams = 1, |
||||||
|
SimpleParams = 2, |
||||||
|
ComplexParams = 3, |
||||||
|
} |
||||||
|
private PayloadOneofCase payloadCase_ = PayloadOneofCase.None; |
||||||
|
public PayloadOneofCase PayloadCase { |
||||||
|
get { return payloadCase_; } |
||||||
|
} |
||||||
|
|
||||||
|
public void ClearPayload() { |
||||||
|
payloadCase_ = PayloadOneofCase.None; |
||||||
|
payload_ = null; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool Equals(object other) { |
||||||
|
return Equals(other as PayloadConfig); |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
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(); |
||||||
|
return hash; |
||||||
|
} |
||||||
|
|
||||||
|
public override string ToString() { |
||||||
|
return pb::JsonFormatter.Default.Format(this); |
||||||
|
} |
||||||
|
|
||||||
|
public void WriteTo(pb::CodedOutputStream 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); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
return size; |
||||||
|
} |
||||||
|
|
||||||
|
public void MergeFrom(PayloadConfig other) { |
||||||
|
if (other == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
switch (other.PayloadCase) { |
||||||
|
case PayloadOneofCase.BytebufParams: |
||||||
|
BytebufParams = other.BytebufParams; |
||||||
|
break; |
||||||
|
case PayloadOneofCase.SimpleParams: |
||||||
|
SimpleParams = other.SimpleParams; |
||||||
|
break; |
||||||
|
case PayloadOneofCase.ComplexParams: |
||||||
|
ComplexParams = other.ComplexParams; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public void MergeFrom(pb::CodedInputStream input) { |
||||||
|
uint tag; |
||||||
|
while ((tag = input.ReadTag()) != 0) { |
||||||
|
switch(tag) { |
||||||
|
default: |
||||||
|
input.SkipLastField(); |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
#endregion Designer generated code |
@ -0,0 +1,108 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
|
||||||
|
// Copyright 2015, Google Inc. |
||||||
|
// All rights reserved. |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
#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.Utils; |
||||||
|
using Grpc.Testing; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace Grpc.IntegrationTesting |
||||||
|
{ |
||||||
|
public class QpsWorker |
||||||
|
{ |
||||||
|
private class ServerOptions |
||||||
|
{ |
||||||
|
[Option("driver_port", DefaultValue = 0)] |
||||||
|
public int DriverPort { get; set; } |
||||||
|
|
||||||
|
[HelpOption] |
||||||
|
public string GetUsage() |
||||||
|
{ |
||||||
|
var help = new HelpText |
||||||
|
{ |
||||||
|
Heading = "gRPC C# performance testing worker", |
||||||
|
AddDashesToOption = true |
||||||
|
}; |
||||||
|
help.AddPreOptionsLine("Usage:"); |
||||||
|
help.AddOptions(this); |
||||||
|
return help; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ServerOptions options; |
||||||
|
|
||||||
|
private QpsWorker(ServerOptions options) |
||||||
|
{ |
||||||
|
this.options = options; |
||||||
|
} |
||||||
|
|
||||||
|
public static void Run(string[] args) |
||||||
|
{ |
||||||
|
var options = new ServerOptions(); |
||||||
|
if (!Parser.Default.ParseArguments(args, options)) |
||||||
|
{ |
||||||
|
Environment.Exit(1); |
||||||
|
} |
||||||
|
|
||||||
|
var workerServer = new QpsWorker(options); |
||||||
|
workerServer.Run(); |
||||||
|
} |
||||||
|
|
||||||
|
private void Run() |
||||||
|
{ |
||||||
|
string host = "0.0.0.0"; |
||||||
|
int port = options.DriverPort; |
||||||
|
|
||||||
|
var server = new Server |
||||||
|
{ |
||||||
|
Services = { WorkerService.BindService(new WorkerServiceImpl()) }, |
||||||
|
Ports = { new ServerPort(host, options.DriverPort, ServerCredentials.Insecure )} |
||||||
|
}; |
||||||
|
int boundPort = server.Ports.Single().BoundPort; |
||||||
|
Console.WriteLine("Running qps worker server on " + string.Format("{0}:{1}", host, boundPort)); |
||||||
|
server.Start(); |
||||||
|
|
||||||
|
server.ShutdownTask.Wait(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,117 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
|
||||||
|
// Copyright 2015, Google Inc. |
||||||
|
// All rights reserved. |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
#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 |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Runs performance tests in-process. |
||||||
|
/// </summary> |
||||||
|
public class RunnerClientServerTest |
||||||
|
{ |
||||||
|
const string Host = "localhost"; |
||||||
|
IServerRunner serverRunner; |
||||||
|
|
||||||
|
[TestFixtureSetUp] |
||||||
|
public void Init() |
||||||
|
{ |
||||||
|
var serverConfig = new ServerConfig |
||||||
|
{ |
||||||
|
ServerType = ServerType.ASYNC_SERVER, |
||||||
|
Host = Host, |
||||||
|
PayloadConfig = new PayloadConfig |
||||||
|
{ |
||||||
|
SimpleParams = new SimpleProtoParams |
||||||
|
{ |
||||||
|
RespSize = 100 |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
serverRunner = ServerRunners.CreateStarted(serverConfig); |
||||||
|
} |
||||||
|
|
||||||
|
[TestFixtureTearDown] |
||||||
|
public void Cleanup() |
||||||
|
{ |
||||||
|
serverRunner.StopAsync().Wait(); |
||||||
|
} |
||||||
|
|
||||||
|
// Test attribute commented out to prevent running as part of the default test suite. |
||||||
|
//[Test] |
||||||
|
//[Category("Performance")] |
||||||
|
public async Task ClientServerRunner() |
||||||
|
{ |
||||||
|
var config = new ClientConfig |
||||||
|
{ |
||||||
|
ServerTargets = { string.Format("{0}:{1}", Host, serverRunner.BoundPort) }, |
||||||
|
RpcType = RpcType.UNARY, |
||||||
|
LoadParams = new LoadParams { ClosedLoop = new ClosedLoopParams() }, |
||||||
|
PayloadConfig = new PayloadConfig |
||||||
|
{ |
||||||
|
SimpleParams = new SimpleProtoParams |
||||||
|
{ |
||||||
|
ReqSize = 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)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,124 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
|
||||||
|
// Copyright 2015, Google Inc. |
||||||
|
// All rights reserved. |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
#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 |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Helper methods to start server runners for performance testing. |
||||||
|
/// </summary> |
||||||
|
public static class ServerRunners |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Creates a started server runner. |
||||||
|
/// </summary> |
||||||
|
public static IServerRunner CreateStarted(ServerConfig config) |
||||||
|
{ |
||||||
|
Grpc.Core.Utils.Preconditions.CheckArgument(config.ServerType == ServerType.ASYNC_SERVER); |
||||||
|
var credentials = config.SecurityParams != null ? TestCredentials.CreateSslServerCredentials() : ServerCredentials.Insecure; |
||||||
|
|
||||||
|
// TODO: qps_driver needs to setup payload properly... |
||||||
|
int responseSize = config.PayloadConfig != null ? config.PayloadConfig.SimpleParams.RespSize : 0; |
||||||
|
var server = new Server |
||||||
|
{ |
||||||
|
Services = { BenchmarkService.BindService(new BenchmarkServiceImpl(responseSize)) }, |
||||||
|
Ports = { new ServerPort(config.Host, config.Port, credentials) } |
||||||
|
}; |
||||||
|
|
||||||
|
server.Start(); |
||||||
|
return new ServerRunnerImpl(server); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Server runner. |
||||||
|
/// </summary> |
||||||
|
public class ServerRunnerImpl : IServerRunner |
||||||
|
{ |
||||||
|
readonly Server server; |
||||||
|
readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch(); |
||||||
|
|
||||||
|
public ServerRunnerImpl(Server server) |
||||||
|
{ |
||||||
|
this.server = Grpc.Core.Utils.Preconditions.CheckNotNull(server); |
||||||
|
} |
||||||
|
|
||||||
|
public int BoundPort |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
return server.Ports.Single().BoundPort; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets server stats. |
||||||
|
/// </summary> |
||||||
|
/// <returns>The stats.</returns> |
||||||
|
public ServerStats GetStats(bool reset) |
||||||
|
{ |
||||||
|
var secondsElapsed = wallClockStopwatch.GetElapsedSnapshot(reset).TotalSeconds; |
||||||
|
|
||||||
|
// TODO: populate user time and system time |
||||||
|
return new ServerStats |
||||||
|
{ |
||||||
|
TimeElapsed = secondsElapsed, |
||||||
|
TimeUser = 0, |
||||||
|
TimeSystem = 0 |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously stops the server. |
||||||
|
/// </summary> |
||||||
|
/// <returns>Task that finishes when server has shutdown.</returns> |
||||||
|
public Task StopAsync() |
||||||
|
{ |
||||||
|
return server.ShutdownAsync(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
// Generated by the protocol buffer compiler. DO NOT EDIT! |
||||||
|
// source: test/proto/benchmarks/services.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 { |
||||||
|
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||||
|
public static partial class Services { |
||||||
|
|
||||||
|
#region Descriptor |
||||||
|
public static pbr::FileDescriptor Descriptor { |
||||||
|
get { return descriptor; } |
||||||
|
} |
||||||
|
private static pbr::FileDescriptor descriptor; |
||||||
|
|
||||||
|
static Services() { |
||||||
|
byte[] descriptorData = global::System.Convert.FromBase64String( |
||||||
|
string.Concat( |
||||||
|
"CiR0ZXN0L3Byb3RvL2JlbmNobWFya3Mvc2VydmljZXMucHJvdG8SDGdycGMu", |
||||||
|
"dGVzdGluZxoZdGVzdC9wcm90by9tZXNzYWdlcy5wcm90bxojdGVzdC9wcm90", |
||||||
|
"by9iZW5jaG1hcmtzL2NvbnRyb2wucHJvdG8yqgEKEEJlbmNobWFya1NlcnZp", |
||||||
|
"Y2USRgoJVW5hcnlDYWxsEhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlcXVlc3Qa", |
||||||
|
"HC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9uc2USTgoNU3RyZWFtaW5nQ2Fs", |
||||||
|
"bBIbLmdycGMudGVzdGluZy5TaW1wbGVSZXF1ZXN0GhwuZ3JwYy50ZXN0aW5n", |
||||||
|
"LlNpbXBsZVJlc3BvbnNlKAEwATKdAQoNV29ya2VyU2VydmljZRJFCglSdW5T", |
||||||
|
"ZXJ2ZXISGC5ncnBjLnRlc3RpbmcuU2VydmVyQXJncxoaLmdycGMudGVzdGlu", |
||||||
|
"Zy5TZXJ2ZXJTdGF0dXMoATABEkUKCVJ1bkNsaWVudBIYLmdycGMudGVzdGlu", |
||||||
|
"Zy5DbGllbnRBcmdzGhouZ3JwYy50ZXN0aW5nLkNsaWVudFN0YXR1cygBMAFi", |
||||||
|
"BnByb3RvMw==")); |
||||||
|
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, |
||||||
|
new pbr::FileDescriptor[] { global::Grpc.Testing.Messages.Descriptor, global::Grpc.Testing.Control.Descriptor, }, |
||||||
|
new pbr::GeneratedCodeInfo(null, null)); |
||||||
|
} |
||||||
|
#endregion |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endregion Designer generated code |
@ -0,0 +1,198 @@ |
|||||||
|
// Generated by the protocol buffer compiler. DO NOT EDIT! |
||||||
|
// source: test/proto/benchmarks/services.proto |
||||||
|
#region Designer generated code |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Threading; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using Grpc.Core; |
||||||
|
|
||||||
|
namespace Grpc.Testing { |
||||||
|
public static class BenchmarkService |
||||||
|
{ |
||||||
|
static readonly string __ServiceName = "grpc.testing.BenchmarkService"; |
||||||
|
|
||||||
|
static readonly Marshaller<global::Grpc.Testing.SimpleRequest> __Marshaller_SimpleRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleRequest.Parser.ParseFrom); |
||||||
|
static readonly Marshaller<global::Grpc.Testing.SimpleResponse> __Marshaller_SimpleResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleResponse.Parser.ParseFrom); |
||||||
|
|
||||||
|
static readonly Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_UnaryCall = new Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>( |
||||||
|
MethodType.Unary, |
||||||
|
__ServiceName, |
||||||
|
"UnaryCall", |
||||||
|
__Marshaller_SimpleRequest, |
||||||
|
__Marshaller_SimpleResponse); |
||||||
|
|
||||||
|
static readonly Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingCall = new Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>( |
||||||
|
MethodType.DuplexStreaming, |
||||||
|
__ServiceName, |
||||||
|
"StreamingCall", |
||||||
|
__Marshaller_SimpleRequest, |
||||||
|
__Marshaller_SimpleResponse); |
||||||
|
|
||||||
|
// service descriptor |
||||||
|
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor |
||||||
|
{ |
||||||
|
get { return global::Grpc.Testing.Services.Descriptor.Services[0]; } |
||||||
|
} |
||||||
|
|
||||||
|
// client interface |
||||||
|
public interface IBenchmarkServiceClient |
||||||
|
{ |
||||||
|
global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); |
||||||
|
global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options); |
||||||
|
AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); |
||||||
|
AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options); |
||||||
|
AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); |
||||||
|
AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options); |
||||||
|
} |
||||||
|
|
||||||
|
// server-side interface |
||||||
|
public interface IBenchmarkService |
||||||
|
{ |
||||||
|
Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context); |
||||||
|
Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context); |
||||||
|
} |
||||||
|
|
||||||
|
// client stub |
||||||
|
public class BenchmarkServiceClient : ClientBase, IBenchmarkServiceClient |
||||||
|
{ |
||||||
|
public BenchmarkServiceClient(Channel channel) : base(channel) |
||||||
|
{ |
||||||
|
} |
||||||
|
public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) |
||||||
|
{ |
||||||
|
var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken)); |
||||||
|
return Calls.BlockingUnaryCall(call, request); |
||||||
|
} |
||||||
|
public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options) |
||||||
|
{ |
||||||
|
var call = CreateCall(__Method_UnaryCall, options); |
||||||
|
return Calls.BlockingUnaryCall(call, request); |
||||||
|
} |
||||||
|
public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) |
||||||
|
{ |
||||||
|
var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken)); |
||||||
|
return Calls.AsyncUnaryCall(call, request); |
||||||
|
} |
||||||
|
public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options) |
||||||
|
{ |
||||||
|
var call = CreateCall(__Method_UnaryCall, options); |
||||||
|
return Calls.AsyncUnaryCall(call, request); |
||||||
|
} |
||||||
|
public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) |
||||||
|
{ |
||||||
|
var call = CreateCall(__Method_StreamingCall, new CallOptions(headers, deadline, cancellationToken)); |
||||||
|
return Calls.AsyncDuplexStreamingCall(call); |
||||||
|
} |
||||||
|
public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options) |
||||||
|
{ |
||||||
|
var call = CreateCall(__Method_StreamingCall, options); |
||||||
|
return Calls.AsyncDuplexStreamingCall(call); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// creates service definition that can be registered with a server |
||||||
|
public static ServerServiceDefinition BindService(IBenchmarkService serviceImpl) |
||||||
|
{ |
||||||
|
return ServerServiceDefinition.CreateBuilder(__ServiceName) |
||||||
|
.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall) |
||||||
|
.AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build(); |
||||||
|
} |
||||||
|
|
||||||
|
// creates a new client |
||||||
|
public static BenchmarkServiceClient NewClient(Channel channel) |
||||||
|
{ |
||||||
|
return new BenchmarkServiceClient(channel); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
public static class WorkerService |
||||||
|
{ |
||||||
|
static readonly string __ServiceName = "grpc.testing.WorkerService"; |
||||||
|
|
||||||
|
static readonly Marshaller<global::Grpc.Testing.ServerArgs> __Marshaller_ServerArgs = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerArgs.Parser.ParseFrom); |
||||||
|
static readonly Marshaller<global::Grpc.Testing.ServerStatus> __Marshaller_ServerStatus = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerStatus.Parser.ParseFrom); |
||||||
|
static readonly Marshaller<global::Grpc.Testing.ClientArgs> __Marshaller_ClientArgs = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientArgs.Parser.ParseFrom); |
||||||
|
static readonly Marshaller<global::Grpc.Testing.ClientStatus> __Marshaller_ClientStatus = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientStatus.Parser.ParseFrom); |
||||||
|
|
||||||
|
static readonly Method<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> __Method_RunServer = new Method<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus>( |
||||||
|
MethodType.DuplexStreaming, |
||||||
|
__ServiceName, |
||||||
|
"RunServer", |
||||||
|
__Marshaller_ServerArgs, |
||||||
|
__Marshaller_ServerStatus); |
||||||
|
|
||||||
|
static readonly Method<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> __Method_RunClient = new Method<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus>( |
||||||
|
MethodType.DuplexStreaming, |
||||||
|
__ServiceName, |
||||||
|
"RunClient", |
||||||
|
__Marshaller_ClientArgs, |
||||||
|
__Marshaller_ClientStatus); |
||||||
|
|
||||||
|
// service descriptor |
||||||
|
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor |
||||||
|
{ |
||||||
|
get { return global::Grpc.Testing.Services.Descriptor.Services[1]; } |
||||||
|
} |
||||||
|
|
||||||
|
// client interface |
||||||
|
public interface IWorkerServiceClient |
||||||
|
{ |
||||||
|
AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); |
||||||
|
AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options); |
||||||
|
AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); |
||||||
|
AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options); |
||||||
|
} |
||||||
|
|
||||||
|
// server-side interface |
||||||
|
public interface IWorkerService |
||||||
|
{ |
||||||
|
Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context); |
||||||
|
Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context); |
||||||
|
} |
||||||
|
|
||||||
|
// client stub |
||||||
|
public class WorkerServiceClient : ClientBase, IWorkerServiceClient |
||||||
|
{ |
||||||
|
public WorkerServiceClient(Channel channel) : base(channel) |
||||||
|
{ |
||||||
|
} |
||||||
|
public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) |
||||||
|
{ |
||||||
|
var call = CreateCall(__Method_RunServer, new CallOptions(headers, deadline, cancellationToken)); |
||||||
|
return Calls.AsyncDuplexStreamingCall(call); |
||||||
|
} |
||||||
|
public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options) |
||||||
|
{ |
||||||
|
var call = CreateCall(__Method_RunServer, options); |
||||||
|
return Calls.AsyncDuplexStreamingCall(call); |
||||||
|
} |
||||||
|
public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) |
||||||
|
{ |
||||||
|
var call = CreateCall(__Method_RunClient, new CallOptions(headers, deadline, cancellationToken)); |
||||||
|
return Calls.AsyncDuplexStreamingCall(call); |
||||||
|
} |
||||||
|
public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options) |
||||||
|
{ |
||||||
|
var call = CreateCall(__Method_RunClient, options); |
||||||
|
return Calls.AsyncDuplexStreamingCall(call); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// creates service definition that can be registered with a server |
||||||
|
public static ServerServiceDefinition BindService(IWorkerService serviceImpl) |
||||||
|
{ |
||||||
|
return ServerServiceDefinition.CreateBuilder(__ServiceName) |
||||||
|
.AddMethod(__Method_RunServer, serviceImpl.RunServer) |
||||||
|
.AddMethod(__Method_RunClient, serviceImpl.RunClient).Build(); |
||||||
|
} |
||||||
|
|
||||||
|
// creates a new client |
||||||
|
public static WorkerServiceClient NewClient(Channel channel) |
||||||
|
{ |
||||||
|
return new WorkerServiceClient(channel); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
#endregion |
@ -0,0 +1,744 @@ |
|||||||
|
// Generated by the protocol buffer compiler. DO NOT EDIT! |
||||||
|
// source: test/proto/benchmarks/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 { |
||||||
|
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||||
|
public static partial class Stats { |
||||||
|
|
||||||
|
#region Descriptor |
||||||
|
public static pbr::FileDescriptor Descriptor { |
||||||
|
get { return descriptor; } |
||||||
|
} |
||||||
|
private static pbr::FileDescriptor descriptor; |
||||||
|
|
||||||
|
static Stats() { |
||||||
|
byte[] descriptorData = global::System.Convert.FromBase64String( |
||||||
|
string.Concat( |
||||||
|
"CiF0ZXN0L3Byb3RvL2JlbmNobWFya3Mvc3RhdHMucHJvdG8SDGdycGMudGVz", |
||||||
|
"dGluZyJLCgtTZXJ2ZXJTdGF0cxIUCgx0aW1lX2VsYXBzZWQYASABKAESEQoJ", |
||||||
|
"dGltZV91c2VyGAIgASgBEhMKC3RpbWVfc3lzdGVtGAMgASgBIjsKD0hpc3Rv", |
||||||
|
"Z3JhbVBhcmFtcxISCgpyZXNvbHV0aW9uGAEgASgBEhQKDG1heF9wb3NzaWJs", |
||||||
|
"ZRgCIAEoASJ3Cg1IaXN0b2dyYW1EYXRhEg4KBmJ1Y2tldBgBIAMoDRIQCght", |
||||||
|
"aW5fc2VlbhgCIAEoARIQCghtYXhfc2VlbhgDIAEoARILCgNzdW0YBCABKAES", |
||||||
|
"FgoOc3VtX29mX3NxdWFyZXMYBSABKAESDQoFY291bnQYBiABKAEiewoLQ2xp", |
||||||
|
"ZW50U3RhdHMSLgoJbGF0ZW5jaWVzGAEgASgLMhsuZ3JwYy50ZXN0aW5nLkhp", |
||||||
|
"c3RvZ3JhbURhdGESFAoMdGltZV9lbGFwc2VkGAIgASgBEhEKCXRpbWVfdXNl", |
||||||
|
"chgDIAEoARITCgt0aW1lX3N5c3RlbRgEIAEoAWIGcHJvdG8z")); |
||||||
|
descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, |
||||||
|
new pbr::FileDescriptor[] { }, |
||||||
|
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { |
||||||
|
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ServerStats), new[]{ "TimeElapsed", "TimeUser", "TimeSystem" }, null, null, null), |
||||||
|
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.HistogramParams), new[]{ "Resolution", "MaxPossible" }, null, null, null), |
||||||
|
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.HistogramData), new[]{ "Bucket", "MinSeen", "MaxSeen", "Sum", "SumOfSquares", "Count" }, null, null, null), |
||||||
|
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ClientStats), new[]{ "Latencies", "TimeElapsed", "TimeUser", "TimeSystem" }, null, null, null) |
||||||
|
})); |
||||||
|
} |
||||||
|
#endregion |
||||||
|
|
||||||
|
} |
||||||
|
#region Messages |
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||||
|
public sealed partial class ServerStats : pb::IMessage<ServerStats> { |
||||||
|
private static readonly pb::MessageParser<ServerStats> _parser = new pb::MessageParser<ServerStats>(() => new ServerStats()); |
||||||
|
public static pb::MessageParser<ServerStats> Parser { get { return _parser; } } |
||||||
|
|
||||||
|
public static pbr::MessageDescriptor Descriptor { |
||||||
|
get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[0]; } |
||||||
|
} |
||||||
|
|
||||||
|
pbr::MessageDescriptor pb::IMessage.Descriptor { |
||||||
|
get { return Descriptor; } |
||||||
|
} |
||||||
|
|
||||||
|
public ServerStats() { |
||||||
|
OnConstruction(); |
||||||
|
} |
||||||
|
|
||||||
|
partial void OnConstruction(); |
||||||
|
|
||||||
|
public ServerStats(ServerStats other) : this() { |
||||||
|
timeElapsed_ = other.timeElapsed_; |
||||||
|
timeUser_ = other.timeUser_; |
||||||
|
timeSystem_ = other.timeSystem_; |
||||||
|
} |
||||||
|
|
||||||
|
public ServerStats Clone() { |
||||||
|
return new ServerStats(this); |
||||||
|
} |
||||||
|
|
||||||
|
public const int TimeElapsedFieldNumber = 1; |
||||||
|
private double timeElapsed_; |
||||||
|
public double TimeElapsed { |
||||||
|
get { return timeElapsed_; } |
||||||
|
set { |
||||||
|
timeElapsed_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public const int TimeUserFieldNumber = 2; |
||||||
|
private double timeUser_; |
||||||
|
public double TimeUser { |
||||||
|
get { return timeUser_; } |
||||||
|
set { |
||||||
|
timeUser_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public const int TimeSystemFieldNumber = 3; |
||||||
|
private double timeSystem_; |
||||||
|
public double TimeSystem { |
||||||
|
get { return timeSystem_; } |
||||||
|
set { |
||||||
|
timeSystem_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override bool Equals(object other) { |
||||||
|
return Equals(other as ServerStats); |
||||||
|
} |
||||||
|
|
||||||
|
public bool Equals(ServerStats other) { |
||||||
|
if (ReferenceEquals(other, null)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (ReferenceEquals(other, this)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
if (TimeElapsed != other.TimeElapsed) return false; |
||||||
|
if (TimeUser != other.TimeUser) return false; |
||||||
|
if (TimeSystem != other.TimeSystem) return false; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public override int GetHashCode() { |
||||||
|
int hash = 1; |
||||||
|
if (TimeElapsed != 0D) hash ^= TimeElapsed.GetHashCode(); |
||||||
|
if (TimeUser != 0D) hash ^= TimeUser.GetHashCode(); |
||||||
|
if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode(); |
||||||
|
return hash; |
||||||
|
} |
||||||
|
|
||||||
|
public override string ToString() { |
||||||
|
return pb::JsonFormatter.Default.Format(this); |
||||||
|
} |
||||||
|
|
||||||
|
public void WriteTo(pb::CodedOutputStream 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); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public int CalculateSize() { |
||||||
|
int size = 0; |
||||||
|
if (TimeElapsed != 0D) { |
||||||
|
size += 1 + 8; |
||||||
|
} |
||||||
|
if (TimeUser != 0D) { |
||||||
|
size += 1 + 8; |
||||||
|
} |
||||||
|
if (TimeSystem != 0D) { |
||||||
|
size += 1 + 8; |
||||||
|
} |
||||||
|
return size; |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void MergeFrom(pb::CodedInputStream input) { |
||||||
|
uint tag; |
||||||
|
while ((tag = input.ReadTag()) != 0) { |
||||||
|
switch(tag) { |
||||||
|
default: |
||||||
|
input.SkipLastField(); |
||||||
|
break; |
||||||
|
case 9: { |
||||||
|
TimeElapsed = input.ReadDouble(); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 17: { |
||||||
|
TimeUser = input.ReadDouble(); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 25: { |
||||||
|
TimeSystem = input.ReadDouble(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||||
|
public sealed partial class HistogramParams : pb::IMessage<HistogramParams> { |
||||||
|
private static readonly pb::MessageParser<HistogramParams> _parser = new pb::MessageParser<HistogramParams>(() => new HistogramParams()); |
||||||
|
public static pb::MessageParser<HistogramParams> Parser { get { return _parser; } } |
||||||
|
|
||||||
|
public static pbr::MessageDescriptor Descriptor { |
||||||
|
get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[1]; } |
||||||
|
} |
||||||
|
|
||||||
|
pbr::MessageDescriptor pb::IMessage.Descriptor { |
||||||
|
get { return Descriptor; } |
||||||
|
} |
||||||
|
|
||||||
|
public HistogramParams() { |
||||||
|
OnConstruction(); |
||||||
|
} |
||||||
|
|
||||||
|
partial void OnConstruction(); |
||||||
|
|
||||||
|
public HistogramParams(HistogramParams other) : this() { |
||||||
|
resolution_ = other.resolution_; |
||||||
|
maxPossible_ = other.maxPossible_; |
||||||
|
} |
||||||
|
|
||||||
|
public HistogramParams Clone() { |
||||||
|
return new HistogramParams(this); |
||||||
|
} |
||||||
|
|
||||||
|
public const int ResolutionFieldNumber = 1; |
||||||
|
private double resolution_; |
||||||
|
public double Resolution { |
||||||
|
get { return resolution_; } |
||||||
|
set { |
||||||
|
resolution_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public const int MaxPossibleFieldNumber = 2; |
||||||
|
private double maxPossible_; |
||||||
|
public double MaxPossible { |
||||||
|
get { return maxPossible_; } |
||||||
|
set { |
||||||
|
maxPossible_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override bool Equals(object other) { |
||||||
|
return Equals(other as HistogramParams); |
||||||
|
} |
||||||
|
|
||||||
|
public bool Equals(HistogramParams other) { |
||||||
|
if (ReferenceEquals(other, null)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (ReferenceEquals(other, this)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
if (Resolution != other.Resolution) return false; |
||||||
|
if (MaxPossible != other.MaxPossible) return false; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public override int GetHashCode() { |
||||||
|
int hash = 1; |
||||||
|
if (Resolution != 0D) hash ^= Resolution.GetHashCode(); |
||||||
|
if (MaxPossible != 0D) hash ^= MaxPossible.GetHashCode(); |
||||||
|
return hash; |
||||||
|
} |
||||||
|
|
||||||
|
public override string ToString() { |
||||||
|
return pb::JsonFormatter.Default.Format(this); |
||||||
|
} |
||||||
|
|
||||||
|
public void WriteTo(pb::CodedOutputStream output) { |
||||||
|
if (Resolution != 0D) { |
||||||
|
output.WriteRawTag(9); |
||||||
|
output.WriteDouble(Resolution); |
||||||
|
} |
||||||
|
if (MaxPossible != 0D) { |
||||||
|
output.WriteRawTag(17); |
||||||
|
output.WriteDouble(MaxPossible); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public int CalculateSize() { |
||||||
|
int size = 0; |
||||||
|
if (Resolution != 0D) { |
||||||
|
size += 1 + 8; |
||||||
|
} |
||||||
|
if (MaxPossible != 0D) { |
||||||
|
size += 1 + 8; |
||||||
|
} |
||||||
|
return size; |
||||||
|
} |
||||||
|
|
||||||
|
public void MergeFrom(HistogramParams other) { |
||||||
|
if (other == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (other.Resolution != 0D) { |
||||||
|
Resolution = other.Resolution; |
||||||
|
} |
||||||
|
if (other.MaxPossible != 0D) { |
||||||
|
MaxPossible = other.MaxPossible; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void MergeFrom(pb::CodedInputStream input) { |
||||||
|
uint tag; |
||||||
|
while ((tag = input.ReadTag()) != 0) { |
||||||
|
switch(tag) { |
||||||
|
default: |
||||||
|
input.SkipLastField(); |
||||||
|
break; |
||||||
|
case 9: { |
||||||
|
Resolution = input.ReadDouble(); |
||||||
|
break; |
||||||
|
} |
||||||
|
case 17: { |
||||||
|
MaxPossible = input.ReadDouble(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||||
|
public sealed partial class HistogramData : pb::IMessage<HistogramData> { |
||||||
|
private static readonly pb::MessageParser<HistogramData> _parser = new pb::MessageParser<HistogramData>(() => new HistogramData()); |
||||||
|
public static pb::MessageParser<HistogramData> Parser { get { return _parser; } } |
||||||
|
|
||||||
|
public static pbr::MessageDescriptor Descriptor { |
||||||
|
get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[2]; } |
||||||
|
} |
||||||
|
|
||||||
|
pbr::MessageDescriptor pb::IMessage.Descriptor { |
||||||
|
get { return Descriptor; } |
||||||
|
} |
||||||
|
|
||||||
|
public HistogramData() { |
||||||
|
OnConstruction(); |
||||||
|
} |
||||||
|
|
||||||
|
partial void OnConstruction(); |
||||||
|
|
||||||
|
public HistogramData(HistogramData other) : this() { |
||||||
|
bucket_ = other.bucket_.Clone(); |
||||||
|
minSeen_ = other.minSeen_; |
||||||
|
maxSeen_ = other.maxSeen_; |
||||||
|
sum_ = other.sum_; |
||||||
|
sumOfSquares_ = other.sumOfSquares_; |
||||||
|
count_ = other.count_; |
||||||
|
} |
||||||
|
|
||||||
|
public HistogramData Clone() { |
||||||
|
return new HistogramData(this); |
||||||
|
} |
||||||
|
|
||||||
|
public const int BucketFieldNumber = 1; |
||||||
|
private static readonly pb::FieldCodec<uint> _repeated_bucket_codec |
||||||
|
= pb::FieldCodec.ForUInt32(10); |
||||||
|
private readonly pbc::RepeatedField<uint> bucket_ = new pbc::RepeatedField<uint>(); |
||||||
|
public pbc::RepeatedField<uint> Bucket { |
||||||
|
get { return bucket_; } |
||||||
|
} |
||||||
|
|
||||||
|
public const int MinSeenFieldNumber = 2; |
||||||
|
private double minSeen_; |
||||||
|
public double MinSeen { |
||||||
|
get { return minSeen_; } |
||||||
|
set { |
||||||
|
minSeen_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public const int MaxSeenFieldNumber = 3; |
||||||
|
private double maxSeen_; |
||||||
|
public double MaxSeen { |
||||||
|
get { return maxSeen_; } |
||||||
|
set { |
||||||
|
maxSeen_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public const int SumFieldNumber = 4; |
||||||
|
private double sum_; |
||||||
|
public double Sum { |
||||||
|
get { return sum_; } |
||||||
|
set { |
||||||
|
sum_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public const int SumOfSquaresFieldNumber = 5; |
||||||
|
private double sumOfSquares_; |
||||||
|
public double SumOfSquares { |
||||||
|
get { return sumOfSquares_; } |
||||||
|
set { |
||||||
|
sumOfSquares_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public const int CountFieldNumber = 6; |
||||||
|
private double count_; |
||||||
|
public double Count { |
||||||
|
get { return count_; } |
||||||
|
set { |
||||||
|
count_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override bool Equals(object other) { |
||||||
|
return Equals(other as HistogramData); |
||||||
|
} |
||||||
|
|
||||||
|
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 (MinSeen != other.MinSeen) return false; |
||||||
|
if (MaxSeen != other.MaxSeen) return false; |
||||||
|
if (Sum != other.Sum) return false; |
||||||
|
if (SumOfSquares != other.SumOfSquares) return false; |
||||||
|
if (Count != other.Count) return false; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public override int GetHashCode() { |
||||||
|
int hash = 1; |
||||||
|
hash ^= bucket_.GetHashCode(); |
||||||
|
if (MinSeen != 0D) hash ^= MinSeen.GetHashCode(); |
||||||
|
if (MaxSeen != 0D) hash ^= MaxSeen.GetHashCode(); |
||||||
|
if (Sum != 0D) hash ^= Sum.GetHashCode(); |
||||||
|
if (SumOfSquares != 0D) hash ^= SumOfSquares.GetHashCode(); |
||||||
|
if (Count != 0D) hash ^= Count.GetHashCode(); |
||||||
|
return hash; |
||||||
|
} |
||||||
|
|
||||||
|
public override string ToString() { |
||||||
|
return pb::JsonFormatter.Default.Format(this); |
||||||
|
} |
||||||
|
|
||||||
|
public void WriteTo(pb::CodedOutputStream output) { |
||||||
|
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); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
return size; |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void MergeFrom(pb::CodedInputStream input) { |
||||||
|
uint tag; |
||||||
|
while ((tag = input.ReadTag()) != 0) { |
||||||
|
switch(tag) { |
||||||
|
default: |
||||||
|
input.SkipLastField(); |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] |
||||||
|
public sealed partial class ClientStats : pb::IMessage<ClientStats> { |
||||||
|
private static readonly pb::MessageParser<ClientStats> _parser = new pb::MessageParser<ClientStats>(() => new ClientStats()); |
||||||
|
public static pb::MessageParser<ClientStats> Parser { get { return _parser; } } |
||||||
|
|
||||||
|
public static pbr::MessageDescriptor Descriptor { |
||||||
|
get { return global::Grpc.Testing.Stats.Descriptor.MessageTypes[3]; } |
||||||
|
} |
||||||
|
|
||||||
|
pbr::MessageDescriptor pb::IMessage.Descriptor { |
||||||
|
get { return Descriptor; } |
||||||
|
} |
||||||
|
|
||||||
|
public ClientStats() { |
||||||
|
OnConstruction(); |
||||||
|
} |
||||||
|
|
||||||
|
partial void OnConstruction(); |
||||||
|
|
||||||
|
public ClientStats(ClientStats other) : this() { |
||||||
|
Latencies = other.latencies_ != null ? other.Latencies.Clone() : null; |
||||||
|
timeElapsed_ = other.timeElapsed_; |
||||||
|
timeUser_ = other.timeUser_; |
||||||
|
timeSystem_ = other.timeSystem_; |
||||||
|
} |
||||||
|
|
||||||
|
public ClientStats Clone() { |
||||||
|
return new ClientStats(this); |
||||||
|
} |
||||||
|
|
||||||
|
public const int LatenciesFieldNumber = 1; |
||||||
|
private global::Grpc.Testing.HistogramData latencies_; |
||||||
|
public global::Grpc.Testing.HistogramData Latencies { |
||||||
|
get { return latencies_; } |
||||||
|
set { |
||||||
|
latencies_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public const int TimeElapsedFieldNumber = 2; |
||||||
|
private double timeElapsed_; |
||||||
|
public double TimeElapsed { |
||||||
|
get { return timeElapsed_; } |
||||||
|
set { |
||||||
|
timeElapsed_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public const int TimeUserFieldNumber = 3; |
||||||
|
private double timeUser_; |
||||||
|
public double TimeUser { |
||||||
|
get { return timeUser_; } |
||||||
|
set { |
||||||
|
timeUser_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public const int TimeSystemFieldNumber = 4; |
||||||
|
private double timeSystem_; |
||||||
|
public double TimeSystem { |
||||||
|
get { return timeSystem_; } |
||||||
|
set { |
||||||
|
timeSystem_ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override bool Equals(object other) { |
||||||
|
return Equals(other as ClientStats); |
||||||
|
} |
||||||
|
|
||||||
|
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 (TimeElapsed != other.TimeElapsed) return false; |
||||||
|
if (TimeUser != other.TimeUser) return false; |
||||||
|
if (TimeSystem != other.TimeSystem) return false; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public override int GetHashCode() { |
||||||
|
int hash = 1; |
||||||
|
if (latencies_ != null) hash ^= Latencies.GetHashCode(); |
||||||
|
if (TimeElapsed != 0D) hash ^= TimeElapsed.GetHashCode(); |
||||||
|
if (TimeUser != 0D) hash ^= TimeUser.GetHashCode(); |
||||||
|
if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode(); |
||||||
|
return hash; |
||||||
|
} |
||||||
|
|
||||||
|
public override string ToString() { |
||||||
|
return pb::JsonFormatter.Default.Format(this); |
||||||
|
} |
||||||
|
|
||||||
|
public void WriteTo(pb::CodedOutputStream 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); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
return size; |
||||||
|
} |
||||||
|
|
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void MergeFrom(pb::CodedInputStream input) { |
||||||
|
uint tag; |
||||||
|
while ((tag = input.ReadTag()) != 0) { |
||||||
|
switch(tag) { |
||||||
|
default: |
||||||
|
input.SkipLastField(); |
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
#endregion |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
#endregion Designer generated code |
@ -0,0 +1,78 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
|
||||||
|
// Copyright 2015, Google Inc. |
||||||
|
// All rights reserved. |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
#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 |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Snapshottable wall clock stopwatch. |
||||||
|
/// </summary> |
||||||
|
public class WallClockStopwatch |
||||||
|
{ |
||||||
|
long startTicks; |
||||||
|
|
||||||
|
public WallClockStopwatch() |
||||||
|
{ |
||||||
|
this.startTicks = DateTime.UtcNow.Ticks; |
||||||
|
} |
||||||
|
|
||||||
|
public TimeSpan GetElapsedSnapshot(bool reset) |
||||||
|
{ |
||||||
|
var utcNow = DateTime.UtcNow; |
||||||
|
|
||||||
|
long oldStartTicks; |
||||||
|
if (reset) |
||||||
|
{ |
||||||
|
oldStartTicks = Interlocked.Exchange(ref this.startTicks, utcNow.Ticks); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
oldStartTicks = this.startTicks; |
||||||
|
} |
||||||
|
return utcNow - new DateTime(oldStartTicks, DateTimeKind.Utc); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,96 @@ |
|||||||
|
#region Copyright notice and license |
||||||
|
|
||||||
|
// Copyright 2015, Google Inc. |
||||||
|
// All rights reserved. |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
#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 |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Implementation of WorkerService server |
||||||
|
/// </summary> |
||||||
|
public class WorkerServiceImpl : WorkerService.IWorkerService |
||||||
|
{ |
||||||
|
public async Task RunServer(IAsyncStreamReader<ServerArgs> requestStream, IServerStreamWriter<ServerStatus> responseStream, ServerCallContext context) |
||||||
|
{ |
||||||
|
Grpc.Core.Utils.Preconditions.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 = 0, // TODO: set number of cores |
||||||
|
}); |
||||||
|
|
||||||
|
while (await requestStream.MoveNext()) |
||||||
|
{ |
||||||
|
var reset = requestStream.Current.Mark.Reset; |
||||||
|
await responseStream.WriteAsync(new ServerStatus |
||||||
|
{ |
||||||
|
Stats = runner.GetStats(reset) |
||||||
|
}); |
||||||
|
} |
||||||
|
await runner.StopAsync(); |
||||||
|
} |
||||||
|
|
||||||
|
public async Task RunClient(IAsyncStreamReader<ClientArgs> requestStream, IServerStreamWriter<ClientStatus> responseStream, ServerCallContext context) |
||||||
|
{ |
||||||
|
Grpc.Core.Utils.Preconditions.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(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,446 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright 2015, Google Inc. |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* * Redistributions in binary form must reproduce the above |
||||||
|
* copyright notice, this list of conditions and the following disclaimer |
||||||
|
* in the documentation and/or other materials provided with the |
||||||
|
* distribution. |
||||||
|
* * Neither the name of Google Inc. nor the names of its |
||||||
|
* contributors may be used to endorse or promote products derived from |
||||||
|
* this software without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "test/core/end2end/end2end_tests.h" |
||||||
|
|
||||||
|
#include <stdio.h> |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
#include <grpc/byte_buffer.h> |
||||||
|
#include <grpc/grpc.h> |
||||||
|
#include <grpc/support/alloc.h> |
||||||
|
#include <grpc/support/log.h> |
||||||
|
#include <grpc/support/string_util.h> |
||||||
|
#include <grpc/support/time.h> |
||||||
|
#include <grpc/support/useful.h> |
||||||
|
|
||||||
|
#include "src/core/support/string.h" |
||||||
|
#include "test/core/end2end/cq_verifier.h" |
||||||
|
|
||||||
|
static void *tag(gpr_intptr t) { return (void *)t; } |
||||||
|
|
||||||
|
const char *hobbits[][2] = {{"Adaldrida", "Brandybuck"}, |
||||||
|
{"Adamanta", "Took"}, |
||||||
|
{"Adalgrim", "Took"}, |
||||||
|
{"Adelard", "Took"}, |
||||||
|
{"Amaranth", "Brandybuck"}, |
||||||
|
{"Andwise", "Roper"}, |
||||||
|
{"Angelica", "Baggins"}, |
||||||
|
{"Asphodel", "Burrows"}, |
||||||
|
{"Balbo", "Baggins"}, |
||||||
|
{"Bandobras", "Took"}, |
||||||
|
{"Belba", "Bolger"}, |
||||||
|
{"Bell", "Gamgee"}, |
||||||
|
{"Belladonna", "Baggins"}, |
||||||
|
{"Berylla", "Baggins"}, |
||||||
|
{"Bilbo", "Baggins"}, |
||||||
|
{"Bilbo", "Gardner"}, |
||||||
|
{"Bill", "Butcher"}, |
||||||
|
{"Bingo", "Baggins"}, |
||||||
|
{"Bodo", "Proudfoot"}, |
||||||
|
{"Bowman", "Cotton"}, |
||||||
|
{"Bungo", "Baggins"}, |
||||||
|
{"Camellia", "Sackville"}, |
||||||
|
{"Carl", "Cotton"}, |
||||||
|
{"Celandine", "Brandybuck"}, |
||||||
|
{"Chica", "Baggins"}, |
||||||
|
{"Daddy", "Twofoot"}, |
||||||
|
{"Daisy", "Boffin"}, |
||||||
|
{"Diamond", "Took"}, |
||||||
|
{"Dinodas", "Brandybuck"}, |
||||||
|
{"Doderic", "Brandybuck"}, |
||||||
|
{"Dodinas", "Brandybuck"}, |
||||||
|
{"Donnamira", "Boffin"}, |
||||||
|
{"Dora", "Baggins"}, |
||||||
|
{"Drogo", "Baggins"}, |
||||||
|
{"Dudo", "Baggins"}, |
||||||
|
{"Eglantine", "Took"}, |
||||||
|
{"Elanor", "Fairbairn"}, |
||||||
|
{"Elfstan", "Fairbairn"}, |
||||||
|
{"Esmeralda", "Brandybuck"}, |
||||||
|
{"Estella", "Brandybuck"}, |
||||||
|
{"Everard", "Took"}, |
||||||
|
{"Falco", "Chubb-Baggins"}, |
||||||
|
{"Faramir", "Took"}, |
||||||
|
{"Farmer", "Maggot"}, |
||||||
|
{"Fastolph", "Bolger"}, |
||||||
|
{"Ferdibrand", "Took"}, |
||||||
|
{"Ferdinand", "Took"}, |
||||||
|
{"Ferumbras", "Took"}, |
||||||
|
{"Ferumbras", "Took"}, |
||||||
|
{"Filibert", "Bolger"}, |
||||||
|
{"Firiel", "Fairbairn"}, |
||||||
|
{"Flambard", "Took"}, |
||||||
|
{"Folco", "Boffin"}, |
||||||
|
{"Fortinbras", "Took"}, |
||||||
|
{"Fortinbras", "Took"}, |
||||||
|
{"Fosco", "Baggins"}, |
||||||
|
{"Fredegar", "Bolger"}, |
||||||
|
{"Frodo", "Baggins"}, |
||||||
|
{"Frodo", "Gardner"}, |
||||||
|
{"Gerontius", "Took"}, |
||||||
|
{"Gilly", "Baggins"}, |
||||||
|
{"Goldilocks", "Took"}, |
||||||
|
{"Gorbadoc", "Brandybuck"}, |
||||||
|
{"Gorbulas", "Brandybuck"}, |
||||||
|
{"Gorhendad", "Brandybuck"}, |
||||||
|
{"Gormadoc", "Brandybuck"}, |
||||||
|
{"Griffo", "Boffin"}, |
||||||
|
{"Halfast", "Gamgee"}, |
||||||
|
{"Halfred", "Gamgee"}, |
||||||
|
{"Halfred", "Greenhand"}, |
||||||
|
{"Hanna", "Brandybuck"}, |
||||||
|
{"Hamfast", "Gamgee"}, |
||||||
|
{"Hamfast", "Gardner"}, |
||||||
|
{"Hamson", "Gamgee"}, |
||||||
|
{"Harding", "Gardner"}, |
||||||
|
{"Hilda", "Brandybuck"}, |
||||||
|
{"Hildibrand", "Took"}, |
||||||
|
{"Hildifons", "Took"}, |
||||||
|
{"Hildigard", "Took"}, |
||||||
|
{"Hildigrim", "Took"}, |
||||||
|
{"Hob", "Gammidge"}, |
||||||
|
{"Hob", "Hayward"}, |
||||||
|
{"Hobson", "Gamgee"}, |
||||||
|
{"Holfast", "Gardner"}, |
||||||
|
{"Holman", "Cotton"}, |
||||||
|
{"Holman", "Greenhand"}, |
||||||
|
{"Hugo", "Boffin"}, |
||||||
|
{"Hugo", "Bracegirdle"}, |
||||||
|
{"Ilberic", "Brandybuck"}, |
||||||
|
{"Isembard", "Took"}, |
||||||
|
{"Isembold", "Took"}, |
||||||
|
{"Isengar", "Took"}, |
||||||
|
{"Isengrim", "Took"}, |
||||||
|
{"Isengrim", "Took"}, |
||||||
|
{"Isumbras", "Took"}, |
||||||
|
{"Isumbras", "Took"}, |
||||||
|
{"Jolly", "Cotton"}, |
||||||
|
{"Lalia", "Took"}, |
||||||
|
{"Largo", "Baggins"}, |
||||||
|
{"Laura", "Baggins"}, |
||||||
|
{"Lily", "Goodbody"}, |
||||||
|
{"Lily", "Cotton"}, |
||||||
|
{"Linda", "Proudfoot"}, |
||||||
|
{"Lobelia", "Sackville-Baggins"}, |
||||||
|
{"Longo", "Baggins"}, |
||||||
|
{"Lotho", "Sackville-Baggins"}, |
||||||
|
{"Madoc", "Brandybuck"}, |
||||||
|
{"Malva", "Brandybuck"}, |
||||||
|
{"Marigold", "Cotton"}, |
||||||
|
{"Marmadas", "Brandybuck"}, |
||||||
|
{"Marmadoc", "Brandybuck"}, |
||||||
|
{"Marroc", "Brandybuck"}, |
||||||
|
{"May", "Gamgee"}, |
||||||
|
{"Melilot", "Brandybuck"}, |
||||||
|
{"Menegilda", "Brandybuck"}, |
||||||
|
{"Mentha", "Brandybuck"}, |
||||||
|
{"Meriadoc", "Brandybuck"}, |
||||||
|
{"Merimac", "Brandybuck"}, |
||||||
|
{"Merimas", "Brandybuck"}, |
||||||
|
{"Merry", "Gardner"}, |
||||||
|
{"Milo", "Burrows"}, |
||||||
|
{"Mimosa", "Baggins"}, |
||||||
|
{"Minto", "Burrows"}, |
||||||
|
{"Mirabella", "Brandybuck"}, |
||||||
|
{"Moro", "Burrows"}, |
||||||
|
{"Mosco", "Burrows"}, |
||||||
|
{"Mungo", "Baggins"}, |
||||||
|
{"Myrtle", "Burrows"}, |
||||||
|
{"Odo", "Proudfoot"}, |
||||||
|
{"Odovacar", "Bolger"}, |
||||||
|
{"Olo", "Proudfoot"}, |
||||||
|
{"Orgulas", "Brandybuck"}, |
||||||
|
{"Otho", "Sackville-Baggins"}, |
||||||
|
{"Paladin", "Took"}, |
||||||
|
{"Pansy", "Bolger"}, |
||||||
|
{"Pearl", "Took"}, |
||||||
|
{"Peony", "Burrows"}, |
||||||
|
{"Peregrin", "Took"}, |
||||||
|
{"Pervinca", "Took"}, |
||||||
|
{"Pimpernel", "Took"}, |
||||||
|
{"Pippin", "Gardner"}, |
||||||
|
{"Polo", "Baggins"}, |
||||||
|
{"Ponto", "Baggins"}, |
||||||
|
{"Porto", "Baggins"}, |
||||||
|
{"Posco", "Baggins"}, |
||||||
|
{"Poppy", "Bolger"}, |
||||||
|
{"Primrose", "Gardner"}, |
||||||
|
{"Primula", "Baggins"}, |
||||||
|
{"Prisca", "Bolger"}, |
||||||
|
{"Reginard", "Took"}, |
||||||
|
{"Robin", "Smallburrow"}, |
||||||
|
{"Robin", "Gardner"}, |
||||||
|
{"Rorimac", "Brandybuck"}, |
||||||
|
{"Rosa", "Took"}, |
||||||
|
{"Rosamunda", "Bolger"}, |
||||||
|
{"Rose", "Gardner"}, |
||||||
|
{"Ruby", "Baggins"}, |
||||||
|
{"Ruby", "Gardner"}, |
||||||
|
{"Rudigar", "Bolger"}, |
||||||
|
{"Rufus", "Burrows"}, |
||||||
|
{"Sadoc", "Brandybuck"}, |
||||||
|
{"Salvia", "Bolger"}, |
||||||
|
{"Samwise", "Gamgee"}, |
||||||
|
{"Sancho", "Proudfoot"}, |
||||||
|
{"Saradas", "Brandybuck"}, |
||||||
|
{"Saradoc", "Brandybuck"}, |
||||||
|
{"Seredic", "Brandybuck"}, |
||||||
|
{"Sigismond", "Took"}, |
||||||
|
{"Smeagol", "Gollum"}, |
||||||
|
{"Tanta", "Baggins"}, |
||||||
|
{"Ted", "Sandyman"}, |
||||||
|
{"Tobold", "Hornblower"}, |
||||||
|
{"Togo", "Goodbody"}, |
||||||
|
{"Tolman", "Cotton"}, |
||||||
|
{"Tolman", "Gardner"}, |
||||||
|
{"Widow", "Rumble"}, |
||||||
|
{"Wilcome", "Cotton"}, |
||||||
|
{"Wilcome", "Cotton"}, |
||||||
|
{"Wilibald", "Bolger"}, |
||||||
|
{"Will", "Whitfoot"}, |
||||||
|
{"Wiseman", "Gamwich"}}; |
||||||
|
|
||||||
|
const char *dragons[] = {"Ancalagon", "Glaurung", "Scatha", |
||||||
|
"Smaug the Magnificent"}; |
||||||
|
|
||||||
|
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, |
||||||
|
const char *test_name, |
||||||
|
grpc_channel_args *client_args, |
||||||
|
grpc_channel_args *server_args) { |
||||||
|
grpc_end2end_test_fixture f; |
||||||
|
gpr_log(GPR_INFO, "%s/%s", test_name, config.name); |
||||||
|
f = config.create_fixture(client_args, server_args); |
||||||
|
config.init_client(&f, client_args); |
||||||
|
config.init_server(&f, server_args); |
||||||
|
return f; |
||||||
|
} |
||||||
|
|
||||||
|
static gpr_timespec n_seconds_time(int n) { |
||||||
|
return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); |
||||||
|
} |
||||||
|
|
||||||
|
static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); } |
||||||
|
|
||||||
|
static void drain_cq(grpc_completion_queue *cq) { |
||||||
|
grpc_event ev; |
||||||
|
do { |
||||||
|
ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL); |
||||||
|
} while (ev.type != GRPC_QUEUE_SHUTDOWN); |
||||||
|
} |
||||||
|
|
||||||
|
static void shutdown_server(grpc_end2end_test_fixture *f) { |
||||||
|
if (!f->server) return; |
||||||
|
grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000)); |
||||||
|
GPR_ASSERT(grpc_completion_queue_pluck( |
||||||
|
f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL) |
||||||
|
.type == GRPC_OP_COMPLETE); |
||||||
|
grpc_server_destroy(f->server); |
||||||
|
f->server = NULL; |
||||||
|
} |
||||||
|
|
||||||
|
static void shutdown_client(grpc_end2end_test_fixture *f) { |
||||||
|
if (!f->client) return; |
||||||
|
grpc_channel_destroy(f->client); |
||||||
|
f->client = NULL; |
||||||
|
} |
||||||
|
|
||||||
|
static void end_test(grpc_end2end_test_fixture *f) { |
||||||
|
shutdown_server(f); |
||||||
|
shutdown_client(f); |
||||||
|
|
||||||
|
grpc_completion_queue_shutdown(f->cq); |
||||||
|
drain_cq(f->cq); |
||||||
|
grpc_completion_queue_destroy(f->cq); |
||||||
|
} |
||||||
|
|
||||||
|
static void simple_request_body(grpc_end2end_test_fixture f, size_t index) { |
||||||
|
grpc_call *c; |
||||||
|
grpc_call *s; |
||||||
|
gpr_timespec deadline = five_seconds_time(); |
||||||
|
cq_verifier *cqv = cq_verifier_create(f.cq); |
||||||
|
grpc_op ops[6]; |
||||||
|
grpc_op *op; |
||||||
|
grpc_metadata_array initial_metadata_recv; |
||||||
|
grpc_metadata_array trailing_metadata_recv; |
||||||
|
grpc_metadata_array request_metadata_recv; |
||||||
|
grpc_call_details call_details; |
||||||
|
grpc_status_code status; |
||||||
|
grpc_call_error error; |
||||||
|
grpc_metadata extra_metadata[3]; |
||||||
|
char *details = NULL; |
||||||
|
size_t details_capacity = 0; |
||||||
|
int was_cancelled = 2; |
||||||
|
|
||||||
|
memset(extra_metadata, 0, sizeof(extra_metadata)); |
||||||
|
extra_metadata[0].key = "hobbit-first-name"; |
||||||
|
extra_metadata[0].value = hobbits[index % GPR_ARRAY_SIZE(hobbits)][0]; |
||||||
|
extra_metadata[0].value_length = strlen(extra_metadata[0].value); |
||||||
|
extra_metadata[1].key = "hobbit-second-name"; |
||||||
|
extra_metadata[1].value = hobbits[index % GPR_ARRAY_SIZE(hobbits)][1]; |
||||||
|
extra_metadata[1].value_length = strlen(extra_metadata[1].value); |
||||||
|
extra_metadata[2].key = "dragon"; |
||||||
|
extra_metadata[2].value = dragons[index % GPR_ARRAY_SIZE(dragons)]; |
||||||
|
extra_metadata[2].value_length = strlen(extra_metadata[2].value); |
||||||
|
|
||||||
|
c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, |
||||||
|
"/foo", "foo.test.google.fr:1234", deadline, |
||||||
|
NULL); |
||||||
|
GPR_ASSERT(c); |
||||||
|
|
||||||
|
grpc_metadata_array_init(&initial_metadata_recv); |
||||||
|
grpc_metadata_array_init(&trailing_metadata_recv); |
||||||
|
grpc_metadata_array_init(&request_metadata_recv); |
||||||
|
grpc_call_details_init(&call_details); |
||||||
|
|
||||||
|
op = ops; |
||||||
|
op->op = GRPC_OP_SEND_INITIAL_METADATA; |
||||||
|
op->data.send_initial_metadata.count = GPR_ARRAY_SIZE(extra_metadata); |
||||||
|
op->data.send_initial_metadata.metadata = extra_metadata; |
||||||
|
op->flags = 0; |
||||||
|
op->reserved = NULL; |
||||||
|
op++; |
||||||
|
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; |
||||||
|
op->flags = 0; |
||||||
|
op->reserved = NULL; |
||||||
|
op++; |
||||||
|
op->op = GRPC_OP_RECV_INITIAL_METADATA; |
||||||
|
op->data.recv_initial_metadata = &initial_metadata_recv; |
||||||
|
op->flags = 0; |
||||||
|
op->reserved = NULL; |
||||||
|
op++; |
||||||
|
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; |
||||||
|
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; |
||||||
|
op->data.recv_status_on_client.status = &status; |
||||||
|
op->data.recv_status_on_client.status_details = &details; |
||||||
|
op->data.recv_status_on_client.status_details_capacity = &details_capacity; |
||||||
|
op->flags = 0; |
||||||
|
op->reserved = NULL; |
||||||
|
op++; |
||||||
|
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); |
||||||
|
GPR_ASSERT(GRPC_CALL_OK == error); |
||||||
|
|
||||||
|
error = |
||||||
|
grpc_server_request_call(f.server, &s, &call_details, |
||||||
|
&request_metadata_recv, f.cq, f.cq, tag(101)); |
||||||
|
GPR_ASSERT(GRPC_CALL_OK == error); |
||||||
|
cq_expect_completion(cqv, tag(101), 1); |
||||||
|
cq_verify(cqv); |
||||||
|
|
||||||
|
op = ops; |
||||||
|
op->op = GRPC_OP_SEND_INITIAL_METADATA; |
||||||
|
op->data.send_initial_metadata.count = 0; |
||||||
|
op->flags = 0; |
||||||
|
op->reserved = NULL; |
||||||
|
op++; |
||||||
|
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; |
||||||
|
op->data.send_status_from_server.trailing_metadata_count = 0; |
||||||
|
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; |
||||||
|
op->data.send_status_from_server.status_details = "xyz"; |
||||||
|
op->flags = 0; |
||||||
|
op->reserved = NULL; |
||||||
|
op++; |
||||||
|
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; |
||||||
|
op->data.recv_close_on_server.cancelled = &was_cancelled; |
||||||
|
op->flags = 0; |
||||||
|
op->reserved = NULL; |
||||||
|
op++; |
||||||
|
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); |
||||||
|
GPR_ASSERT(GRPC_CALL_OK == error); |
||||||
|
|
||||||
|
cq_expect_completion(cqv, tag(102), 1); |
||||||
|
cq_expect_completion(cqv, tag(1), 1); |
||||||
|
cq_verify(cqv); |
||||||
|
|
||||||
|
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); |
||||||
|
GPR_ASSERT(0 == strcmp(details, "xyz")); |
||||||
|
GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); |
||||||
|
GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr:1234")); |
||||||
|
GPR_ASSERT(was_cancelled == 1); |
||||||
|
|
||||||
|
gpr_free(details); |
||||||
|
grpc_metadata_array_destroy(&initial_metadata_recv); |
||||||
|
grpc_metadata_array_destroy(&trailing_metadata_recv); |
||||||
|
grpc_metadata_array_destroy(&request_metadata_recv); |
||||||
|
grpc_call_details_destroy(&call_details); |
||||||
|
|
||||||
|
grpc_call_destroy(c); |
||||||
|
grpc_call_destroy(s); |
||||||
|
|
||||||
|
cq_verifier_destroy(cqv); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_size(grpc_end2end_test_config config, int encode_size, |
||||||
|
int decode_size) { |
||||||
|
size_t i; |
||||||
|
grpc_end2end_test_fixture f; |
||||||
|
grpc_arg server_arg; |
||||||
|
grpc_channel_args server_args; |
||||||
|
grpc_arg client_arg; |
||||||
|
grpc_channel_args client_args; |
||||||
|
char *name; |
||||||
|
|
||||||
|
server_arg.type = GRPC_ARG_INTEGER; |
||||||
|
server_arg.key = GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER; |
||||||
|
server_arg.value.integer = decode_size; |
||||||
|
server_args.num_args = 1; |
||||||
|
server_args.args = &server_arg; |
||||||
|
|
||||||
|
client_arg.type = GRPC_ARG_INTEGER; |
||||||
|
client_arg.key = GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER; |
||||||
|
client_arg.value.integer = encode_size; |
||||||
|
client_args.num_args = 1; |
||||||
|
client_args.args = &client_arg; |
||||||
|
|
||||||
|
gpr_asprintf(&name, "test_size:e=%d:d=%d", encode_size, decode_size); |
||||||
|
f = begin_test(config, name, encode_size != 4096 ? &client_args : NULL, |
||||||
|
decode_size != 4096 ? &server_args : NULL); |
||||||
|
for (i = 0; i < 4 * GPR_ARRAY_SIZE(hobbits); i++) { |
||||||
|
simple_request_body(f, i); |
||||||
|
} |
||||||
|
end_test(&f); |
||||||
|
config.tear_down_data(&f); |
||||||
|
gpr_free(name); |
||||||
|
} |
||||||
|
|
||||||
|
void grpc_end2end_tests(grpc_end2end_test_config config) { |
||||||
|
static const int interesting_sizes[] = {4096, 0, 100, |
||||||
|
1000, 32768, 4 * 1024 * 1024}; |
||||||
|
size_t i, j; |
||||||
|
|
||||||
|
for (i = 0; i < GPR_ARRAY_SIZE(interesting_sizes); i++) { |
||||||
|
for (j = 0; j < GPR_ARRAY_SIZE(interesting_sizes); j++) { |
||||||
|
test_size(config, interesting_sizes[i], interesting_sizes[j]); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,103 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright 2015, Google Inc. |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* * Redistributions in binary form must reproduce the above |
||||||
|
* copyright notice, this list of conditions and the following disclaimer |
||||||
|
* in the documentation and/or other materials provided with the |
||||||
|
* distribution. |
||||||
|
* * Neither the name of Google Inc. nor the names of its |
||||||
|
* contributors may be used to endorse or promote products derived from |
||||||
|
* this software without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*is % allowed in string |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <memory> |
||||||
|
#include <string> |
||||||
|
|
||||||
|
#include <gflags/gflags.h> |
||||||
|
#include <grpc++/grpc++.h> |
||||||
|
|
||||||
|
#include "test/cpp/util/metrics_server.h" |
||||||
|
#include "test/cpp/util/test_config.h" |
||||||
|
#include "test/proto/metrics.grpc.pb.h" |
||||||
|
#include "test/proto/metrics.pb.h" |
||||||
|
|
||||||
|
DEFINE_string(metrics_server_address, "", |
||||||
|
"The metrics server addresses in the fomrat <hostname>:<port>"); |
||||||
|
|
||||||
|
using grpc::testing::EmptyMessage; |
||||||
|
using grpc::testing::GaugeResponse; |
||||||
|
using grpc::testing::MetricsService; |
||||||
|
using grpc::testing::MetricsServiceImpl; |
||||||
|
|
||||||
|
void PrintMetrics(grpc::string& server_address) { |
||||||
|
gpr_log(GPR_INFO, "creating a channel to %s", server_address.c_str()); |
||||||
|
std::shared_ptr<grpc::Channel> channel( |
||||||
|
grpc::CreateChannel(server_address, grpc::InsecureChannelCredentials())); |
||||||
|
|
||||||
|
std::unique_ptr<MetricsService::Stub> stub(MetricsService::NewStub(channel)); |
||||||
|
|
||||||
|
grpc::ClientContext context; |
||||||
|
EmptyMessage message; |
||||||
|
|
||||||
|
std::unique_ptr<grpc::ClientReader<GaugeResponse>> reader( |
||||||
|
stub->GetAllGauges(&context, message)); |
||||||
|
|
||||||
|
GaugeResponse gauge_response; |
||||||
|
long overall_qps = 0; |
||||||
|
int idx = 0; |
||||||
|
while (reader->Read(&gauge_response)) { |
||||||
|
if (gauge_response.value_case() == GaugeResponse::kLongValue) { |
||||||
|
gpr_log(GPR_INFO, "Gauge: %d (%s: %ld)", ++idx, |
||||||
|
gauge_response.name().c_str(), gauge_response.long_value()); |
||||||
|
overall_qps += gauge_response.long_value(); |
||||||
|
} else { |
||||||
|
gpr_log(GPR_INFO, "Gauge %s is not a long value", |
||||||
|
gauge_response.name().c_str()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
gpr_log(GPR_INFO, "OVERALL: %ld", overall_qps); |
||||||
|
|
||||||
|
const grpc::Status status = reader->Finish(); |
||||||
|
if (!status.ok()) { |
||||||
|
gpr_log(GPR_ERROR, "Error in getting metrics from the client"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
int main(int argc, char** argv) { |
||||||
|
grpc::testing::InitTest(&argc, &argv, true); |
||||||
|
|
||||||
|
// Make sure server_addresses flag is not empty
|
||||||
|
if (FLAGS_metrics_server_address.empty()) { |
||||||
|
gpr_log( |
||||||
|
GPR_ERROR, |
||||||
|
"Cannot connect to the Metrics server. Please pass the address of the" |
||||||
|
"metrics server to connect to via the 'metrics_server_address' flag"); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
PrintMetrics(FLAGS_metrics_server_address); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
@ -0,0 +1,119 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright 2015, Google Inc. |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* * Redistributions in binary form must reproduce the above |
||||||
|
* copyright notice, this list of conditions and the following disclaimer |
||||||
|
* in the documentation and/or other materials provided with the |
||||||
|
* distribution. |
||||||
|
* * Neither the name of Google Inc. nor the names of its |
||||||
|
* contributors may be used to endorse or promote products derived from |
||||||
|
* this software without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*is % allowed in string |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "test/cpp/util/metrics_server.h" |
||||||
|
|
||||||
|
#include <grpc++/server_builder.h> |
||||||
|
|
||||||
|
#include "test/proto/metrics.grpc.pb.h" |
||||||
|
#include "test/proto/metrics.pb.h" |
||||||
|
|
||||||
|
namespace grpc { |
||||||
|
namespace testing { |
||||||
|
|
||||||
|
Gauge::Gauge(long initial_val) : val_(initial_val) {} |
||||||
|
|
||||||
|
void Gauge::Set(long new_val) { |
||||||
|
std::lock_guard<std::mutex> lock(val_mu_); |
||||||
|
val_ = new_val; |
||||||
|
} |
||||||
|
|
||||||
|
long Gauge::Get() { |
||||||
|
std::lock_guard<std::mutex> lock(val_mu_); |
||||||
|
return val_; |
||||||
|
} |
||||||
|
|
||||||
|
grpc::Status MetricsServiceImpl::GetAllGauges( |
||||||
|
ServerContext* context, const EmptyMessage* request, |
||||||
|
ServerWriter<GaugeResponse>* writer) { |
||||||
|
gpr_log(GPR_INFO, "GetAllGauges called"); |
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(mu_); |
||||||
|
for (auto it = gauges_.begin(); it != gauges_.end(); it++) { |
||||||
|
GaugeResponse resp; |
||||||
|
resp.set_name(it->first); // Gauge name
|
||||||
|
resp.set_long_value(it->second->Get()); // Gauge value
|
||||||
|
writer->Write(resp); |
||||||
|
} |
||||||
|
|
||||||
|
return Status::OK; |
||||||
|
} |
||||||
|
|
||||||
|
grpc::Status MetricsServiceImpl::GetGauge(ServerContext* context, |
||||||
|
const GaugeRequest* request, |
||||||
|
GaugeResponse* response) { |
||||||
|
std::lock_guard<std::mutex> lock(mu_); |
||||||
|
|
||||||
|
const auto it = gauges_.find(request->name()); |
||||||
|
if (it != gauges_.end()) { |
||||||
|
response->set_name(it->first); |
||||||
|
response->set_long_value(it->second->Get()); |
||||||
|
} |
||||||
|
|
||||||
|
return Status::OK; |
||||||
|
} |
||||||
|
|
||||||
|
std::shared_ptr<Gauge> MetricsServiceImpl::CreateGauge(const grpc::string& name, |
||||||
|
bool* already_present) { |
||||||
|
std::lock_guard<std::mutex> lock(mu_); |
||||||
|
|
||||||
|
std::shared_ptr<Gauge> gauge(new Gauge(0)); |
||||||
|
const auto p = gauges_.emplace(name, gauge); |
||||||
|
|
||||||
|
// p.first is an iterator pointing to <name, shared_ptr<Gauge>> pair. p.second
|
||||||
|
// is a boolean which is set to 'true' if the Gauge is inserted in the guages_
|
||||||
|
// map and 'false' if it is already present in the map
|
||||||
|
*already_present = !p.second; |
||||||
|
return p.first->second; |
||||||
|
} |
||||||
|
|
||||||
|
// Starts the metrics server and returns the grpc::Server instance. Call Wait()
|
||||||
|
// on the returned server instance.
|
||||||
|
std::unique_ptr<grpc::Server> MetricsServiceImpl::StartServer(int port) { |
||||||
|
gpr_log(GPR_INFO, "Building metrics server.."); |
||||||
|
|
||||||
|
const grpc::string address = "0.0.0.0:" + std::to_string(port); |
||||||
|
|
||||||
|
ServerBuilder builder; |
||||||
|
builder.AddListeningPort(address, grpc::InsecureServerCredentials()); |
||||||
|
builder.RegisterService(this); |
||||||
|
|
||||||
|
std::unique_ptr<grpc::Server> server(builder.BuildAndStart()); |
||||||
|
gpr_log(GPR_INFO, "Metrics server %s started. Ready to receive requests..", |
||||||
|
address.c_str()); |
||||||
|
|
||||||
|
return server; |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
} // namespace grpc
|
@ -0,0 +1,100 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright 2015, Google Inc. |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* * Redistributions in binary form must reproduce the above |
||||||
|
* copyright notice, this list of conditions and the following disclaimer |
||||||
|
* in the documentation and/or other materials provided with the |
||||||
|
* distribution. |
||||||
|
* * Neither the name of Google Inc. nor the names of its |
||||||
|
* contributors may be used to endorse or promote products derived from |
||||||
|
* this software without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*is % allowed in string |
||||||
|
*/ |
||||||
|
#ifndef GRPC_TEST_CPP_METRICS_SERVER_H |
||||||
|
#define GRPC_TEST_CPP_METRICS_SERVER_H |
||||||
|
|
||||||
|
#include <map> |
||||||
|
#include <mutex> |
||||||
|
|
||||||
|
#include "test/proto/metrics.grpc.pb.h" |
||||||
|
#include "test/proto/metrics.pb.h" |
||||||
|
|
||||||
|
/*
|
||||||
|
* This implements a Metrics server defined in test/proto/metrics.proto. Any |
||||||
|
* test service can use this to export Metrics (TODO (sreek): Only Gauges for |
||||||
|
* now). |
||||||
|
* |
||||||
|
* Example: |
||||||
|
* MetricsServiceImpl metricsImpl; |
||||||
|
* .. |
||||||
|
* // Create Gauge(s). Note: Gauges can be created even after calling
|
||||||
|
* // 'StartServer'.
|
||||||
|
* Gauge gauge1 = metricsImpl.CreateGauge("foo",is_present); |
||||||
|
* // gauge1 can now be used anywhere in the program to set values.
|
||||||
|
* ... |
||||||
|
* // Create the metrics server
|
||||||
|
* std::unique_ptr<grpc::Server> server = metricsImpl.StartServer(port); |
||||||
|
* server->Wait(); // Note: This is blocking.
|
||||||
|
*/ |
||||||
|
namespace grpc { |
||||||
|
namespace testing { |
||||||
|
|
||||||
|
// TODO(sreek): Add support for other types of Gauges like Double, String in
|
||||||
|
// future
|
||||||
|
class Gauge { |
||||||
|
public: |
||||||
|
Gauge(long initial_val); |
||||||
|
void Set(long new_val); |
||||||
|
long Get(); |
||||||
|
|
||||||
|
private: |
||||||
|
long val_; |
||||||
|
std::mutex val_mu_; |
||||||
|
}; |
||||||
|
|
||||||
|
class MetricsServiceImpl GRPC_FINAL : public MetricsService::Service { |
||||||
|
public: |
||||||
|
grpc::Status GetAllGauges(ServerContext* context, const EmptyMessage* request, |
||||||
|
ServerWriter<GaugeResponse>* writer) GRPC_OVERRIDE; |
||||||
|
|
||||||
|
grpc::Status GetGauge(ServerContext* context, const GaugeRequest* request, |
||||||
|
GaugeResponse* response) GRPC_OVERRIDE; |
||||||
|
|
||||||
|
// Create a Gauge with name 'name'. is_present is set to true if the Gauge
|
||||||
|
// is already present in the map.
|
||||||
|
// NOTE: CreateGauge can be called anytime (i.e before or after calling
|
||||||
|
// StartServer).
|
||||||
|
std::shared_ptr<Gauge> CreateGauge(const grpc::string& name, |
||||||
|
bool* already_present); |
||||||
|
|
||||||
|
std::unique_ptr<grpc::Server> StartServer(int port); |
||||||
|
|
||||||
|
private: |
||||||
|
std::map<string, std::shared_ptr<Gauge>> gauges_; |
||||||
|
std::mutex mu_; |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
} // namespace grpc
|
||||||
|
|
||||||
|
#endif // GRPC_TEST_CPP_METRICS_SERVER_H
|
@ -0,0 +1,56 @@ |
|||||||
|
|
||||||
|
// Copyright 2015, Google Inc. |
||||||
|
// All rights reserved. |
||||||
|
// |
||||||
|
// Redistribution and use in source and binary forms, with or without |
||||||
|
// modification, are permitted provided that the following conditions are |
||||||
|
// met: |
||||||
|
// |
||||||
|
// * Redistributions of source code must retain the above copyright |
||||||
|
// notice, this list of conditions and the following disclaimer. |
||||||
|
// * Redistributions in binary form must reproduce the above |
||||||
|
// copyright notice, this list of conditions and the following disclaimer |
||||||
|
// in the documentation and/or other materials provided with the |
||||||
|
// distribution. |
||||||
|
// * Neither the name of Google Inc. nor the names of its |
||||||
|
// contributors may be used to endorse or promote products derived from |
||||||
|
// this software without specific prior written permission. |
||||||
|
// |
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
// An integration test service that covers all the method signature permutations |
||||||
|
// of unary/streaming requests/responses. |
||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
package grpc.testing; |
||||||
|
|
||||||
|
message GaugeResponse { |
||||||
|
string name = 1; |
||||||
|
oneof value { |
||||||
|
int64 long_value = 2; |
||||||
|
double double_vale = 3; |
||||||
|
string string_value = 4; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
message GaugeRequest { |
||||||
|
string name = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message EmptyMessage { |
||||||
|
} |
||||||
|
|
||||||
|
service MetricsService { |
||||||
|
rpc GetAllGauges(EmptyMessage) returns (stream GaugeResponse); |
||||||
|
rpc GetGauge(GaugeRequest) returns (GaugeResponse); |
||||||
|
} |
@ -0,0 +1,216 @@ |
|||||||
|
#!/usr/bin/env python2.7 |
||||||
|
# Copyright 2015, Google Inc. |
||||||
|
# All rights reserved. |
||||||
|
# |
||||||
|
# Redistribution and use in source and binary forms, with or without |
||||||
|
# modification, are permitted provided that the following conditions are |
||||||
|
# met: |
||||||
|
# |
||||||
|
# * Redistributions of source code must retain the above copyright |
||||||
|
# notice, this list of conditions and the following disclaimer. |
||||||
|
# * Redistributions in binary form must reproduce the above |
||||||
|
# copyright notice, this list of conditions and the following disclaimer |
||||||
|
# in the documentation and/or other materials provided with the |
||||||
|
# distribution. |
||||||
|
# * Neither the name of Google Inc. nor the names of its |
||||||
|
# contributors may be used to endorse or promote products derived from |
||||||
|
# this software without specific prior written permission. |
||||||
|
# |
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
|
||||||
|
import requests |
||||||
|
import json |
||||||
|
|
||||||
|
_REQUEST_TIMEOUT_SECS = 10 |
||||||
|
|
||||||
|
def _make_pod_config(pod_name, image_name, container_port_list, cmd_list, |
||||||
|
arg_list): |
||||||
|
"""Creates a string containing the Pod defintion as required by the Kubernetes API""" |
||||||
|
body = { |
||||||
|
'kind': 'Pod', |
||||||
|
'apiVersion': 'v1', |
||||||
|
'metadata': { |
||||||
|
'name': pod_name, |
||||||
|
'labels': {'name': pod_name} |
||||||
|
}, |
||||||
|
'spec': { |
||||||
|
'containers': [ |
||||||
|
{ |
||||||
|
'name': pod_name, |
||||||
|
'image': image_name, |
||||||
|
'ports': [] |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
} |
||||||
|
# Populate the 'ports' list |
||||||
|
for port in container_port_list: |
||||||
|
port_entry = {'containerPort': port, 'protocol': 'TCP'} |
||||||
|
body['spec']['containers'][0]['ports'].append(port_entry) |
||||||
|
|
||||||
|
# Add the 'Command' and 'Args' attributes if they are passed. |
||||||
|
# Note: |
||||||
|
# - 'Command' overrides the ENTRYPOINT in the Docker Image |
||||||
|
# - 'Args' override the COMMAND in Docker image (yes, it is confusing!) |
||||||
|
if len(cmd_list) > 0: |
||||||
|
body['spec']['containers'][0]['command'] = cmd_list |
||||||
|
if len(arg_list) > 0: |
||||||
|
body['spec']['containers'][0]['args'] = arg_list |
||||||
|
return json.dumps(body) |
||||||
|
|
||||||
|
|
||||||
|
def _make_service_config(service_name, pod_name, service_port_list, |
||||||
|
container_port_list, is_headless): |
||||||
|
"""Creates a string containing the Service definition as required by the Kubernetes API. |
||||||
|
|
||||||
|
NOTE: |
||||||
|
This creates either a Headless Service or 'LoadBalancer' service depending on |
||||||
|
the is_headless parameter. For Headless services, there is no 'type' attribute |
||||||
|
and the 'clusterIP' attribute is set to 'None'. Also, if the service is |
||||||
|
Headless, Kubernetes creates DNS entries for Pods - i.e creates DNS A-records |
||||||
|
mapping the service's name to the Pods' IPs |
||||||
|
""" |
||||||
|
if len(container_port_list) != len(service_port_list): |
||||||
|
print( |
||||||
|
'ERROR: container_port_list and service_port_list must be of same size') |
||||||
|
return '' |
||||||
|
body = { |
||||||
|
'kind': 'Service', |
||||||
|
'apiVersion': 'v1', |
||||||
|
'metadata': { |
||||||
|
'name': service_name, |
||||||
|
'labels': { |
||||||
|
'name': service_name |
||||||
|
} |
||||||
|
}, |
||||||
|
'spec': { |
||||||
|
'ports': [], |
||||||
|
'selector': { |
||||||
|
'name': pod_name |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
# Populate the 'ports' list in the 'spec' section. This maps service ports |
||||||
|
# (port numbers that are exposed by Kubernetes) to container ports (i.e port |
||||||
|
# numbers that are exposed by your Docker image) |
||||||
|
for idx in range(len(container_port_list)): |
||||||
|
port_entry = { |
||||||
|
'port': service_port_list[idx], |
||||||
|
'targetPort': container_port_list[idx], |
||||||
|
'protocol': 'TCP' |
||||||
|
} |
||||||
|
body['spec']['ports'].append(port_entry) |
||||||
|
|
||||||
|
# Make this either a LoadBalancer service or a headless service depending on |
||||||
|
# the is_headless parameter |
||||||
|
if is_headless: |
||||||
|
body['spec']['clusterIP'] = 'None' |
||||||
|
else: |
||||||
|
body['spec']['type'] = 'LoadBalancer' |
||||||
|
return json.dumps(body) |
||||||
|
|
||||||
|
|
||||||
|
def _print_connection_error(msg): |
||||||
|
print('ERROR: Connection failed. Did you remember to run Kubenetes proxy on ' |
||||||
|
'localhost (i.e kubectl proxy --port=<proxy_port>) ?. Error: %s' % msg) |
||||||
|
|
||||||
|
def _do_post(post_url, api_name, request_body): |
||||||
|
"""Helper to do HTTP POST. |
||||||
|
|
||||||
|
Note: |
||||||
|
1) On success, Kubernetes returns a success code of 201(CREATED) not 200(OK) |
||||||
|
2) A response code of 509(CONFLICT) is interpreted as a success code (since |
||||||
|
the error is most likely due to the resource already existing). This makes |
||||||
|
_do_post() idempotent which is semantically desirable. |
||||||
|
""" |
||||||
|
is_success = True |
||||||
|
try: |
||||||
|
r = requests.post(post_url, data=request_body, timeout=_REQUEST_TIMEOUT_SECS) |
||||||
|
if r.status_code == requests.codes.conflict: |
||||||
|
print('WARN: Looks like the resource already exists. Api: %s, url: %s' % |
||||||
|
(api_name, post_url)) |
||||||
|
elif r.status_code != requests.codes.created: |
||||||
|
print('ERROR: %s API returned error. HTTP response: (%d) %s' % |
||||||
|
(api_name, r.status_code, r.text)) |
||||||
|
is_success = False |
||||||
|
except(requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e: |
||||||
|
is_success = False |
||||||
|
_print_connection_error(str(e)) |
||||||
|
return is_success |
||||||
|
|
||||||
|
|
||||||
|
def _do_delete(del_url, api_name): |
||||||
|
"""Helper to do HTTP DELETE. |
||||||
|
|
||||||
|
Note: A response code of 404(NOT_FOUND) is treated as success to keep |
||||||
|
_do_delete() idempotent. |
||||||
|
""" |
||||||
|
is_success = True |
||||||
|
try: |
||||||
|
r = requests.delete(del_url, timeout=_REQUEST_TIMEOUT_SECS) |
||||||
|
if r.status_code == requests.codes.not_found: |
||||||
|
print('WARN: The resource does not exist. Api: %s, url: %s' % |
||||||
|
(api_name, del_url)) |
||||||
|
elif r.status_code != requests.codes.ok: |
||||||
|
print('ERROR: %s API returned error. HTTP response: %s' % |
||||||
|
(api_name, r.text)) |
||||||
|
is_success = False |
||||||
|
except(requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e: |
||||||
|
is_success = False |
||||||
|
_print_connection_error(str(e)) |
||||||
|
return is_success |
||||||
|
|
||||||
|
|
||||||
|
def create_service(kube_host, kube_port, namespace, service_name, pod_name, |
||||||
|
service_port_list, container_port_list, is_headless): |
||||||
|
"""Creates either a Headless Service or a LoadBalancer Service depending |
||||||
|
on the is_headless parameter. |
||||||
|
""" |
||||||
|
post_url = 'http://%s:%d/api/v1/namespaces/%s/services' % ( |
||||||
|
kube_host, kube_port, namespace) |
||||||
|
request_body = _make_service_config(service_name, pod_name, service_port_list, |
||||||
|
container_port_list, is_headless) |
||||||
|
return _do_post(post_url, 'Create Service', request_body) |
||||||
|
|
||||||
|
|
||||||
|
def create_pod(kube_host, kube_port, namespace, pod_name, image_name, |
||||||
|
container_port_list, cmd_list, arg_list): |
||||||
|
"""Creates a Kubernetes Pod. |
||||||
|
|
||||||
|
Note that it is generally NOT considered a good practice to directly create |
||||||
|
Pods. Typically, the recommendation is to create 'Controllers' to create and |
||||||
|
manage Pods' lifecycle. Currently Kubernetes only supports 'Replication |
||||||
|
Controller' which creates a configurable number of 'identical Replicas' of |
||||||
|
Pods and automatically restarts any Pods in case of failures (for eg: Machine |
||||||
|
failures in Kubernetes). This makes it less flexible for our test use cases |
||||||
|
where we might want slightly different set of args to each Pod. Hence we |
||||||
|
directly create Pods and not care much about Kubernetes failures since those |
||||||
|
are very rare. |
||||||
|
""" |
||||||
|
post_url = 'http://%s:%d/api/v1/namespaces/%s/pods' % (kube_host, kube_port, |
||||||
|
namespace) |
||||||
|
request_body = _make_pod_config(pod_name, image_name, container_port_list, |
||||||
|
cmd_list, arg_list) |
||||||
|
return _do_post(post_url, 'Create Pod', request_body) |
||||||
|
|
||||||
|
|
||||||
|
def delete_service(kube_host, kube_port, namespace, service_name): |
||||||
|
del_url = 'http://%s:%d/api/v1/namespaces/%s/services/%s' % ( |
||||||
|
kube_host, kube_port, namespace, service_name) |
||||||
|
return _do_delete(del_url, 'Delete Service') |
||||||
|
|
||||||
|
|
||||||
|
def delete_pod(kube_host, kube_port, namespace, pod_name): |
||||||
|
del_url = 'http://%s:%d/api/v1/namespaces/%s/pods/%s' % (kube_host, kube_port, |
||||||
|
namespace, pod_name) |
||||||
|
return _do_delete(del_url, 'Delete Pod') |
@ -0,0 +1,72 @@ |
|||||||
|
package http2interop |
||||||
|
|
||||||
|
import ( |
||||||
|
"encoding/binary" |
||||||
|
"fmt" |
||||||
|
"io" |
||||||
|
) |
||||||
|
|
||||||
|
type GoAwayFrame struct { |
||||||
|
Header FrameHeader |
||||||
|
Reserved |
||||||
|
StreamID |
||||||
|
// TODO(carl-mastrangelo): make an enum out of this.
|
||||||
|
Code uint32 |
||||||
|
Data []byte |
||||||
|
} |
||||||
|
|
||||||
|
func (f *GoAwayFrame) GetHeader() *FrameHeader { |
||||||
|
return &f.Header |
||||||
|
} |
||||||
|
|
||||||
|
func (f *GoAwayFrame) ParsePayload(r io.Reader) error { |
||||||
|
raw := make([]byte, f.Header.Length) |
||||||
|
if _, err := io.ReadFull(r, raw); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
return f.UnmarshalPayload(raw) |
||||||
|
} |
||||||
|
|
||||||
|
func (f *GoAwayFrame) UnmarshalPayload(raw []byte) error { |
||||||
|
if f.Header.Length != len(raw) { |
||||||
|
return fmt.Errorf("Invalid Payload length %d != %d", f.Header.Length, len(raw)) |
||||||
|
} |
||||||
|
if f.Header.Length < 8 { |
||||||
|
return fmt.Errorf("Invalid Payload length %d", f.Header.Length) |
||||||
|
} |
||||||
|
*f = GoAwayFrame{ |
||||||
|
Reserved: Reserved(raw[0]>>7 == 1), |
||||||
|
StreamID: StreamID(binary.BigEndian.Uint32(raw[0:4]) & 0x7fffffff), |
||||||
|
Code: binary.BigEndian.Uint32(raw[4:8]), |
||||||
|
Data: []byte(string(raw[8:])), |
||||||
|
} |
||||||
|
|
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
func (f *GoAwayFrame) MarshalPayload() ([]byte, error) { |
||||||
|
raw := make([]byte, 8, 8+len(f.Data)) |
||||||
|
binary.BigEndian.PutUint32(raw[:4], uint32(f.StreamID)) |
||||||
|
binary.BigEndian.PutUint32(raw[4:8], f.Code) |
||||||
|
raw = append(raw, f.Data...) |
||||||
|
|
||||||
|
return raw, nil |
||||||
|
} |
||||||
|
|
||||||
|
func (f *GoAwayFrame) MarshalBinary() ([]byte, error) { |
||||||
|
payload, err := f.MarshalPayload() |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
f.Header.Length = len(payload) |
||||||
|
f.Header.Type = GoAwayFrameType |
||||||
|
header, err := f.Header.MarshalBinary() |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
header = append(header, payload...) |
||||||
|
|
||||||
|
return header, nil |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue