text:
@import XCTest;

#import <Bolts/Bolts.h>

@interface TaskTests : XCTestCase
@end

@implementation TaskTests

- (void)testBasicOnSuccess {
    [[[BFTask taskWithResult:@"foo"] continueWithSuccessBlock:^id(BFTask *task) {
        XCTAssertEqualObjects(@"foo", task.result);
        return nil;
    }] waitUntilFinished];
}

- (void)testBasicOnSuccessWithExecutor {
    __block BOOL completed = NO;
    BFTask *task = [[BFTask taskWithDelay:100] continueWithExecutor:[BFExecutor immediateExecutor]
                                                   withSuccessBlock:^id _Nullable(BFTask * _Nonnull task) {
                                                       completed = YES;
                                                       return nil;
                                                   }];
    [task waitUntilFinished];
    XCTAssertTrue(completed);
    XCTAssertTrue(task.completed);
    XCTAssertFalse(task.faulted);
    XCTAssertFalse(task.cancelled);
    XCTAssertNil(task.result);
}

- (void)testBasicOnSuccessWithToken {
    BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];
    BFTask *task = [BFTask taskWithDelay:100];

    task = [task continueWithSuccessBlock:^id(BFTask *task) {
        XCTFail(@"Success block should not be triggered");
        return nil;
    } cancellationToken:cts.token];

    [cts cancel];
    [task waitUntilFinished];

    XCTAssertTrue(task.cancelled);
}

- (void)testBasicOnSuccessWithExecutorToken {
    BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];
    BFTask *task = [BFTask taskWithDelay:100];

    task = [task continueWithExecutor:[BFExecutor immediateExecutor]
                         successBlock:^id(BFTask *task) {
                             XCTFail(@"Success block should not be triggered");
                             return nil;
                         }
                    cancellationToken:cts.token];

    [cts cancel];
    [task waitUntilFinished];

    XCTAssertTrue(task.cancelled);
}

- (void)testBasicOnSuccessWithCancelledToken {
    BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];
    BFTask *task = [BFTask taskWithResult:nil];

    [cts cancel];

    task = [task continueWithExecutor:[BFExecutor immediateExecutor]
                         successBlock:^id(BFTask *task) {
                             XCTFail(@"Success block should not be triggered");
                             return nil;
                         }
                    cancellationToken:cts.token];

    XCTAssertTrue(task.isCancelled);
}

- (void)testBasicContinueWithError {
    NSError *originalError = [NSError errorWithDomain:@"Bolts" code:22 userInfo:nil];
    [[[BFTask taskWithError:originalError] continueWithBlock:^id(BFTask *task) {
        XCTAssertNotNil(task.error, @"Task should have failed.");
        XCTAssertEqual((NSInteger)22, task.error.code);
        return nil;
    }] waitUntilFinished];
}

- (void)testBasicContinueWithException {
    NSString *message = @"This is expected.";
    [[[[BFTask taskWithResult:nil] continueWithBlock:^id(BFTask *task) {
        [NSException raise:NSInternalInconsistencyException format:message];
        return nil;
    }] continueWithBlock:^id(BFTask *task) {
        XCTAssertNotNil(task.exception, @"Task should have failed.");
        XCTAssertEqualObjects(message, task.exception.description);
        return nil;
    }] waitUntilFinished];
}

- (void)testBasicContinueWithToken {
    BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];
    BFTask *task = [BFTask taskWithDelay:100];

    task = [task continueWithExecutor:[BFExecutor immediateExecutor]
                                block:^id(BFTask *task) {
                                    XCTFail(@"Continuation block should not be triggered");
                                    return nil;
                                }
                    cancellationToken:cts.token];

    [cts cancel];
    [task waitUntilFinished];

    XCTAssertTrue(task.isCancelled);
}

- (void)testBasicContinueWithCancelledToken {
    BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];
    BFTask *task = [BFTask taskWithResult:nil];

    [cts cancel];

    task = [task continueWithExecutor:[BFExecutor immediateExecutor]
                                block:^id(BFTask *task) {
                                    XCTFail(@"Continuation block should not be triggered");
                                    return nil;
                                }
                    cancellationToken:cts.token];

    XCTAssertTrue(task.isCancelled);
}

- (void)testFinishLaterWithSuccess {
    BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
    BFTask *task = [tcs.task continueWithBlock:^id(BFTask *task) {
        XCTAssertEqualObjects(@"bar", task.result);
        return nil;
    }];
    [[BFTask taskWithDelay:0] continueWithBlock:^id(BFTask *task) {
        tcs.result = @"bar";
        return nil;
    }];
    [task waitUntilFinished];
}

- (void)testFinishLaterWithError {
    BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
    BFTask *task = [tcs.task continueWithBlock:^id(BFTask *task) {
        XCTAssertNotNil(task.error);
        XCTAssertEqual((NSInteger)23, task.error.code);
        return nil;
    }];
    [[BFTask taskWithDelay:0] continueWithBlock:^id(BFTask *task) {
        tcs.error = [NSError errorWithDomain:@"Bolts" code:23 userInfo:nil];
        return nil;
    }];
    [task waitUntilFinished];
}

- (void)testFinishLaterWithException {
    NSString *message = @"This is expected.";
    BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
    BFTask *task = [tcs.task continueWithBlock:^id(BFTask *task) {
        XCTAssertNotNil(task.exception, @"Task should have failed.");
        XCTAssertEqualObjects(message, task.exception.description);
        return nil;
    }];
    [tcs setException:[NSException exceptionWithName:NSInternalInconsistencyException
                                              reason:message
                                            userInfo:nil]];
    [task waitUntilFinished];
}

- (void)testTransformConstantToConstant {
    BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
    BFTask *task = [[tcs.task continueWithBlock:^id(BFTask *task) {
        XCTAssertEqualObjects(@"foo", task.result);
        return @"bar";
    }] continueWithBlock:^id(BFTask *task) {
        XCTAssertEqualObjects(@"bar", task.result);
        return nil;
    }];
    [[BFTask taskWithDelay:0] continueWithBlock:^id(BFTask *task) {
        tcs.result = @"foo";
        return nil;
    }];
    [task waitUntilFinished];
}

