blob: e318ee44f4f32b402953d8c43f71fcc217df7a6d [file] [log] [blame]
Jan Tattermuschc75c57c2015-08-07 22:07:40 -07001#region Copyright notice and license
2
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003// Copyright 2015 gRPC authors.
Jan Tattermuschc75c57c2015-08-07 22:07:40 -07004//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
Jan Tattermuschc75c57c2015-08-07 22:07:40 -07008//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009// http://www.apache.org/licenses/LICENSE-2.0
Jan Tattermuschc75c57c2015-08-07 22:07:40 -070010//
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
Jan Tattermuschc75c57c2015-08-07 22:07:40 -070016
17#endregion
18
19using System;
Jan Tattermusch4c25efa2015-08-21 16:07:57 -070020using System.Collections.Generic;
Jan Tattermuschc75c57c2015-08-07 22:07:40 -070021using System.Diagnostics;
22using System.Linq;
23using System.Threading;
24using System.Threading.Tasks;
Jan Tattermusch4c25efa2015-08-21 16:07:57 -070025
Jan Tattermuschc75c57c2015-08-07 22:07:40 -070026using Grpc.Core;
27using Grpc.Core.Internal;
28using Grpc.Core.Utils;
Jan Tattermusch4c25efa2015-08-21 16:07:57 -070029
Jan Tattermuschc75c57c2015-08-07 22:07:40 -070030using NUnit.Framework;
31
32namespace Grpc.Core.Tests
33{
34 /// <summary>
35 /// Tests for response headers support.
36 /// </summary>
37 public class ResponseHeadersTest
38 {
39 MockServiceHelper helper;
40 Server server;
41 Channel channel;
42
43 Metadata headers;
44
45 [SetUp]
46 public void Init()
47 {
48 helper = new MockServiceHelper();
49
50 server = helper.GetServer();
51 server.Start();
52 channel = helper.GetChannel();
53
Jan Tattermusch410c4732015-08-08 00:02:07 -070054 headers = new Metadata { { "ascii-header", "abcdefg" } };
Jan Tattermuschc75c57c2015-08-07 22:07:40 -070055 }
56
57 [TearDown]
58 public void Cleanup()
59 {
Jan Tattermusch2b357952015-08-20 14:54:33 -070060 channel.ShutdownAsync().Wait();
Jan Tattermuschc75c57c2015-08-07 22:07:40 -070061 server.ShutdownAsync().Wait();
62 }
63
Jan Tattermuschc75c57c2015-08-07 22:07:40 -070064 [Test]
Jan Tattermuschfb34a992015-08-21 10:45:39 -070065 public async Task ResponseHeadersAsync_UnaryCall()
66 {
67 helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
68 {
69 await context.WriteResponseHeadersAsync(headers);
70 return "PASS";
71 });
72
73 var call = Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "");
74 var responseHeaders = await call.ResponseHeadersAsync;
75
76 Assert.AreEqual(headers.Count, responseHeaders.Count);
77 Assert.AreEqual("ascii-header", responseHeaders[0].Key);
78 Assert.AreEqual("abcdefg", responseHeaders[0].Value);
79
80 Assert.AreEqual("PASS", await call.ResponseAsync);
81 }
82
83 [Test]
Jan Tattermusch4c25efa2015-08-21 16:07:57 -070084 public async Task ResponseHeadersAsync_ClientStreamingCall()
85 {
86 helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) =>
87 {
88 await context.WriteResponseHeadersAsync(headers);
89 return "PASS";
90 });
91
92 var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall());
93 await call.RequestStream.CompleteAsync();
94 var responseHeaders = await call.ResponseHeadersAsync;
95
96 Assert.AreEqual("ascii-header", responseHeaders[0].Key);
97 Assert.AreEqual("PASS", await call.ResponseAsync);
98 }
99
100 [Test]
101 public async Task ResponseHeadersAsync_ServerStreamingCall()
102 {
103 helper.ServerStreamingHandler = new ServerStreamingServerMethod<string, string>(async (request, responseStream, context) =>
104 {
105 await context.WriteResponseHeadersAsync(headers);
106 await responseStream.WriteAsync("PASS");
107 });
108
109 var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), "");
110 var responseHeaders = await call.ResponseHeadersAsync;
111
112 Assert.AreEqual("ascii-header", responseHeaders[0].Key);
Jan Tattermuschdca145b2015-08-21 16:12:35 -0700113 CollectionAssert.AreEqual(new[] { "PASS" }, await call.ResponseStream.ToListAsync());
Jan Tattermusch4c25efa2015-08-21 16:07:57 -0700114 }
115
116 [Test]
117 public async Task ResponseHeadersAsync_DuplexStreamingCall()
118 {
119 helper.DuplexStreamingHandler = new DuplexStreamingServerMethod<string, string>(async (requestStream, responseStream, context) =>
120 {
121 await context.WriteResponseHeadersAsync(headers);
122 while (await requestStream.MoveNext())
123 {
124 await responseStream.WriteAsync(requestStream.Current);
125 }
126 });
127
128 var call = Calls.AsyncDuplexStreamingCall(helper.CreateDuplexStreamingCall());
129 var responseHeaders = await call.ResponseHeadersAsync;
130
131 var messages = new[] { "PASS" };
132 await call.RequestStream.WriteAllAsync(messages);
133
134 Assert.AreEqual("ascii-header", responseHeaders[0].Key);
135 CollectionAssert.AreEqual(messages, await call.ResponseStream.ToListAsync());
136 }
137
138 [Test]
Jan Tattermuschc75c57c2015-08-07 22:07:40 -0700139 public void WriteResponseHeaders_NullNotAllowed()
140 {
Jan Tattermusch2fb313c2017-08-09 09:41:25 +0200141 helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) =>
Jan Tattermuschc75c57c2015-08-07 22:07:40 -0700142 {
Jan Tattermusche331da22016-04-08 11:05:39 -0700143 Assert.ThrowsAsync(typeof(ArgumentNullException), async () => await context.WriteResponseHeadersAsync(null));
Jan Tattermusch2fb313c2017-08-09 09:41:25 +0200144 return Task.FromResult("PASS");
Jan Tattermuschc75c57c2015-08-07 22:07:40 -0700145 });
146
147 Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), ""));
148 }
149
150 [Test]
151 public void WriteResponseHeaders_AllowedOnlyOnce()
152 {
153 helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
154 {
155 await context.WriteResponseHeadersAsync(headers);
156 try
157 {
158 await context.WriteResponseHeadersAsync(headers);
159 Assert.Fail();
160 }
Jan Tattermusch2fb313c2017-08-09 09:41:25 +0200161 catch (InvalidOperationException)
Jan Tattermuschc75c57c2015-08-07 22:07:40 -0700162 {
163 }
164 return "PASS";
165 });
166
167 Assert.AreEqual("PASS", Calls.BlockingUnaryCall(helper.CreateUnaryCall(), ""));
168 }
169
170 [Test]
171 public async Task WriteResponseHeaders_NotAllowedAfterWrite()
172 {
173 helper.ServerStreamingHandler = new ServerStreamingServerMethod<string, string>(async (request, responseStream, context) =>
174 {
175 await responseStream.WriteAsync("A");
176 try
177 {
178 await context.WriteResponseHeadersAsync(headers);
179 Assert.Fail();
180 }
Jan Tattermusch2fb313c2017-08-09 09:41:25 +0200181 catch (InvalidOperationException)
Jan Tattermuschc75c57c2015-08-07 22:07:40 -0700182 {
183 }
184 await responseStream.WriteAsync("B");
185 });
186
187 var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), "");
Jan Tattermuschf22abfb2015-08-09 16:15:34 -0700188 var responses = await call.ResponseStream.ToListAsync();
Jan Tattermuschc75c57c2015-08-07 22:07:40 -0700189 CollectionAssert.AreEqual(new[] { "A", "B" }, responses);
190 }
191 }
192}