3 * Copyright 2015 gRPC authors.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #import <XCTest/XCTest.h>
21 #import <RxLibrary/GRXBufferedPipe.h>
22 #import <RxLibrary/GRXWriteable.h>
23 #import <RxLibrary/GRXWriter.h>
25 #define TEST_TIMEOUT 1
27 // A mock of a GRXSingleValueHandler block that can be queried for how many times it was called and
28 // what were the last values passed to it.
30 // TODO(jcanizales): Move this to a test util library, and add tests for it.
31 @interface CapturingSingleValueHandler : NSObject
32 @property(nonatomic, readonly) void (^block)(id value, NSError *errorOrNil);
33 @property(nonatomic, readonly) NSUInteger timesCalled;
34 @property(nonatomic, readonly) id value;
35 @property(nonatomic, readonly) NSError *errorOrNil;
36 + (instancetype)handler;
39 @implementation CapturingSingleValueHandler
40 + (instancetype)handler {
41 return [[self alloc] init];
44 - (GRXSingleHandler)block {
45 return ^(id value, NSError *errorOrNil) {
48 self->_errorOrNil = errorOrNil;
53 // TODO(jcanizales): Split into one file per tested class.
55 @interface RxLibraryUnitTests : XCTestCase
58 @implementation RxLibraryUnitTests
61 NSLog(@"GRPCClientTests Started");
64 #pragma mark Writeable
66 - (void)testWriteableSingleHandlerIsCalledForValue {
68 CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
72 id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
73 [writeable writeValue:anyValue];
74 [writeable writesFinishedWithError:nil];
77 XCTAssertEqual(handler.timesCalled, 1);
78 XCTAssertEqualObjects(handler.value, anyValue);
79 XCTAssertEqualObjects(handler.errorOrNil, nil);
82 - (void)testWriteableSingleHandlerIsCalledForError {
84 CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
85 NSError *anyError = [NSError errorWithDomain:@"domain" code:7 userInfo:nil];
88 id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
89 [writeable writesFinishedWithError:anyError];
92 XCTAssertEqual(handler.timesCalled, 1);
93 XCTAssertEqualObjects(handler.value, nil);
94 XCTAssertEqualObjects(handler.errorOrNil, anyError);
97 - (void)testWriteableSingleHandlerIsCalledOnlyOnce_ValueThenError {
99 CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
101 NSError *anyError = [NSError errorWithDomain:@"domain" code:7 userInfo:nil];
104 id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
105 [writeable writeValue:anyValue];
106 [writeable writesFinishedWithError:anyError];
109 XCTAssertEqual(handler.timesCalled, 1);
110 XCTAssertEqualObjects(handler.value, anyValue);
111 XCTAssertEqualObjects(handler.errorOrNil, nil);
114 - (void)testWriteableSingleHandlerIsCalledOnlyOnce_ValueThenValue {
116 CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
120 id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
121 [writeable writeValue:anyValue];
122 [writeable writeValue:anyValue];
123 [writeable writesFinishedWithError:nil];
126 XCTAssertEqual(handler.timesCalled, 1);
127 XCTAssertEqualObjects(handler.value, anyValue);
128 XCTAssertEqualObjects(handler.errorOrNil, nil);
131 - (void)testWriteableSingleHandlerFailsOnEmptyWriter {
133 CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
136 id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
137 [writeable writesFinishedWithError:nil];
140 XCTAssertEqual(handler.timesCalled, 1);
141 XCTAssertEqualObjects(handler.value, nil);
142 XCTAssertNotNil(handler.errorOrNil);
145 #pragma mark BufferedPipe
147 - (void)testBufferedPipePropagatesValue {
148 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Response received"];
150 CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
151 id<GRXWriteable> writeable =
152 [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil) {
153 handler.block(value, errorOrNil);
154 [expectation fulfill];
160 GRXBufferedPipe *pipe = [GRXBufferedPipe pipe];
161 [pipe startWithWriteable:writeable];
162 [pipe writeValue:anyValue];
163 [pipe writesFinishedWithError:nil];
166 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
167 XCTAssertEqual(handler.timesCalled, 1);
168 XCTAssertEqualObjects(handler.value, anyValue);
169 XCTAssertEqualObjects(handler.errorOrNil, nil);
172 - (void)testBufferedPipePropagatesError {
173 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Response received"];
175 CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
176 id<GRXWriteable> writeable =
177 [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil) {
178 handler.block(value, errorOrNil);
179 [expectation fulfill];
181 NSError *anyError = [NSError errorWithDomain:@"domain" code:7 userInfo:nil];
184 GRXBufferedPipe *pipe = [GRXBufferedPipe pipe];
185 [pipe startWithWriteable:writeable];
186 [pipe writesFinishedWithError:anyError];
189 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
190 XCTAssertEqual(handler.timesCalled, 1);
191 XCTAssertEqualObjects(handler.value, nil);
192 XCTAssertEqualObjects(handler.errorOrNil, anyError);
195 - (void)testBufferedPipeFinishWriteWhilePaused {
196 __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Response received"];
198 CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
199 id<GRXWriteable> writeable =
200 [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil) {
201 handler.block(value, errorOrNil);
202 [expectation fulfill];
207 GRXBufferedPipe *pipe = [GRXBufferedPipe pipe];
208 // Write something, then finish
209 [pipe writeValue:anyValue];
210 [pipe writesFinishedWithError:nil];
211 // then start the writeable
212 [pipe startWithWriteable:writeable];
215 [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
216 XCTAssertEqual(handler.timesCalled, 1);
217 XCTAssertEqualObjects(handler.value, anyValue);
218 XCTAssertEqualObjects(handler.errorOrNil, nil);
221 #define WRITE_ROUNDS (1000)
222 - (void)testBufferedPipeResumeWhenDealloc {
224 id<GRXWriteable> writeable =
225 [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil){
228 // Release after alloc;
229 GRXBufferedPipe *pipe = [GRXBufferedPipe pipe];
232 // Release after write but before start
233 pipe = [GRXBufferedPipe pipe];
234 for (int i = 0; i < WRITE_ROUNDS; i++) {
235 [pipe writeValue:anyValue];
239 // Release after start but not write
240 pipe = [GRXBufferedPipe pipe];
241 [pipe startWithWriteable:writeable];
244 // Release after start and write
245 pipe = [GRXBufferedPipe pipe];
246 for (int i = 0; i < WRITE_ROUNDS; i++) {
247 [pipe writeValue:anyValue];
249 [pipe startWithWriteable:writeable];
252 // Release after start, write and pause
253 pipe = [GRXBufferedPipe pipe];
254 [pipe startWithWriteable:writeable];
255 for (int i = 0; i < WRITE_ROUNDS; i++) {
256 [pipe writeValue:anyValue];
258 pipe.state = GRXWriterStatePaused;
259 for (int i = 0; i < WRITE_ROUNDS; i++) {
260 [pipe writeValue:anyValue];
264 // Release after start, write, pause and finish
265 pipe = [GRXBufferedPipe pipe];
266 [pipe startWithWriteable:writeable];
267 for (int i = 0; i < WRITE_ROUNDS; i++) {
268 [pipe writeValue:anyValue];
270 pipe.state = GRXWriterStatePaused;
271 for (int i = 0; i < WRITE_ROUNDS; i++) {
272 [pipe writeValue:anyValue];
274 [pipe finishWithError:nil];
277 // Release after start, write, pause, finish and resume
278 pipe = [GRXBufferedPipe pipe];
279 [pipe startWithWriteable:writeable];
280 for (int i = 0; i < WRITE_ROUNDS; i++) {
281 [pipe writeValue:anyValue];
283 pipe.state = GRXWriterStatePaused;
284 for (int i = 0; i < WRITE_ROUNDS; i++) {
285 [pipe writeValue:anyValue];
287 [pipe finishWithError:nil];
288 pipe.state = GRXWriterStateStarted;