- (void)testTransformErrorToConstant {
    BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
    BFTask *task = [[tcs.task continueWithBlock:^id(BFTask *task) {
        XCTAssertNotNil(task.error);
        XCTAssertEqual((NSInteger)23, task.error.code);
        return @"bar";
    }] continueWithBlock:^id(BFTask *task) {
        XCTAssertEqualObjects(@"bar", task.result);
        return nil;
    }];
    [[BFTask taskWithDelay:0] continueWithBlock:^id(BFTask *task) {
        tcs.error = [NSError errorWithDomain:@"Bolts" code:23 userInfo:nil];
        return nil;
    }];
    [task waitUntilFinished];
}

- (void)testReturnSuccessfulTaskFromContinuation {
    BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
    BFTask *task = [[tcs.task continueWithBlock:^id(BFTask *task) {
        XCTAssertEqualObjects(@"foo", task.result);
        return [BFTask taskWithResult:@"bar"];
    }] continueWithBlock:^id(BFTask *task) {
        XCTAssertEqualObjects(@"bar", task.result);
        return nil;
    }];
    [[BFTask taskWithDelay:0] continueWithBlock:^id(BFTask *task) {
        tcs.result = @"foo";
        return nil;
    }];
    [task waitUntilFinished];
}

- (void)testReturnSuccessfulTaskFromContinuationAfterError {
    BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
    BFTask *task = [[tcs.task continueWithBlock:^id(BFTask *task) {
        XCTAssertNotNil(task.error);
        XCTAssertEqual((NSInteger)23, task.error.code);
        return [BFTask taskWithResult:@"bar"];
    }] continueWithBlock:^id(BFTask *task) {
        XCTAssertEqualObjects(@"bar", task.result);
        return nil;
    }];
    [[BFTask taskWithDelay:0] continueWithBlock:^id(BFTask *task) {
        tcs.error = [NSError errorWithDomain:@"Bolts" code:23 userInfo:nil];
        return nil;
    }];
    [task waitUntilFinished];
}

- (void)testReturnErrorTaskFromContinuation {
    BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
    BFTask *task = [[tcs.task continueWithBlock:^id(BFTask *task) {
        XCTAssertEqualObjects(@"foo", task.result);
        NSError *originalError = [NSError errorWithDomain:@"Bolts" code:24 userInfo:nil];
        return [BFTask taskWithError:originalError];
    }] continueWithBlock:^id(BFTask *task) {
        XCTAssertNotNil(task.error);
        XCTAssertEqual((NSInteger)24, task.error.code);
        return nil;
    }];
    [[BFTask taskWithDelay:0] continueWithBlock:^id(BFTask *task) {
        tcs.result = @"foo";
        return nil;
    }];
    [task waitUntilFinished];
}

- (void)testReturnErrorTaskFromContinuationAfterError {
    BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
    BFTask *task = [[tcs.task continueWithBlock:^id(BFTask *task) {
        XCTAssertNotNil(task.error);
        XCTAssertEqual((NSInteger)23, task.error.code);
        NSError *originalError = [NSError errorWithDomain:@"Bolts" code:24 userInfo:nil];
        return [BFTask taskWithError:originalError];
    }] continueWithBlock:^id(BFTask *task) {
        XCTAssertNotNil(task.error);
        XCTAssertEqual((NSInteger)24, task.error.code);
        return nil;
    }];
    [[BFTask taskWithDelay:0] continueWithBlock:^id(BFTask *task) {
        tcs.error = [NSError errorWithDomain:@"Bolts" code:23 userInfo:nil];
        return nil;
    }];
    [task waitUntilFinished];
}

- (void)testPassOnError {
    NSError *originalError = [NSError errorWithDomain:@"Bolts" code:30 userInfo:nil];
    [[[[[[[[BFTask taskWithError:originalError] continueWithSuccessBlock:^id(BFTask *task) {
        XCTFail(@"This callback should be skipped.");
        return nil;
    }] continueWithSuccessBlock:^id(BFTask *task) {
        XCTFail(@"This callback should be skipped.");
        return nil;
    }] continueWithBlock:^id(BFTask *task) {
        XCTAssertNotNil(task.error);
        XCTAssertEqual((NSInteger)30, task.error.code);
        NSError *newError = [NSError errorWithDomain:@"Bolts" code:31 userInfo:nil];
        return [BFTask taskWithError:newError];
    }] continueWithSuccessBlock:^id(BFTask *task) {
        XCTFail(@"This callback should be skipped.");
        return nil;
    }] continueWithBlock:^id(BFTask *task) {
        XCTAssertNotNil(task.error);
        XCTAssertEqual((NSInteger)31, task.error.code);
        return [BFTask taskWithResult:@"okay"];
    }] continueWithSuccessBlock:^id(BFTask *task) {
        XCTAssertEqualObjects(@"okay", task.result);
        return nil;
    }] waitUntilFinished];
}

- (void)testCancellation {
    BFTaskCompletionSource *tcs = [BFTaskCompletionSource taskCompletionSource];
    BFTask *task = [[BFTask taskWithDelay:100] continueWithBlock:^id(BFTask *task) {
        return tcs.task;
    }];

    [tcs cancel];
    [task waitUntilFinished];

    XCTAssertTrue(task.isCancelled);
}

- (void)testTaskForCompletionOfAllTasksSuccess {
    NSMutableArray *tasks = [NSMutableArray array];

    const int kTaskCount = 20;
    for (int i = 0; i < kTaskCount; ++i) {
        double sleepTimeInMs = rand() % 100;
        [tasks addObject:[[BFTask taskWithDelay:(int)sleepTimeInMs] continueWithBlock:^id(BFTask *task) {
            return @(i);
        }]];
    }

    [[[BFTask taskForCompletionOfAllTasks:tasks] continueWithBlock:^id(BFTask *task) {
        XCTAssertNil(task.error);
        XCTAssertNil(task.exception);
        XCTAssertFalse(task.isCancelled);

        for (int i = 0; i < kTaskCount; ++i) {
            XCTAssertEqual(i, [((BFTask *)[tasks objectAtIndex:i]).result intValue]);
        }
        return nil;
    }] waitUntilFinished];
}

