Home | History | Annotate | Download | only in tests
      1 /*
      2  *
      3  * Copyright 2015 gRPC authors.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  */
     18 
     19 #import <UIKit/UIKit.h>
     20 #import <XCTest/XCTest.h>
     21 
     22 #import <RxLibrary/GRXBufferedPipe.h>
     23 #import <RxLibrary/GRXWriteable.h>
     24 #import <RxLibrary/GRXWriter.h>
     25 
     26 #define TEST_TIMEOUT 1
     27 
     28 // A mock of a GRXSingleValueHandler block that can be queried for how many times it was called and
     29 // what were the last values passed to it.
     30 //
     31 // TODO(jcanizales): Move this to a test util library, and add tests for it.
     32 @interface CapturingSingleValueHandler : NSObject
     33 @property(nonatomic, readonly) void (^block)(id value, NSError *errorOrNil);
     34 @property(nonatomic, readonly) NSUInteger timesCalled;
     35 @property(nonatomic, readonly) id value;
     36 @property(nonatomic, readonly) NSError *errorOrNil;
     37 + (instancetype)handler;
     38 @end
     39 
     40 @implementation CapturingSingleValueHandler
     41 + (instancetype)handler {
     42   return [[self alloc] init];
     43 }
     44 
     45 - (GRXSingleHandler)block {
     46   return ^(id value, NSError *errorOrNil) {
     47     ++_timesCalled;
     48     _value = value;
     49     _errorOrNil = errorOrNil;
     50   };
     51 }
     52 @end
     53 
     54 // TODO(jcanizales): Split into one file per tested class.
     55 
     56 @interface RxLibraryUnitTests : XCTestCase
     57 @end
     58 
     59 @implementation RxLibraryUnitTests
     60 
     61 + (void)setUp {
     62   NSLog(@"GRPCClientTests Started");
     63 }
     64 
     65 #pragma mark Writeable
     66 
     67 - (void)testWriteableSingleHandlerIsCalledForValue {
     68   // Given:
     69   CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
     70   id anyValue = @7;
     71 
     72   // If:
     73   id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
     74   [writeable writeValue:anyValue];
     75   [writeable writesFinishedWithError:nil];
     76 
     77   // Then:
     78   XCTAssertEqual(handler.timesCalled, 1);
     79   XCTAssertEqualObjects(handler.value, anyValue);
     80   XCTAssertEqualObjects(handler.errorOrNil, nil);
     81 }
     82 
     83 - (void)testWriteableSingleHandlerIsCalledForError {
     84   // Given:
     85   CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
     86   NSError *anyError = [NSError errorWithDomain:@"domain" code:7 userInfo:nil];
     87 
     88   // If:
     89   id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
     90   [writeable writesFinishedWithError:anyError];
     91 
     92   // Then:
     93   XCTAssertEqual(handler.timesCalled, 1);
     94   XCTAssertEqualObjects(handler.value, nil);
     95   XCTAssertEqualObjects(handler.errorOrNil, anyError);
     96 }
     97 
     98 - (void)testWriteableSingleHandlerIsCalledOnlyOnce_ValueThenError {
     99   // Given:
    100   CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
    101   id anyValue = @7;
    102   NSError *anyError = [NSError errorWithDomain:@"domain" code:7 userInfo:nil];
    103 
    104   // If:
    105   id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
    106   [writeable writeValue:anyValue];
    107   [writeable writesFinishedWithError:anyError];
    108 
    109   // Then:
    110   XCTAssertEqual(handler.timesCalled, 1);
    111   XCTAssertEqualObjects(handler.value, anyValue);
    112   XCTAssertEqualObjects(handler.errorOrNil, nil);
    113 }
    114 
    115 - (void)testWriteableSingleHandlerIsCalledOnlyOnce_ValueThenValue {
    116   // Given:
    117   CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
    118   id anyValue = @7;
    119 
    120   // If:
    121   id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
    122   [writeable writeValue:anyValue];
    123   [writeable writeValue:anyValue];
    124   [writeable writesFinishedWithError:nil];
    125 
    126   // Then:
    127   XCTAssertEqual(handler.timesCalled, 1);
    128   XCTAssertEqualObjects(handler.value, anyValue);
    129   XCTAssertEqualObjects(handler.errorOrNil, nil);
    130 }
    131 
    132 - (void)testWriteableSingleHandlerFailsOnEmptyWriter {
    133   // Given:
    134   CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
    135 
    136   // If:
    137   id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:handler.block];
    138   [writeable writesFinishedWithError:nil];
    139 
    140   // Then:
    141   XCTAssertEqual(handler.timesCalled, 1);
    142   XCTAssertEqualObjects(handler.value, nil);
    143   XCTAssertNotNil(handler.errorOrNil);
    144 }
    145 
    146 #pragma mark BufferedPipe
    147 
    148 - (void)testBufferedPipePropagatesValue {
    149   __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Response received"];
    150   // Given:
    151   CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
    152   id<GRXWriteable> writeable =
    153       [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil) {
    154         handler.block(value, errorOrNil);
    155         [expectation fulfill];
    156       }];
    157 
    158   id anyValue = @7;
    159 
    160   // If:
    161   GRXBufferedPipe *pipe = [GRXBufferedPipe pipe];
    162   [pipe startWithWriteable:writeable];
    163   [pipe writeValue:anyValue];
    164   [pipe writesFinishedWithError:nil];
    165 
    166   // Then:
    167   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
    168   XCTAssertEqual(handler.timesCalled, 1);
    169   XCTAssertEqualObjects(handler.value, anyValue);
    170   XCTAssertEqualObjects(handler.errorOrNil, nil);
    171 }
    172 
    173 - (void)testBufferedPipePropagatesError {
    174   __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Response received"];
    175   // Given:
    176   CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
    177   id<GRXWriteable> writeable =
    178       [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil) {
    179         handler.block(value, errorOrNil);
    180         [expectation fulfill];
    181       }];
    182   NSError *anyError = [NSError errorWithDomain:@"domain" code:7 userInfo:nil];
    183 
    184   // If:
    185   GRXBufferedPipe *pipe = [GRXBufferedPipe pipe];
    186   [pipe startWithWriteable:writeable];
    187   [pipe writesFinishedWithError:anyError];
    188 
    189   // Then:
    190   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
    191   XCTAssertEqual(handler.timesCalled, 1);
    192   XCTAssertEqualObjects(handler.value, nil);
    193   XCTAssertEqualObjects(handler.errorOrNil, anyError);
    194 }
    195 
    196 - (void)testBufferedPipeFinishWriteWhilePaused {
    197   __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Response received"];
    198   // Given:
    199   CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
    200   id<GRXWriteable> writeable =
    201       [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil) {
    202         handler.block(value, errorOrNil);
    203         [expectation fulfill];
    204       }];
    205   id anyValue = @7;
    206 
    207   // If:
    208   GRXBufferedPipe *pipe = [GRXBufferedPipe pipe];
    209   // Write something, then finish
    210   [pipe writeValue:anyValue];
    211   [pipe writesFinishedWithError:nil];
    212   // then start the writeable
    213   [pipe startWithWriteable:writeable];
    214 
    215   // Then:
    216   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
    217   XCTAssertEqual(handler.timesCalled, 1);
    218   XCTAssertEqualObjects(handler.value, anyValue);
    219   XCTAssertEqualObjects(handler.errorOrNil, nil);
    220 }
    221 
    222 #define WRITE_ROUNDS (1000)
    223 - (void)testBufferedPipeResumeWhenDealloc {
    224   id anyValue = @7;
    225   id<GRXWriteable> writeable =
    226       [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil){
    227       }];
    228 
    229   // Release after alloc;
    230   GRXBufferedPipe *pipe = [GRXBufferedPipe pipe];
    231   pipe = nil;
    232 
    233   // Release after write but before start
    234   pipe = [GRXBufferedPipe pipe];
    235   for (int i = 0; i < WRITE_ROUNDS; i++) {
    236     [pipe writeValue:anyValue];
    237   }
    238   pipe = nil;
    239 
    240   // Release after start but not write
    241   pipe = [GRXBufferedPipe pipe];
    242   [pipe startWithWriteable:writeable];
    243   pipe = nil;
    244 
    245   // Release after start and write
    246   pipe = [GRXBufferedPipe pipe];
    247   for (int i = 0; i < WRITE_ROUNDS; i++) {
    248     [pipe writeValue:anyValue];
    249   }
    250   [pipe startWithWriteable:writeable];
    251   pipe = nil;
    252 
    253   // Release after start, write and pause
    254   pipe = [GRXBufferedPipe pipe];
    255   [pipe startWithWriteable:writeable];
    256   for (int i = 0; i < WRITE_ROUNDS; i++) {
    257     [pipe writeValue:anyValue];
    258   }
    259   pipe.state = GRXWriterStatePaused;
    260   for (int i = 0; i < WRITE_ROUNDS; i++) {
    261     [pipe writeValue:anyValue];
    262   }
    263   pipe = nil;
    264 
    265   // Release after start, write, pause and finish
    266   pipe = [GRXBufferedPipe pipe];
    267   [pipe startWithWriteable:writeable];
    268   for (int i = 0; i < WRITE_ROUNDS; i++) {
    269     [pipe writeValue:anyValue];
    270   }
    271   pipe.state = GRXWriterStatePaused;
    272   for (int i = 0; i < WRITE_ROUNDS; i++) {
    273     [pipe writeValue:anyValue];
    274   }
    275   [pipe finishWithError:nil];
    276   pipe = nil;
    277 
    278   // Release after start, write, pause, finish and resume
    279   pipe = [GRXBufferedPipe pipe];
    280   [pipe startWithWriteable:writeable];
    281   for (int i = 0; i < WRITE_ROUNDS; i++) {
    282     [pipe writeValue:anyValue];
    283   }
    284   pipe.state = GRXWriterStatePaused;
    285   for (int i = 0; i < WRITE_ROUNDS; i++) {
    286     [pipe writeValue:anyValue];
    287   }
    288   [pipe finishWithError:nil];
    289   pipe.state = GRXWriterStateStarted;
    290   pipe = nil;
    291 }
    292 
    293 @end
    294