- (void)testTaskForCompletionOfAllTasksOneException {
    NSMutableArray *tasks = [NSMutableArray array];

    const int kTaskCount = 20;
    for (int i = 0; i < kTaskCount; ++i) {
        double sleepTimeInMs = rand() % 100;
        [tasks addObject:[[BFTask taskWithDelay:(int)sleepTimeInMs] continueWithBlock:^id(BFTask *task) {
            if (i == 10) {
                [NSException raise:@"TestException" format:@"This exception is expected."];
            }
            return @(i);
        }]];
    }

    [[[BFTask taskForCompletionOfAllTasks:tasks] continueWithBlock:^id(BFTask *task) {
        XCTAssertNil(task.error);
        XCTAssertNotNil(task.exception);
        XCTAssertFalse(task.isCancelled);

        XCTAssertEqualObjects(@"TestException", task.exception.name);

        for (int i = 0; i < kTaskCount; ++i) {
            if (i == 10) {
                XCTAssertNotNil(((BFTask *)[tasks objectAtIndex:i]).exception);
            } else {
                XCTAssertEqual(i, [((BFTask *)[tasks objectAtIndex:i]).result intValue]);
            }
        }
        return nil;
    }] waitUntilFinished];
}

- (void)testTaskForCompletionOfAllTasksTwoExceptions {
    NSMutableArray *tasks = [NSMutableArray array];

    const int kTaskCount = 20;
    for (int i = 0; i < kTaskCount; ++i) {
        double sleepTimeInMs = rand() % 100;
        [tasks addObject:[[BFTask taskWithDelay:(int)sleepTimeInMs] continueWithBlock:^id(BFTask *task) {
            if (i == 10 || i == 11) {
                [NSException raise:@"TestException" format:@"This exception is expected."];
            }
            return @(i);
        }]];
    }

    [[[BFTask taskForCompletionOfAllTasks:tasks] continueWithBlock:^id(BFTask *task) {
        XCTAssertNil(task.error);
        XCTAssertNotNil(task.exception);
        XCTAssertFalse(task.isCancelled);

        XCTAssertEqualObjects(@"BFMultipleExceptionsException", task.exception.name);

        NSArray *exceptions = [task.exception.userInfo objectForKey:BFTaskMultipleExceptionsUserInfoKey];
        XCTAssertEqual(2, (int)exceptions.count);
        XCTAssertEqualObjects(@"TestException", [[exceptions objectAtIndex:0] name]);
        XCTAssertEqualObjects(@"TestException", [[exceptions objectAtIndex:1] name]);

        for (int i = 0; i < kTaskCount; ++i) {
            if (i == 10 || i == 11) {
                XCTAssertNotNil(((BFTask *)[tasks objectAtIndex:i]).exception);
            } else {
                XCTAssertEqual(i, [((BFTask *)[tasks objectAtIndex:i]).result intValue]);
            }
        }
        return nil;
    }] waitUntilFinished];
}

- (void)testTaskForCompletionOfAllTasksOneError {
    NSMutableArray *tasks = [NSMutableArray array];

    const int kTaskCount = 20;
    for (int i = 0; i < kTaskCount; ++i) {
        double sleepTimeInMs = rand() % 100;
        [tasks addObject:[[BFTask taskWithDelay:(int)sleepTimeInMs] continueWithBlock:^id(BFTask *task) {
            if (i == 10) {
                return [BFTask taskWithError:[NSError errorWithDomain:@"BoltsTests"
                                                                 code:35
                                                             userInfo:nil]];
            }
            return @(i);
        }]];
    }

    [[[BFTask taskForCompletionOfAllTasks:tasks] continueWithBlock:^id(BFTask *task) {
        XCTAssertNotNil(task.error);
        XCTAssertNil(task.exception);
        XCTAssertFalse(task.isCancelled);

        XCTAssertEqualObjects(@"BoltsTests", task.error.domain);
        XCTAssertEqual(35, (int)task.error.code);

        for (int i = 0; i < kTaskCount; ++i) {
            if (i == 10) {
                XCTAssertNotNil(((BFTask *)[tasks objectAtIndex:i]).error);
            } else {
                XCTAssertEqual(i, [((BFTask *)[tasks objectAtIndex:i]).result intValue]);
            }
        }
        return nil;
    }] waitUntilFinished];
}

- (void)testTaskForCompletionOfAllTasksTwoErrors {
    NSMutableArray *tasks = [NSMutableArray array];

    const int kTaskCount = 20;
    for (int i = 0; i < kTaskCount; ++i) {
        double sleepTimeInMs = rand() % 100;
        [tasks addObject:[[BFTask taskWithDelay:(int)sleepTimeInMs] continueWithBlock:^id(BFTask *task) {
            if (i == 10 || i == 11) {
                return [BFTask taskWithError:[NSError errorWithDomain:@"BoltsTests"
                                                                 code:35
                                                             userInfo:nil]];
            }
            return @(i);
        }]];
    }

    [[[BFTask taskForCompletionOfAllTasks:tasks] continueWithBlock:^id(BFTask *task) {
        XCTAssertNotNil(task.error);
        XCTAssertNil(task.exception);
        XCTAssertFalse(task.isCancelled);

        XCTAssertEqualObjects(@"bolts", task.error.domain);
        XCTAssertEqual(kBFMultipleErrorsError, task.error.code);

        NSArray *errors = [task.error.userInfo objectForKey:BFTaskMultipleErrorsUserInfoKey];
        XCTAssertEqualObjects(@"BoltsTests", [[errors objectAtIndex:0] domain]);
        XCTAssertEqual(35, (int)[[errors objectAtIndex:0] code]);
        XCTAssertEqualObjects(@"BoltsTests", [[errors objectAtIndex:1] domain]);
        XCTAssertEqual(35, (int)[[errors objectAtIndex:1] code]);

        for (int i = 0; i < kTaskCount; ++i) {
            if (i == 10 || i == 11) {
                XCTAssertNotNil(((BFTask *)[tasks objectAtIndex:i]).error);
            } else {
                XCTAssertEqual(i, [((BFTask *)[tasks objectAtIndex:i]).result intValue]);
            }
        }
        return nil;
    }] waitUntilFinished];
}

- (void)testTaskForCompletionOfAllTasksCancelled {
    NSMutableArray *tasks = [NSMutableArray array];

    const int kTaskCount = 20;
    for (int i = 0; i < kTaskCount; ++i) {
        double sleepTimeInMs = rand() % 100;
        [tasks addObject:[[BFTask taskWithDelay:(int)sleepTimeInMs] continueWithBlock:^id(BFTask *task) {
            if (i == 10) {
                return [BFTask cancelledTask];
            }
            return @(i);
        }]];
    }

    [[[BFTask taskForCompletionOfAllTasks:tasks] continueWithBlock:^id(BFTask *task) {
        XCTAssertNil(task.error);
        XCTAssertNil(task.exception);
        XCTAssertTrue(task.isCancelled);

        for (int i = 0; i < kTaskCount; ++i) {
            if (i == 10) {
                XCTAssertTrue(((BFTask *)[tasks objectAtIndex:i]).isCancelled);
            } else {
                XCTAssertEqual(i, [((BFTask *)[tasks objectAtIndex:i]).result intValue]);
            }
        }
        return nil;
    }] waitUntilFinished];
}

- (void)testTaskForCompletionOfAllTasksNoTasksImmediateCompletion {
    NSMutableArray *tasks = [NSMutableArray array];

    BFTask *task = [BFTask taskForCompletionOfAllTasks:tasks];
    XCTAssertTrue(task.completed);
    XCTAssertFalse(task.cancelled);
    XCTAssertFalse(task.faulted);
}

- (void)testTaskForCompletionOfAllTasksWithResultsSuccess {
    NSMutableArray *tasks = [NSMutableArray array];

    const int kTaskCount = 20;
    for (int i = 0; i < kTaskCount; ++i) {
        double sleepTimeInMs = i * 10;
        int result = i + 1;
        [tasks addObject:[[BFTask taskWithDelay:(int)sleepTimeInMs] continueWithBlock:^id(BFTask *task) {
            return @(result);
        }]];
    }

    [[[BFTask taskForCompletionOfAllTasksWithResults:tasks] continueWithBlock:^id(BFTask *task) {
        XCTAssertFalse(task.cancelled);
        XCTAssertFalse(task.faulted);

        NSArray *results = task.result;
        for (int i = 0; i < kTaskCount; ++i) {
            NSNumber *individualResult = [results objectAtIndex:i];
            XCTAssertEqual([individualResult intValue], [((BFTask *)[tasks objectAtIndex:i]).result intValue]);
        }
        return nil;
    }] waitUntilFinished];
}

- (void)testTaskForCompletionOfAllTasksErrorCancelledSuccess {
    BFTask *errorTask = [BFTask taskWithError:[NSError new]];
    BFTask *cancelledTask = [BFTask cancelledTask];
    BFTask *successfulTask = [BFTask taskWithResult:[NSNumber numberWithInt:2]];

    BFTask *allTasks = [BFTask taskForCompletionOfAllTasks:@[ successfulTask, cancelledTask, errorTask ]];

    XCTAssertTrue(allTasks.faulted, @"Task should be faulted");
}

- (void)testTaskForCompletionOfAllTasksExceptionCancelledSuccess {
    NSException *exception = [NSException exceptionWithName:@"" reason:@"" userInfo:nil];
    BFTask *exceptionTask = [BFTask taskWithException:exception];
    BFTask *cancelledTask = [BFTask cancelledTask];
    BFTask *successfulTask = [BFTask taskWithResult:[NSNumber numberWithInt:2]];

    BFTask *allTasks = [BFTask taskForCompletionOfAllTasks:@[ successfulTask, cancelledTask, exceptionTask ]];

    XCTAssertTrue(allTasks.faulted, @"Task should be faulted");
    XCTAssertNil(allTasks.error, @"Task shoud not have error");
    XCTAssertNotNil(allTasks.exception, @"Task should have exception");
}

- (void)testTaskForCompletionOfAllTasksExceptionErrorCancelledSuccess {
    BFTask *errorTask = [BFTask taskWithError:[NSError new]];
    BFTask *exceptionTask = [BFTask taskWithException:[NSException new]];
    BFTask *cancelledTask = [BFTask cancelledTask];
    BFTask *successfulTask = [BFTask taskWithResult:[NSNumber numberWithInt:2]];

    BFTask *allTasks = [BFTask taskForCompletionOfAllTasks:@[ successfulTask, cancelledTask, exceptionTask, errorTask ]];

    XCTAssertTrue(allTasks.faulted, @"Task should be faulted");
    XCTAssertNotNil(allTasks.error, @"Task should have error");
    XCTAssertNil(allTasks.exception, @"Task should not have exception");
}

- (void)testTaskForCompletionOfAllTasksErrorCancelled {
    BFTask *errorTask = [BFTask taskWithError:[NSError new]];
    BFTask *cancelledTask = [BFTask cancelledTask];

    BFTask *allTasks = [BFTask taskForCompletionOfAllTasks:@[ cancelledTask, errorTask ]];

    XCTAssertTrue(allTasks.faulted, @"Task should be faulted");
}

- (void)testTaskForCompletionOfAllTasksSuccessCancelled {
    BFTask *cancelledTask = [BFTask cancelledTask];
    BFTask *successfulTask = [BFTask taskWithResult:[NSNumber numberWithInt:2]];

    BFTask *allTasks = [BFTask taskForCompletionOfAllTasks:@[ successfulTask, cancelledTask ]];

    XCTAssertTrue(allTasks.cancelled, @"Task should be cancelled");
}

- (void)testTaskForCompletionOfAllTasksSuccessError {
    BFTask *errorTask = [BFTask taskWithError:[NSError new]];
    BFTask *successfulTask = [BFTask taskWithResult:[NSNumber numberWithInt:2]];

    BFTask *allTasks = [BFTask taskForCompletionOfAllTasks:@[ successfulTask, errorTask ]];

    XCTAssertTrue(allTasks.faulted, @"Task should be faulted");
}

- (void)testTaskForCompletionOfAllTasksWithResultsNoTasksImmediateCompletion {
    NSMutableArray *tasks = [NSMutableArray array];

    BFTask *task = [BFTask taskForCompletionOfAllTasksWithResults:tasks];
    XCTAssertTrue(task.completed);
    XCTAssertFalse(task.cancelled);
    XCTAssertFalse(task.faulted);
    XCTAssertTrue(task.result != nil);
}

- (void)testTasksForTaskForCompletionOfAnyTasksWithSuccess {
    BFTask *task = [BFTask taskForCompletionOfAnyTask:@[[BFTask taskWithDelay:20], [BFTask taskWithResult:@"success"]]];
    [task waitUntilFinished];

    XCTAssertEqualObjects(@"success", task.result);
}

- (void)testTasksForTaskForCompletionOfAnyTasksWithRacing {
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    BFExecutor *executor = [BFExecutor executorWithDispatchQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];

    BFTask *first = [BFTask taskFromExecutor:executor withBlock:^id _Nullable {
        return @"first";
    }];
    BFTask *second = [BFTask taskFromExecutor:executor withBlock:^id _Nullable {
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        return @"second";
    }];

    BFTask *task = [BFTask taskForCompletionOfAnyTask:@[first, second]];
    [task waitUntilFinished];

    dispatch_semaphore_signal(semaphore);

    XCTAssertEqualObjects(@"first", task.result);
}

- (void)testTasksForTaskForCompletionOfAnyTasksWithErrorAndSuccess {
    NSError *error = [NSError errorWithDomain:@"BoltsTests"
                                         code:35
                                     userInfo:nil];

    BFTask *task = [BFTask taskForCompletionOfAnyTask:@[[BFTask taskWithError:error], [BFTask taskWithResult:@"success"]]];
    [task waitUntilFinished];

    XCTAssertEqualObjects(@"success", task.result);
    XCTAssertNil(task.error);
}

- (void)testTasksForTaskForCompletionOfAnyTasksWithError {
    NSError *error = [NSError errorWithDomain:@"BoltsTests"
                                         code:35
                                     userInfo:nil];

    BFTask *task = [BFTask taskForCompletionOfAnyTask:@[[BFTask taskWithError:error]]];
    [task waitUntilFinished];

    XCTAssertEqualObjects(error, task.error);
    XCTAssertNotNil(task.error);
}

- (void)testTasksForTaskForCompletionOfAnyTasksWithNilArray {

    BFTask *task = [BFTask taskForCompletionOfAnyTask:nil];
    [task waitUntilFinished];

    XCTAssertNil(task.result);
    XCTAssertNil(task.error);
    XCTAssertNil(task.exception);
}

- (void)testTasksForTaskForCompletionOfAnyTasksAllErrors {
    NSError *error = [NSError errorWithDomain:@"BoltsTests"
                                         code:35
                                     userInfo:nil];

    BFTask *task = [BFTask taskForCompletionOfAnyTask:@[[BFTask taskWithError:error], [BFTask taskWithError:error]]];
    [task waitUntilFinished];

    XCTAssertNil(task.result);
    XCTAssertNotNil(task.error);
    XCTAssertNotNil(task.error.userInfo);
    XCTAssertEqualObjects(@"bolts", task.error.domain);
    XCTAssertTrue([task.error.userInfo[@"errors"] isKindOfClass:[NSArray class]]);
    XCTAssertEqual(2, [task.error.userInfo[@"errors"] count]);
}

- (void)testWaitUntilFinished {
    BFTask *task = [[BFTask taskWithDelay:50] continueWithBlock:^id(BFTask *task) {
        return @"foo";
    }];

    [task waitUntilFinished];

    XCTAssertEqualObjects(@"foo", task.result);
}

- (void)testDelayWithToken {
    BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];

    BFTask *task = [BFTask taskWithDelay:100 cancellationToken:cts.token];

    [cts cancel];
    [task waitUntilFinished];

    XCTAssertTrue(task.cancelled, @"Task should be cancelled immediately");
}

- (void)testDelayWithCancelledToken {
    BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];
    [cts cancel];

    BFTask *task = [BFTask taskWithDelay:100 cancellationToken:cts.token];

    XCTAssertTrue(task.cancelled, @"Task should be cancelled immediately");
}

- (void)testTaskFromExecutor {
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0L);
    BFExecutor *queueExecutor = [BFExecutor executorWithDispatchQueue:queue];

    BFTask *task = [BFTask taskFromExecutor:queueExecutor withBlock:^id() {
        XCTAssertEqual(queue, dispatch_get_current_queue());
        return @"foo";
    }];
    [task waitUntilFinished];
    XCTAssertEqual(@"foo", task.result);
}

- (void)testDescription {
    BFTask *task = [BFTask taskWithResult:nil];
    NSString *expected = [NSString stringWithFormat:@"<BFTask: %p; completed = YES; cancelled = NO; faulted = NO; result = (null)>", task];

    NSString *description = task.description;

    XCTAssertTrue([expected isEqualToString:description]);
}

- (void)testReturnTaskFromContinuationWithCancellation {
    BFCancellationTokenSource *cts = [BFCancellationTokenSource cancellationTokenSource];

    XCTestExpectation *expectation = [self expectationWithDescription:@"task"];
    [[[BFTask taskWithDelay:1] continueWithBlock:^id(BFTask *task) {
        [cts cancel];
        return [BFTask taskWithDelay:10];
    } cancellationToken:cts.token] continueWithBlock:^id(BFTask *task) {
        XCTAssertTrue(task.cancelled);
        [expectation fulfill];
        return nil;
    }];
    [self waitForExpectationsWithTimeout:10.0 handler:nil];
}

- (void)testSetResult {
    BFTaskCompletionSource *taskCompletionSource = [BFTaskCompletionSource taskCompletionSource];
    taskCompletionSource.result = @"a";
    XCTAssertThrowsSpecificNamed([taskCompletionSource setResult:@"b"], NSException, NSInternalInconsistencyException);

    XCTAssertTrue(taskCompletionSource.task.completed);
    XCTAssertEqualObjects(taskCompletionSource.task.result, @"a");
}

- (void)testTrySetResult {
    BFTaskCompletionSource *taskCompletionSource = [BFTaskCompletionSource taskCompletionSource];
    [taskCompletionSource trySetResult:@"a"];
    [taskCompletionSource trySetResult:@"b"];
    XCTAssertTrue(taskCompletionSource.task.completed);
    XCTAssertEqualObjects(taskCompletionSource.task.result, @"a");
}

- (void)testSetError {
    BFTaskCompletionSource *taskCompletionSource = [BFTaskCompletionSource taskCompletionSource];

    NSError *error = [NSError errorWithDomain:@"TestDomain" code:100500 userInfo:nil];
    taskCompletionSource.error = error;
    XCTAssertThrowsSpecificNamed([taskCompletionSource setError:error], NSException, NSInternalInconsistencyException);

    XCTAssertTrue(taskCompletionSource.task.completed);
    XCTAssertTrue(taskCompletionSource.task.faulted);
    XCTAssertEqualObjects(taskCompletionSource.task.error, error);
}

- (void)testTrySetError {
    BFTaskCompletionSource *taskCompletionSource = [BFTaskCompletionSource taskCompletionSource];

    NSError *error = [NSError errorWithDomain:@"TestDomain" code:100500 userInfo:nil];
    [taskCompletionSource trySetError:error];
    [taskCompletionSource trySetError:error];

    XCTAssertTrue(taskCompletionSource.task.completed);
    XCTAssertTrue(taskCompletionSource.task.faulted);
    XCTAssertEqualObjects(taskCompletionSource.task.error, error);
}

- (void)testSetException {
    BFTaskCompletionSource *taskCompletionSource = [BFTaskCompletionSource taskCompletionSource];

    NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException reason:@"test" userInfo:nil];
    taskCompletionSource.exception = exception;
    XCTAssertThrowsSpecificNamed([taskCompletionSource setException:exception], NSException, NSInternalInconsistencyException);

    XCTAssertTrue(taskCompletionSource.task.completed);
    XCTAssertTrue(taskCompletionSource.task.faulted);
    XCTAssertEqualObjects(taskCompletionSource.task.exception, exception);
}

- (void)testTrySetException {
    BFTaskCompletionSource *taskCompletionSource = [BFTaskCompletionSource taskCompletionSource];

    NSException *exception = [NSException exceptionWithName:NSInvalidArgumentException reason:@"test" userInfo:nil];
    [taskCompletionSource trySetException:exception];
    [taskCompletionSource trySetException:exception];

    XCTAssertTrue(taskCompletionSource.task.completed);
    XCTAssertTrue(taskCompletionSource.task.faulted);
    XCTAssertEqualObjects(taskCompletionSource.task.exception, exception);
}

- (void)testSetCancelled {
    BFTaskCompletionSource *taskCompletionSource = [BFTaskCompletionSource taskCompletionSource];

    [taskCompletionSource cancel];
    XCTAssertThrowsSpecificNamed([taskCompletionSource cancel], NSException, NSInternalInconsistencyException);

    XCTAssertTrue(taskCompletionSource.task.completed);
    XCTAssertTrue(taskCompletionSource.task.cancelled);
}

- (void)testTrySetCancelled {
    BFTaskCompletionSource *taskCompletionSource = [BFTaskCompletionSource taskCompletionSource];

    [taskCompletionSource trySetCancelled];
    [taskCompletionSource trySetCancelled];

    XCTAssertTrue(taskCompletionSource.task.completed);
    XCTAssertTrue(taskCompletionSource.task.cancelled);
}

@end


text:
{% extends "horizon/common/_modal_form_add_members.html" %}
{% load i18n %}
{% load url from future %}

{% block modal-header %}{% trans "Add Group Assignment" %}{% endblock %}

{% block modal-footer %}
  {% trans "Cancel" %}
{% endblock %}

redpajama_set_name: RedPajamaGithub


text:
namespace generator
{
namespace
{
size_t constexpr kArcSecondsInDegree = 60 * 60;
size_t constexpr kSrtmTileSize = (kArcSecondsInDegree + 1) * (kArcSecondsInDegree + 1) * 2;

struct UnzipMemDelegate : public ZipFileReader::Delegate
{
  UnzipMemDelegate(string & buffer) : m_buffer(buffer), m_completed(false) {}

  // ZipFileReader::Delegate overrides:
  void OnBlockUnzipped(size_t size, char const * data) override { m_buffer.append(data, size); }

  void OnStarted() override
  {
    m_buffer.clear();
    m_completed = false;
  }

  void OnCompleted() override { m_completed = true; }

  string & m_buffer;
  bool m_completed;
};
}  // namespace

// SrtmTile ----------------------------------------------------------------------------------------
SrtmTile::SrtmTile()
{
  Invalidate();
}

SrtmTile::SrtmTile(SrtmTile && rhs) : m_data(move(rhs.m_data)), m_valid(rhs.m_valid)
{
  rhs.Invalidate();
}

void SrtmTile::Init(string const & dir, ms::LatLon const & coord)
{
  Invalidate();

  string const base = GetBase(coord);
  string const cont = dir + base + ".SRTMGL1.hgt.zip";
  string file = base + ".hgt";

  UnzipMemDelegate delegate(m_data);
  try
  {
    ZipFileReader::UnzipFile(cont, file, delegate);
  }
  catch (ZipFileReader::LocateZipException const & e)
  {
    // Sometimes packed file has different name. See N39E051 measure.
    file = base + ".SRTMGL1.hgt";

    ZipFileReader::UnzipFile(cont, file, delegate);
  }

  if (!delegate.m_completed)
  {
    LOG(LWARNING, ("Can't decompress SRTM file:", cont));
    Invalidate();
    return;
  }

  if (m_data.size() != kSrtmTileSize)
  {
    LOG(LWARNING, ("Bad decompressed SRTM file size:", cont, m_data.size()));
    Invalidate();
    return;
  }

  m_valid = true;
}

SrtmTile::THeight SrtmTile::GetHeight(ms::LatLon const & coord)
{
  if (!IsValid())
    return kInvalidHeight;

  double ln = coord.lon - static_cast<int>(coord.lon);
  if (ln < 0)
    ln += 1;
  double lt = coord.lat - static_cast<int>(coord.lat);
  if (lt < 0)
    lt += 1;
  lt = 1 - lt;  // from North to South

  size_t const row = kArcSecondsInDegree * lt;
  size_t const col = kArcSecondsInDegree * ln;

  size_t const ix = row * (kArcSecondsInDegree + 1) + col;

  if (ix >= Size())
    return kInvalidHeight;
  return ReverseByteOrder(Data()[ix]);
}

string SrtmTile::GetBase(ms::LatLon coord)
{
  ostringstream ss;
  if (coord.lat < 0)
  {
    ss << "S";
    coord.lat *= -1;
    coord.lat += 1;
  }
  else
  {
    ss << "N";
  }
  ss << setw(2) << setfill('0') << static_cast<int>(coord.lat);

  if (coord.lon < 0)
  {
    ss << "W";
    coord.lon *= -1;
    coord.lon += 1;
  }
  else
  {
    ss << "E";
  }
  ss << setw(3) << static_cast<int>(coord.lon);
  return ss.str();
}

void SrtmTile::Invalidate()
{
  m_data.clear();
  m_data.shrink_to_fit();
  m_valid = false;
}

// SrtmTileManager ---------------------------------------------------------------------------------
SrtmTileManager::SrtmTileManager(string const & dir) : m_dir(dir) {}

SrtmTile::THeight SrtmTileManager::GetHeight(ms::LatLon const & coord)
{
  string const base = SrtmTile::GetBase(coord);
  auto it = m_tiles.find(base);
  if (it == m_tiles.end())
  {
    SrtmTile tile;
    try
    {
      tile.Init(m_dir, coord);
    }
    catch (RootException const & e)
    {
      LOG(LWARNING, ("Can't init SRTM tile:", base, "reason:", e.Msg()));
    }

    // It's OK to store even invalid tiles and return invalid height
    // for them later.
    it = m_tiles.emplace(base, move(tile)).first;
  }

  return it->second.GetHeight(coord);
}
}  // namespace generator


text:
package com.jlj.dao.imp;

import java.sql.SQLException;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Component;

import com.jlj.dao.IAdminDao;
import com.jlj.model.Admin;
@Component("adminDao")
public class AdminDaoImp implements IAdminDao {
	private HibernateTemplate hibernateTemplate;

	public HibernateTemplate getHibernateTemplate() {
		return hibernateTemplate;
	}
	@Resource
	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}

	//保存一条记录
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#save(com.jlj.model.Admin)
	 */
	public void save(Admin admin) {
		this.hibernateTemplate.save(admin);
	}

	//删除一条记录
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#delete(com.jlj.model.Admin)
	 */
	public void delete(Admin admin) {
		this.hibernateTemplate.delete(admin);
	}
	//根据ID删除一条记录
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#deleteById(int)
	 */
	public void deleteById(int id) {
		this.hibernateTemplate.delete(this.loadById(id));
	}

	//修改一条记录
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#update(com.jlj.model.Admin)
	 */
	public void update(Admin admin) {
		this.hibernateTemplate.update(admin);
	}

	//根据hql语句、条件、条件值修改某些记录
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#updateByHql(java.lang.String, java.lang.String[], java.lang.Object[])
	 */
	public void updateByHql(final String hql,final String[] paramNames,final Object[] values) {
		this.hibernateTemplate.execute(new HibernateCallback(){

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query=session.createQuery(hql);
				for (int i = 0; i < paramNames.length; i++) {
					query.setParameter(paramNames[i], values[i]);
				}
				query.executeUpdate();
				return null;
			}

		});
	}

	//获得所有记录
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#getAdmins()
	 */
	public List<Admin> getAdmins() {
		return this.hibernateTemplate.loadAll(Admin.class);
	}

	//根据hql语句来查询所有记录
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#queryList(java.lang.String)
	 */
	public List<Admin> queryList(String queryString) {
		return this.hibernateTemplate.find(queryString);
	}

	//根据hql、条件值查询某些记录
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#getObjectsByCondition(java.lang.String, java.lang.Object[])
	 */
	public List<Admin> getObjectsByCondition(String queryString, Object[] p) {
		return this.hibernateTemplate.find(queryString,p);
	}

	//根据hql语句、条件、条件值查询某些记录
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#queryList(java.lang.String, java.lang.String[], java.lang.Object[])
	 */
	public List<Admin> queryList(String queryString, String[] paramNames,
			Object[] values)
	{
		List list =  this.hibernateTemplate.findByNamedParam(queryString, paramNames, values);
		return list;
	}

	//根据hql、id列表查询某些记录
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#getObjectsByIdList(java.lang.String, java.util.List)
	 */
	public List<Admin> getObjectsByIdList(final String hql,final List<Integer> idList) {
		return this.hibernateTemplate.executeFind(new HibernateCallback(){

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query=session.createQuery(hql);
				query.setParameterList("idList", idList);
				return query.list();
			}

		});
	}

	//根据hql语句、条件值、分页查询某些记录
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#pageList(java.lang.String, java.lang.Object[], java.lang.Integer, java.lang.Integer)
	 */
	public List<Admin> pageList(final String queryString,final Object[] p,final Integer page,
			final Integer size) {
		return this.hibernateTemplate.executeFind(new HibernateCallback(){

			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query query=session.createQuery(queryString);
				if(p!=null&&p.length>0){
					for (int i = 0; i < p.length; i++) {
						query.setParameter(i, p[i]);
					}
				}
				if(page!=null&&page>0&&size!=null&&size>0){
					query.setFirstResult((page-1)*size).setMaxResults(size);
				}
				return query.list();
			}

		});
	}

	//根据hql、条件值获得一个唯一值
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#getUniqueResult(java.lang.String, java.lang.Object[])
	 */
	public int getUniqueResult(final String queryString,final Object[] p) {
		Session session=this.hibernateTemplate.getSessionFactory().getCurrentSession();
		Query query= session.createQuery(queryString);
		if(p!=null&&p.length>0){
			for (int i = 0; i < p.length; i++) {
				query.setParameter(i, p[i]);
			}
		}
		Object obj=query.uniqueResult();
		return ((Long)obj).intValue();

	}

	//根据id查询一条记录
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#loadById(int)
	 */
	public Admin loadById(int id) {
		return (Admin) this.hibernateTemplate.load(Admin.class, id);
	}

	//根据hql语句、条件、值来查询一条记录
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#queryByNamedParam(java.lang.String, java.lang.String[], java.lang.Object[])
	 */
	public Admin queryByNamedParam(String queryString, String[] paramNames,
			Object[] values) {
		List list=this.hibernateTemplate.findByNamedParam(queryString, paramNames, values);
		return list.size()>0?(Admin)list.get(0):null;
	}

	//根据hql语句、条件值来查询是否存在该记录
	/* (non-Javadoc)
	 * @see com.jlj.dao.imp.IAdminDao#checkClientExistsWithName(java.lang.String, java.lang.Object[])
	 */
	public boolean checkClientExistsWithName(String queryString, Object[] p) {
		List list =  this.hibernateTemplate.find(queryString,p);
		return list.size()>0 ? true : false;
	}

}


text:
class SupplierDiversityLineObject < DataFactory

  include DateFactory
  include StringFactory
  include GlobalConfig

  attr_accessor   :line_number,
                  :type, :certification_expiration_date, :active

  def initialize(browser, opts={})
    @browser = browser

    defaults = {
      type:                          '::random::',
      certification_expiration_date: tomorrow[:date_w_slashes],
      active:                        :set
    }

    set_options(defaults.merge(opts))
  end

  def create
    on VendorPage do |vp|
      if !@type.nil? && @type.empty?
        vp.new_supplier_diversity_type.pick!                      ''
      else
        vp.new_supplier_diversity_type.pick!                      @type
        while @type.empty?
          # This will only happen when we try to pick a random one and it selects the
          # empty type. We want it to actually pick a valid one if we're going to add it.
          @type = '::random::'
          vp.new_supplier_diversity_type.pick!                    @type
        end
      end
      vp.new_supplier_diversity_active.fit                        @active
      vp.new_supplier_diversity_certification_expiration_date.fit @certification_expiration_date
      fill_out_extended_attributes
      vp.add_supplier_diversity
    end
  end

  def edit(opts={})
    raise ArgumentError, 'Supplier Diversity type cannot be updated!' unless opts[:type].nil?
    on(VendorPage).update_supplier_diversity_certification_expiration_date(@line_number).fit opts[:certification_expiration_date]
    on(VendorPage).update_supplier_diversity_active(@line_number).fit opts[:active]
    update_options(opts)
  end

  def delete
    raise NoMethodError, 'There is no way to delete a Supplier Diversity from a Vendor. Perhaps you have a site-specific extension?'
  end

  def fill_out_extended_attributes
    # Override this method if you have site-specific extended attributes.
  end

  def update_extended_attributes(opts = {})
    # Override this method if you have site-specific extended attributes.
  end
  alias_method :edit_extended_attributes, :update_extended_attributes

end

class SupplierDiversityLineObjectCollection < LineObjectCollection

  contains SupplierDiversityLineObject

  def update_from_page!(target=:new)
    on VendorPage do |lines|
      clear # Drop any cached lines. More reliable than sorting out an array merge.

      lines.expand_all
      unless lines.current_supplier_diversity_count.zero?
        (0..(lines.current_supplier_diversity_count - 1)).to_a.collect!{ |i|
          pull_existing_supplier_diversity(i, target).merge(pull_extended_existing_supplier_diversity(i, target))
        }.each { |new_obj|
          # Update the stored lines
          self << (make contained_class, new_obj)
        }
      end

    end
  end

  # @param [Fixnum] i The line number to look for (zero-based)
  # @param [Symbol] target Which supplier diversity to pull from (most useful during a copy action). Defaults to :new
  # @return [Hash] The return values of attributes for the given line
  def pull_existing_supplier_diversity(i=0, target=:new)
    pulled_supplier_diversity = Hash.new

    on VendorPage do |vp|
      case target
        when :old
          pulled_supplier_diversity = {
              type:                          vp.old_supplier_diversity_type(i),
              certification_expiration_date: vp.old_supplier_diversity_certification_expiration_date(i),
              active:                        yesno2setclear(vp.old_supplier_diversity_active(i))
          }
        when :new
          pulled_supplier_diversity = {
              type:                          vp.update_supplier_diversity_type(i).text.strip,
              certification_expiration_date: vp.update_supplier_diversity_certification_expiration_date(i).value.strip,
              active:                        yesno2setclear(vp.update_supplier_diversity_active(i).value.strip)
          }
      end
    end

    pulled_supplier_diversity
  end

  # @param [Fixnum] i The line number to look for (zero-based)
  # @param [Symbol] target Which supplier diversity to pull from (most useful during a copy action). Defaults to :new
  # @return [Hash] The return values of attributes for the given line
  def pull_extended_existing_supplier_diversity(i=0, target=:new)
    # This can be implemented for site-specific attributes. See the Hash returned in
    # the #collect! in #update_from_page! above for the kind of way to get the
    # right return value.
    Hash.new
  end

end


text:
Choicescript Tutorials

	Please note that all these links are external and point to tutorials that are not specifically related
	to the IDE but rather Choicescript as a whole.

		Official CoG Documentation

		Wiki Tutorial

		CS_Closet's Tutorial

		Reaperoa's Tutorial