text:
@interface CTRLBreakerViewCell ()

@property (nonatomic, strong) UIView *breakerView;
@property (nonatomic, readwrite) UILabel *nameLabel;
@property (nonatomic, readwrite) UILabel *amperageLabel;
@property (nonatomic, strong) UILabel *fixtureBadge;
@property (nonatomic, strong) UIView *onOffView;
@property (nonatomic, strong) UIView *flipSwitchView;
@property (nonatomic, strong) UILabel *onLabel;
@property (nonatomic, strong) UILabel *offLabel;
@property (nonatomic, strong) UIImageView *gfciImage;
@property (nonatomic, strong) UIView *breakerView2;
@property (nonatomic, readwrite) UILabel *nameLabel2;
@property (nonatomic, readwrite) UILabel *amperageLabel2;
@property (nonatomic, strong) UILabel *fixtureBadge2;
@property (nonatomic, strong) UIView *onOffView2;
@property (nonatomic, strong) UILabel *onLabel2;
@property (nonatomic, strong) UILabel *offLabel2;
@property (nonatomic, strong) UIImageView *gfciImage2;
@property (nonatomic, strong) UIView *seperatorLine2;

@end

@implementation CTRLBreakerViewCell

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    if (self) {
        [self initializeCell];
        [self setupCell];
    }

    return self;
}

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

    if (self) {
        [self initializeCell];
        [self setupCell];
    }

    return self;
}

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
//- (void)drawRect:(CGRect)rect
//{
//    // Drawing code
//}

- (void)initializeCell
{
    self.backgroundColor = [UIColor colorWithR:240 g:240 b:240];
    self.seperatorLine2 = [[UIView alloc] init];
    self.breakerView = [[UIView alloc] init];
    self.nameLabel = [[UILabel alloc] init];
    self.amperageLabel = [[UILabel alloc] init];
    self.fixtureBadge = [[UILabel alloc] init];
    self.flipSwitch = [[CTRLSwitch alloc] initWithFrame:CGRectZero];
    [self.flipSwitch addTarget:self action:@selector(switchChanged) forControlEvents:UIControlEventValueChanged];
    self.flipSwitchView = [[UIView alloc] init];
    self.onOffView = [[UIView alloc] init];
    self.onLabel = [[UILabel alloc] init];
    self.offLabel = [[UILabel alloc] init];
    self.gfciImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"breakerGFCI"]];
}

- (void)setupCell
{
    self.breakerView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    self.nameLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
    self.fixtureBadge.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
    self.amperageLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
    self.flipSwitchView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin| UIViewAutoresizingFlexibleRightMargin;
    self.onOffView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin| UIViewAutoresizingFlexibleLeftMargin;
    self.gfciImage.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;

    self.offLabel.font = [UIFont boldSystemFontOfSize:8];
    self.onLabel.font = [UIFont boldSystemFontOfSize:8];
    self.nameLabel.font = [UIFont boldSystemFontOfSize:12];
    self.amperageLabel.font = [UIFont boldSystemFontOfSize:10];

    UIColor *textColor = [UIColor colorWithR:169 g:169 b:169];
    self.onLabel.textColor = textColor;
    self.offLabel.textColor = textColor;
    self.nameLabel.textColor = textColor;

    self.fixtureBadge.textColor = [UIColor whiteColor];
    self.fixtureBadge.layer.cornerRadius = 25.0/2.0;

    self.onOffView.backgroundColor = [UIColor clearColor];
    self.breakerView.backgroundColor = self.backgroundColor;
    self.seperatorLine2.backgroundColor = textColor;
    self.nameLabel.backgroundColor = [UIColor whiteColor];
    self.amperageLabel.backgroundColor = [UIColor colorWithR:235 g:235 b:235];
    self.fixtureBadge.backgroundColor = [UIColor darkGrayColor];

    self.offLabel.textAlignment = NSTextAlignmentCenter;
    self.onLabel.textAlignment = NSTextAlignmentCenter;
    self.nameLabel.textAlignment = NSTextAlignmentCenter;
    self.amperageLabel.textAlignment = NSTextAlignmentCenter;
    self.fixtureBadge.textAlignment = NSTextAlignmentCenter;

    CGColorRef borderColor = [textColor CGColor];
    CGFloat borderWidth = 1.0;
    CGFloat borderRadius = 2.5;

    self.nameLabel.layer.borderColor = borderColor;
    self.nameLabel.layer.borderWidth = borderWidth;
    self.nameLabel.layer.cornerRadius = borderRadius;

    self.amperageLabel.layer.borderColor = borderColor;
    self.amperageLabel.layer.borderWidth = borderWidth;
    self.amperageLabel.layer.cornerRadius = borderRadius;

    self.onLabel.text = @"ON";
    self.offLabel.text = @"OFF";

    [self setFrames];

    [self.breakerView addSubview:self.nameLabel];
    [self.breakerView addSubview:self.amperageLabel];
    [self.onOffView addSubview:self.onLabel];
    [self.onOffView addSubview:self.offLabel];
    [self.breakerView addSubview:self.onOffView];
    [self.breakerView addSubview:self.gfciImage];
    [self.contentView addSubview:self.breakerView];
    [self.flipSwitchView addSubview:self.flipSwitch];
    [self.contentView addSubview:self.flipSwitchView];
    [self.contentView addSubview:self.fixtureBadge];
}

- (void)setFrames
{

    self.flipSwitch.transform = CGAffineTransformIdentity;
    self.breakerView.transform = CGAffineTransformIdentity;
    self.nameLabel.transform = CGAffineTransformIdentity;
    self.fixtureBadge.transform = CGAffineTransformIdentity;
    self.amperageLabel.transform = CGAffineTransformIdentity;
    self.offLabel.transform = CGAffineTransformIdentity;
    self.onLabel.transform = CGAffineTransformIdentity;
    self.gfciImage.transform = CGAffineTransformIdentity;

    self.flipSwitch.frame = CGRectMake(0,
                                       0,
                                       CGRectGetWidth(self.flipSwitch.frame),
                                       CGRectGetHeight(self.flipSwitch.frame));
    self.flipSwitchView.frame = self.flipSwitch.frame;

    CGRect breakerFrame = CGRectMake(0,
                                     0,
                                     CGRectGetWidth(self.contentView.bounds),
                                     CGRectGetHeight(self.contentView.bounds));

    if (self.cellStyle == CTRLBreakerCellStyleHorizontal) {
        if (CGRectGetWidth(breakerFrame) > 88) {
            breakerFrame.size.width = 88;
        }
    }
    else {
        if (CGRectGetHeight(breakerFrame) > 88) {
            breakerFrame.size.height = 88;
        }
    }

    self.breakerView.frame = breakerFrame;
    self.nameLabel.frame = CGRectMake(0, 0, 129, 31);
    self.amperageLabel.frame = CGRectMake(0, 0, 31, 18);
    self.fixtureBadge.frame = CGRectMake(0, 0, 25, 25);
    self.onOffView.frame = CGRectMake(0, 0, 85, CGRectGetHeight(breakerFrame));
    self.offLabel.frame = CGRectMake(0, 0, 25, 10);
    self.onLabel.frame = self.offLabel.frame;
    self.gfciImage.frame = CGRectMake(0, 0, CGRectGetWidth(self.gfciImage.frame), CGRectGetHeight(self.gfciImage.frame));

    if (self.cellStyle == CTRLBreakerCellStyleHorizontal) {
        self.gfciImage.transform = CGAffineTransformMakeRotation(M_PI_2);
        self.nameLabel.transform = CGAffineTransformMakeRotation(-M_PI_2);
        self.fixtureBadge.transform = CGAffineTransformMakeRotation(-M_PI_2);

        if (self.switchOrientation == SwitchOrientationRight) {
            [self setFrameOffsetsForLeftHorizontalOrientation];
        }
        else {
            [self setFrameOffsetsForRightHorizontalOrientation];
        }

    }
    else {
        self.offLabel.transform = CGAffineTransformMakeRotation(-M_PI_2);
        self.onLabel.transform = CGAffineTransformMakeRotation(-M_PI_2);
        self.amperageLabel.transform = CGAffineTransformMakeRotation(-M_PI_2);

        if (self.switchOrientation == SwitchOrientationLeft) {
            [self setFrameOffsetsForLeftVerticalOrientation];
        }
        else {
            [self setFrameOffsetsForRightVerticalOrientation];
        }
    }
}

- (void)setFrameOffsetsForLeftHorizontalOrientation
{
    self.flipSwitch.transform = CGAffineTransformMakeRotation(-M_PI_2);

    CGRect flipSwitchFrame = self.flipSwitch.frame;
    flipSwitchFrame.origin.x = 0;
    flipSwitchFrame.origin.y = 0;
    self.flipSwitch.frame = flipSwitchFrame;

    self.onLabel.frame = CGRectOffset(self.onLabel.frame, 0, 2);
    self.flipSwitch.frame = CGRectOffset(self.flipSwitch.frame, 0, CGRectGetMaxY(self.onLabel.frame)+4);
    self.offLabel.frame = CGRectOffset(self.offLabel.frame, 0, CGRectGetMaxY(self.flipSwitch.frame)+3);

    CGFloat amperageY = CGRectGetHeight(self.breakerView.frame)-CGRectGetHeight(self.amperageLabel.frame)-13;
    self.amperageLabel.frame = CGRectOffset(self.amperageLabel.frame, 0, amperageY);

    CGFloat nameY = CGRectGetMinY(self.amperageLabel.frame)-CGRectGetHeight(self.nameLabel.frame)-17.0;
    self.nameLabel.frame = CGRectMake(CGRectGetMinX(self.nameLabel.frame), nameY, CGRectGetWidth(self.nameLabel.frame), CGRectGetHeight(self.nameLabel.frame));

    CGFloat gfciY = CGRectGetMinY(self.nameLabel.frame)-CGRectGetHeight(self.gfciImage.frame)-2;
    self.gfciImage.frame = CGRectMake(CGRectGetMinX(self.gfciImage.frame),
                                      gfciY,
                                      CGRectGetWidth(self.gfciImage.frame),
                                      CGRectGetHeight(self.gfciImage.frame));

    CGPoint center = self.breakerView.center;
    CGPoint flipSwitchCenter = center;

    if (self.isDoubleCell) {
        flipSwitchCenter.x += 44.0;
    }
    self.onLabel.center = CGPointMake(center.x, self.onLabel.center.y);
    self.offLabel.center = CGPointMake(center.x, self.offLabel.center.y);

    self.nameLabel.center = CGPointMake(center.x, self.nameLabel.center.y);
    self.amperageLabel.center = CGPointMake(center.x, self.amperageLabel.center.y);
    self.flipSwitch.center = CGPointMake(flipSwitchCenter.x, self.flipSwitch.center.y);
    self.gfciImage.center = CGPointMake(center.x, self.gfciImage.center.y);
}

- (void)setFrameOffsetsForRightHorizontalOrientation
{
    self.flipSwitch.transform = CGAffineTransformMakeRotation(M_PI_2);
    self.onOffView.frame = CGRectOffset(self.onOffView.frame,
                                        CGRectGetMaxX(self.breakerView.frame)-CGRectGetWidth(self.onOffView.frame),
                                        0);

    CGFloat offLabelHeight = CGRectGetHeight(self.offLabel.frame);
    CGFloat flipSwitchHeight = CGRectGetHeight(self.flipSwitch.frame);

    self.onLabel.frame = CGRectOffset(self.onLabel.frame, 0, CGRectGetWidth(self.onOffView.frame)-2);
    self.flipSwitch.frame = CGRectMake(0,
                                       CGRectGetMinY(self.onLabel.frame)-flipSwitchHeight-4 ,
                                       CGRectGetWidth(self.flipSwitch.frame), CGRectGetHeight(self.flipSwitch.frame));
    self.offLabel.frame = CGRectOffset(self.offLabel.frame, 0, CGRectGetMinY(self.flipSwitch.frame)-offLabelHeight-2);

    CGFloat amperageY = 13;
    self.amperageLabel.frame = CGRectOffset(self.amperageLabel.frame, 0, amperageY);

    CGFloat nameY = CGRectGetMaxY(self.amperageLabel.frame)+17.0;
    self.nameLabel.frame = CGRectMake(CGRectGetMinX(self.nameLabel.frame), nameY, CGRectGetWidth(self.nameLabel.frame), CGRectGetHeight(self.nameLabel.frame));

    CGFloat gfciY = CGRectGetMaxY(self.nameLabel.frame)+2;
    self.gfciImage.frame = CGRectMake(CGRectGetMinX(self.gfciImage.frame),
                                      gfciY,
                                      CGRectGetWidth(self.gfciImage.frame),
                                      CGRectGetHeight(self.gfciImage.frame));

    CGPoint center = self.breakerView.center;

    CGPoint flipSwitchCenter = center;

    if (self.isDoubleCell) {
        flipSwitchCenter.x += 44.0;
    }

    self.onLabel.center = CGPointMake(center.x, self.onLabel.center.y);
    self.offLabel.center = CGPointMake(center.x, self.offLabel.center.y);

    self.nameLabel.center = CGPointMake(center.x, self.nameLabel.center.y);
    self.amperageLabel.center = CGPointMake(center.x, self.amperageLabel.center.y);
    self.flipSwitch.center = CGPointMake(flipSwitchCenter.x, self.flipSwitch.center.y);
    self.gfciImage.center = CGPointMake(center.x, self.gfciImage.center.y);
}

- (void)setFrameOffsetsForLeftVerticalOrientation
{
    self.flipSwitchView.autoresizingMask = (self.flipSwitchView.autoresizingMask^UIViewAutoresizingFlexibleLeftMargin)| UIViewAutoresizingFlexibleRightMargin;
    self.onOffView.autoresizingMask = (self.onOffView.autoresizingMask^UIViewAutoresizingFlexibleLeftMargin)| UIViewAutoresizingFlexibleRightMargin;

    self.onOffView.frame = CGRectMake(0, 0, CGRectGetWidth(self.onOffView.frame), CGRectGetHeight(self.onOffView.frame));

    self.flipSwitch.transform = CGAffineTransformMakeScale(-1, 1);
    self.flipSwitch.frame = CGRectMake(0, 0, CGRectGetWidth(self.flipSwitch.frame), CGRectGetHeight(self.flipSwitch.frame));

    self.onLabel.frame = CGRectMake(0, 0, CGRectGetWidth(self.onLabel.frame), CGRectGetHeight(self.onLabel.frame));
    self.onLabel.frame = CGRectOffset(self.onLabel.frame, 2, 0);
    self.offLabel.frame = CGRectMake(0, 0, CGRectGetWidth(self.offLabel.frame), CGRectGetHeight(self.offLabel.frame));
    self.offLabel.frame = CGRectOffset(self.offLabel.frame, CGRectGetMaxX(self.onOffView.bounds)-CGRectGetWidth(self.offLabel.frame), 0);
    self.flipSwitchView.frame = CGRectOffset(self.flipSwitch.frame,
                                         CGRectGetMidX(self.onOffView.frame)-CGRectGetWidth(self.flipSwitch.frame)/2,
                                         0);

    CGFloat amperageX = CGRectGetWidth(self.breakerView.frame)-CGRectGetWidth(self.amperageLabel.frame)-16;
    self.amperageLabel.frame = CGRectOffset(self.amperageLabel.frame,amperageX,0);

    CGFloat nameX = CGRectGetMinX(self.amperageLabel.frame)-CGRectGetWidth(self.nameLabel.frame)-17.0;
    self.nameLabel.frame = CGRectOffset(self.nameLabel.frame, nameX, 0);

    self.fixtureBadge.frame = CGRectOffset(self.fixtureBadge.frame, CGRectGetMaxX(self.nameLabel.frame)-CGRectGetWidth(self.fixtureBadge.frame)-3, 0);

    CGFloat gfciX = CGRectGetMinX(self.nameLabel.frame)-CGRectGetWidth(self.gfciImage.frame)-2;
    self.gfciImage.frame = CGRectMake(gfciX,
                                      CGRectGetMinY(self.gfciImage.frame),
                                      CGRectGetWidth(self.gfciImage.frame),
                                      CGRectGetHeight(self.gfciImage.frame));

    CGPoint center = self.breakerView.center;
    CGPoint flipSwitchCenter = center;

    if (self.isDoubleCell) {
        flipSwitchCenter.y += 44.0;
    }

    self.onLabel.center = CGPointMake(self.onLabel.center.x, center.y);
    self.offLabel.center = CGPointMake(self.offLabel.center.x, center.y);

    self.nameLabel.center = CGPointMake(self.nameLabel.center.x, center.y);
    self.fixtureBadge.center = CGPointMake(self.fixtureBadge.center.x, center.y);
    self.amperageLabel.center = CGPointMake(self.amperageLabel.center.x, center.y);
    self.flipSwitchView.center = CGPointMake(self.flipSwitchView.center.x, flipSwitchCenter.y);
    self.gfciImage.center = CGPointMake(self.gfciImage.center.x, center.y);

}

- (void)setFrameOffsetsForRightVerticalOrientation
{
    self.flipSwitchView.autoresizingMask = (self.flipSwitchView.autoresizingMask^UIViewAutoresizingFlexibleRightMargin)| UIViewAutoresizingFlexibleLeftMargin;
    self.onOffView.autoresizingMask = (self.onOffView.autoresizingMask^UIViewAutoresizingFlexibleRightMargin)| UIViewAutoresizingFlexibleLeftMargin;

    self.onOffView.frame = CGRectOffset(self.onOffView.frame,
                                        CGRectGetMaxX(self.breakerView.frame)-CGRectGetWidth(self.onOffView.frame),
                                        0);

    CGFloat onLabelWidth = CGRectGetWidth(self.onLabel.frame); //Height/Width switched because its flipped

    self.onLabel.frame = CGRectMake(CGRectGetMaxX(self.onOffView.bounds)-onLabelWidth-2, 0, CGRectGetWidth(self.onLabel.frame), CGRectGetHeight(self.onLabel.frame));
    self.offLabel.frame = CGRectMake(0, 0, CGRectGetWidth(self.offLabel.frame), CGRectGetHeight(self.offLabel.frame));
    self.flipSwitchView.frame = CGRectOffset(self.flipSwitch.frame, CGRectGetMidX(self.onOffView.frame)-CGRectGetWidth(self.flipSwitch.frame)/2, 0.0);

    CGFloat amperageX = 5;
    self.amperageLabel.frame = CGRectOffset(self.amperageLabel.frame,amperageX,0);

    CGFloat nameX = CGRectGetMaxX(self.amperageLabel.frame)+17.0;
    self.nameLabel.frame = CGRectOffset(self.nameLabel.frame, nameX, 0);

    self.fixtureBadge.frame = CGRectOffset(self.fixtureBadge.frame, CGRectGetMinX(self.nameLabel.frame)+3, 0);

    CGFloat gfciX = CGRectGetMaxX(self.nameLabel.frame)+3;
    self.gfciImage.frame = CGRectMake(gfciX,
                                      CGRectGetMinY(self.gfciImage.frame),
                                      CGRectGetWidth(self.gfciImage.frame),
                                      CGRectGetHeight(self.gfciImage.frame));

    CGPoint center = self.breakerView.center;
    CGPoint flipSwitchCenter = center;

    if (self.isDoubleCell) {
        flipSwitchCenter.y += 44.0;
    }

    self.onLabel.center = CGPointMake(self.onLabel.center.x, center.y);
    self.offLabel.center = CGPointMake(self.offLabel.center.x, center.y);

    self.nameLabel.center = CGPointMake(self.nameLabel.center.x, center.y);
    self.fixtureBadge.center = CGPointMake(self.fixtureBadge.center.x, center.y);
    self.amperageLabel.center = CGPointMake(self.amperageLabel.center.x, center.y);
    self.flipSwitchView.center = CGPointMake(self.flipSwitchView.center.x, flipSwitchCenter.y);
    self.gfciImage.center = CGPointMake(self.gfciImage.center.x, center.y);
}

//#pragma mark - Getters
//
//- (BOOL)isEditing
//{
//    return _editing;
//}

#pragma mark - Setters

- (void)setGfci:(BOOL)gfci
{
    _gfci = gfci;

    if (gfci) {
        self.gfciImage.hidden = NO;
    }
    else {
        self.gfciImage.hidden = YES;
    }
}

//TODO: refactor - maybe an enum of accessory type or something
- (void)setTandem:(BOOL)tandem
{
    _tandem = tandem;

    CGRect frame = self.flipSwitch.frame;
    CGAffineTransform transfrom = self.flipSwitch.transform;

    [self.flipSwitch removeFromSuperview];
    BOOL wasOn = self.flipSwitch.on;

    if (tandem) {
        //Casting to a UISwitch is kind of sloppy
        self.flipSwitch = (CTRLSwitch *)[[CTRLTandemSwitch alloc] initWithFrame:frame];
        self.flipSwitch.transform = transfrom;
        self.flipSwitch.tintColor = self.tintColor;
        self.flipSwitch.onTintColor = self.tintColor;
        self.flipSwitch.on = wasOn;
    }
    else {
        if (self.isDoublePole) {
            self.flipSwitch = (CTRLSwitch *)[[CTRLDoublePoleSwitch alloc] initWithFrame:frame];
            self.flipSwitch.transform = transfrom;
            self.flipSwitch.tintColor = self.tintColor;
            self.flipSwitch.onTintColor = self.tintColor;
            self.flipSwitch.on = wasOn;
        }
        else {
            self.flipSwitch = [[CTRLSwitch alloc] initWithFrame:frame];
            self.flipSwitch.transform = transfrom;
            self.flipSwitch.tintColor = self.tintColor;
            self.flipSwitch.onTintColor = self.tintColor;
            self.flipSwitch.on = wasOn;
        }
    }

    [self.flipSwitch addTarget:self action:@selector(switchChanged) forControlEvents:UIControlEventValueChanged];

    [self.flipSwitchView addSubview:self.flipSwitch];
}

- (void)setDoublePole:(BOOL)doublePole
{
    _doublePole = doublePole;

    CGRect frame = self.flipSwitch.frame;
    CGAffineTransform transfrom = self.flipSwitch.transform;

    [self.flipSwitch removeFromSuperview];
    BOOL wasOn = self.flipSwitch.on;

    if (doublePole || self.doubleCell) {
        //Casting to a UISwitch is kind of sloppy
        if (!self.doubleCell) {
            frame.size.height = 79;
        }
        else {
            frame.size.height = 122;
        }
        self.flipSwitch = (CTRLSwitch *)[[CTRLDoublePoleSwitch alloc] initWithFrame:frame];
        self.flipSwitch.transform = transfrom;
        self.flipSwitch.tintColor = self.tintColor;
        self.flipSwitch.onTintColor = self.tintColor;
        self.flipSwitch.on = wasOn;
    }
    else {
        if (self.isTandem) {
            self.flipSwitch = (CTRLSwitch *)[[CTRLTandemSwitch alloc] initWithFrame:frame];
            self.flipSwitch.transform = transfrom;
            self.flipSwitch.tintColor = self.tintColor;
            self.flipSwitch.onTintColor = self.tintColor;
            self.flipSwitch.on = wasOn;
        }
        else {
            self.flipSwitch = [[CTRLSwitch alloc] initWithFrame:frame];
            self.flipSwitch.transform = transfrom;
            self.flipSwitch.tintColor = self.tintColor;
            self.flipSwitch.onTintColor = self.tintColor;
            self.flipSwitch.on = wasOn;
        }
    }

    [self.flipSwitch addTarget:self action:@selector(switchChanged) forControlEvents:UIControlEventValueChanged];
    [self.flipSwitchView addSubview:self.flipSwitch];
}

- (void)setCellStyle:(CTRLBreakerCellStyle)cellStyle
{
    _cellStyle = cellStyle;

    [self setNeedsLayout];
}
//- (void)setEditing:(BOOL)editing
//{
//    [self setEditing:editing animated:NO];
//}
//
//- (void)setEditing:(BOOL)editing animated:(BOOL)animated
//{
//    if (_editing == editing)
//        return;
//
//    [self willChangeValueForKey:@"editing"];
//    _editing = editing;
//    [self didChangeValueForKey:@"editing"];
//
//    void (^editAnimationBlock)();
//    void (^editAnimationCompletionBlock)(BOOL);
//    if (editing) {
//
//        self.deleteButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
//        self.deleteButton.center = CGPointMake(30, self.breakerScrollView.center.y);
//        self.deleteButton.alpha = 0.0;
//        [self.deleteButton addTarget:self action:@selector(deleteButtonTapped) forControlEvents:UIControlEventTouchUpInside];
//
//        [self.contentView addSubview:self.deleteButton];
//
//        editAnimationBlock = ^(){
//            self.deleteButton.alpha = 1.0;
//            self.breakerContentView.frame = CGRectMake(60,
//                                                       0,
//                                                       CGRectGetWidth(self.breakerContentView.frame),
//                                                       CGRectGetHeight(self.breakerContentView.frame));
//        };
//        editAnimationCompletionBlock = ^(BOOL completed){};
//    }
//    else {
//        editAnimationBlock = ^(){
//            self.breakerContentView.frame = CGRectMake(0,
//                                                       0,
//                                                       CGRectGetWidth(self.breakerContentView.frame),
//                                                       CGRectGetHeight(self.breakerContentView.frame));
//            self.breakerScrollView.contentOffset = CGPointZero;
//            self.deleteButton.alpha = 0.0;
//        };
//        editAnimationCompletionBlock = ^(BOOL completed){
//            [self.deleteButton removeFromSuperview];
//            [self.deleteConfirmationButton removeFromSuperview];
//            self.breakerScrollView.userInteractionEnabled = NO;
//            self.breakerScrollView.scrollEnabled = NO;
//        };
//    }
//
//    if (animated) {
//        [UIView animateWithDuration:.3 animations:editAnimationBlock completion:editAnimationCompletionBlock];
//    }
//    else {
//        editAnimationBlock();
//        editAnimationCompletionBlock(YES);
//    }
//
//}

- (void)setSwitchOrientation:(SwitchOrientation)switchOrientation
{
    _switchOrientation = switchOrientation;

    [self setFrames];
}

- (void)setDoubleCell:(BOOL)doubleCell
{
    _doubleCell = doubleCell;

    if (doubleCell) {
        self.breakerView.autoresizingMask = self.breakerView.autoresizingMask^UIViewAutoresizingFlexibleHeight;

        CGRect breakerFrame = self.breakerView.frame;
        breakerFrame.size.height = 88;
        self.breakerView.frame = breakerFrame;

        CGRect flipSwitchFrame = self.flipSwitch.frame;
        flipSwitchFrame.size.height = 122;

        CGAffineTransform transform = self.flipSwitch.transform;
        UIColor *onColor = self.flipSwitch.onTintColor;
        UIColor *tintColor = self.flipSwitch.tintColor;
        BOOL isOn = self.flipSwitch.isOn;

        [self.flipSwitch removeFromSuperview];

        self.flipSwitch = (CTRLSwitch *)[[CTRLDoublePoleSwitch alloc] initWithFrame:flipSwitchFrame];
        self.flipSwitch.transform = transform;
        self.flipSwitch.tintColor = tintColor;
        self.flipSwitch.onTintColor = onColor;
        self.flipSwitch.on = isOn;
        [self.flipSwitch addTarget:self action:@selector(switchChanged) forControlEvents:UIControlEventValueChanged];
        [self.flipSwitchView addSubview:self.flipSwitch];
        self.flipSwitchView.frame = CGRectOffset(self.flipSwitchView.frame, 0, 2);

        [self.breakerView2 removeFromSuperview];
        self.breakerView2 = [self copyBreakerView];
        self.breakerView2.frame = CGRectOffset(self.breakerView2.frame, 0, breakerFrame.size.height);

        self.seperatorLine2.frame = CGRectMake(0,
                                               CGRectGetMaxY(self.breakerView.frame)-1,
                                               CGRectGetWidth(self.contentView.bounds),
                                               .5);

        [self.contentView addSubview:self.breakerView2];
        [self.contentView addSubview:self.seperatorLine2];
        [self.contentView bringSubviewToFront:self.flipSwitchView];
    }
    else {
        [self.breakerView2 removeFromSuperview];
        self.tandem = self.isTandem;
        self.doublePole = self.isDoublePole;
    }
}

- (UIView *)copyBreakerView
{
    UIView *breakerViewCopy = [[UIView alloc] initWithFrame:self.breakerView.frame];
    breakerViewCopy.backgroundColor = self.breakerView.backgroundColor;
    breakerViewCopy.autoresizingMask = self.breakerView.autoresizingMask;

    self.onLabel2 = [[UILabel alloc] initWithFrame:CGRectZero];
    self.onLabel2.autoresizingMask = self.onLabel.autoresizingMask;
    self.onLabel2.backgroundColor = self.onLabel2.backgroundColor;
    self.onLabel2.font = self.onLabel.font;
    self.onLabel2.textColor = self.onLabel.textColor;
    self.onLabel2.textAlignment = self.onLabel.textAlignment;
    self.onLabel2.text = self.onLabel.text;
    self.onLabel2.transform = self.onLabel.transform;
    self.onLabel2.frame = self.onLabel.frame;

    self.offLabel2 = [[UILabel alloc] initWithFrame:CGRectZero];
    self.offLabel2.autoresizingMask = self.offLabel.autoresizingMask;
    self.offLabel2.backgroundColor = self.offLabel.backgroundColor;
    self.offLabel2.font = self.offLabel.font;
    self.offLabel2.textColor = self.offLabel.textColor;
    self.offLabel2.textAlignment = self.offLabel.textAlignment;
    self.offLabel2.text = self.offLabel.text;
    self.offLabel2.transform = self.offLabel.transform;
    self.offLabel2.frame = self.offLabel.frame;

    self.onOffView2 = [[UIView alloc] initWithFrame:self.onOffView.frame];
    self.onOffView2.backgroundColor = self.onOffView2.backgroundColor;
    self.onOffView2.autoresizingMask = self.onOffView2.autoresizingMask;

    self.nameLabel2 = [[UILabel alloc] initWithFrame:CGRectZero];
    self.nameLabel2.autoresizingMask = self.nameLabel.autoresizingMask;
    self.nameLabel2.backgroundColor = self.nameLabel.backgroundColor;
    self.nameLabel2.font = self.nameLabel.font;
    self.nameLabel2.textColor = self.nameLabel.textColor;
    self.nameLabel2.textAlignment = self.nameLabel.textAlignment;
    self.nameLabel2.text = self.nameLabel.text;
    self.nameLabel2.transform = self.nameLabel.transform;
    self.nameLabel2.frame = self.nameLabel.frame;
    self.nameLabel2.layer.borderColor = self.nameLabel.layer.borderColor;
    self.nameLabel2.layer.borderWidth = self.nameLabel.layer.borderWidth;
    self.nameLabel2.layer.cornerRadius = self.nameLabel.layer.cornerRadius;

    self.amperageLabel2 = [[UILabel alloc] initWithFrame:CGRectZero];
    self.amperageLabel2.autoresizingMask = self.amperageLabel.autoresizingMask;
    self.amperageLabel2.backgroundColor = self.amperageLabel.backgroundColor;
    self.amperageLabel2.font = self.amperageLabel.font;
    self.amperageLabel2.textColor = self.amperageLabel.textColor;
    self.amperageLabel2.textAlignment = self.amperageLabel.textAlignment;
    self.amperageLabel2.text = self.amperageLabel.text;
    self.amperageLabel2.transform = self.amperageLabel.transform;
    self.amperageLabel2.frame = self.amperageLabel.frame;
    self.amperageLabel2.layer.borderColor = self.amperageLabel.layer.borderColor;
    self.amperageLabel2.layer.borderWidth = self.amperageLabel.layer.borderWidth;
    self.amperageLabel2.layer.cornerRadius = self.amperageLabel.layer.cornerRadius;

    [self.onOffView2 addSubview:self.onLabel2];
    [self.onOffView2 addSubview:self.offLabel2];
    [breakerViewCopy addSubview:self.onOffView2];
    [breakerViewCopy addSubview:self.amperageLabel2];
    [breakerViewCopy addSubview:self.nameLabel2];

    return breakerViewCopy;
}

- (void)prepareForReuse
{
    [super prepareForReuse];
    [self setFrames];
}

#pragma mark - Actions

- (void)switchChanged
{
    if ([self.delegate respondsToSelector:@selector(breakerViewCell:didDetectSwitchChangeButtonTap:)])
    {
        [self.delegate breakerViewCell:self didDetectSwitchChangeButtonTap:self.flipSwitch];
    }
}

@end


text:
unicodedata2
============

unicodedata backport/updates to python 2.

The versions of this package match unicode versions, so unicodedata2==7.0.0 is data from unicode 7.0.0.
Additionally this backports support for named aliases and named sequences to python2.

redpajama_set_name: RedPajamaGithub


text:
<!DOCTYPE html>

        <meta name="viewport" content="width=800" />
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">

                        Denomination
                        Number
                        Total

                        0.05x
                        <input data-ng-model="employee.nickelCount" data-ng-change="employee.nickelTotal=(employee.nickelCount * 5) / 100.0" type="number">
                        <input data-ng-model="employee.nickelTotal" data-ng-change="employee.nickelCount=employee.nickelTotal / 0.05" type="number">

                        0.10x
                        <input data-ng-model="employee.dimeCount" data-ng-change="employee.dimeTotal=(employee.dimeCount * 10) / 100.0" type="number">
                        <input data-ng-model="employee.dimeTotal" data-ng-change="employee.dimeCount=employee.dimeTotal / 0.10" type="number">

                        0.25x
                        <input data-ng-model="employee.quarterCount" data-ng-change="employee.quarterTotal=(employee.quarterCount * 25) / 100.0" type="number">
                        <input data-ng-model="employee.quarterTotal" data-ng-change="employee.quarterCount=employee.quarterTotal / 0.25" type="number">

                        1.00x
                        <input data-ng-model="employee.loonieCount" data-ng-change="employee.loonieTotal=employee.loonieCount" type="number">
                        <input data-ng-model="employee.loonieTotal" data-ng-change="employee.loonieCount=employee.loonieTotal" type="number">

                        2.00x
                        <input data-ng-model="employee.toonieCount" data-ng-change="employee.toonieTotal=(employee.toonieCount * 200) / 100.0" type="number">
                        <input data-ng-model="employee.toonieTotal" data-ng-change="employee.toonieCount=employee.toonieTotal / 2" type="number">

                        5.00x
                        <input data-ng-model="employee.fiveCount" data-ng-change="employee.fiveTotal=(employee.fiveCount * 500) / 100.0" type="number">
                        <input data-ng-model="employee.fiveTotal" data-ng-change="employee.fiveCount=employee.fiveTotal / 5" type="number">

                        10.00x
                        <input data-ng-model="employee.tenCount" data-ng-change="employee.tenTotal=(employee.tenCount * 1000) / 100.0" type="number">
                        <input data-ng-model="employee.tenTotal" data-ng-change="employee.tenCount=employee.tenTotal / 5" type="number">

                        20.00x
                        <input data-ng-model="employee.twentyCount" data-ng-change="employee.twentyTotal=(employee.twentyCount * 2000) / 100.0" type="number">
                        <input data-ng-model="employee.twentyTotal" data-ng-change="employee.twentyCount=employee.twentyTotal / 20" type="number">

                        50.00x
                        <input data-ng-model="employee.fiftyCount" data-ng-change="employee.fiftyTotal=(employee.fiftyCount * 5000) / 100.0" type="number">
                        <input data-ng-model="employee.fiftyTotal" data-ng-change="employee.fiftyCount=employee.fiftyTotal / 50" type="number">

                        100.00x
                        <input data-ng-model="employee.hundredCount" data-ng-change="employee.hundredTotal=(employee.hundredCount * 10000) / 100.0" type="number">
                        <input data-ng-model="employee.hundredTotal" data-ng-change="employee.hundredCount=employee.hundredTotal / 100" type="number">

                        Rolled 0.05x
                        <input data-ng-model="employee.rolledNickelCount" data-ng-change="employee.rolledNickelTotal=(employee.rolledNickelCount * 200) / 100.0" type="number">
                        <input data-ng-model="employee.rolledNickelTotal" data-ng-change="employee.rolledNickelCount=employee.rolledNickelTotal / 2" type="number">

                        Rolled 0.10x
                        <input data-ng-model="employee.rolledDimeCount" data-ng-change="employee.rolledDimeTotal=(employee.rolledDimeCount * 500) / 100.0" type="number">
                        <input data-ng-model="employee.rolledDimeTotal" data-ng-change="employee.rolledDimeCount=employee.rolledDimeTotal / 5" type="number">

                        Rolled 0.25x
                        <input data-ng-model="employee.rolledQuarterCount" data-ng-change="employee.rolledQuarterTotal=(employee.rolledQuarterCount * 1000) / 100.0" type="number">
                        <input data-ng-model="employee.rolledQuarterTotal" data-ng-change="employee.rolledQuarterCount=employee.rolledQuarterTotal / 10" type="number">

                        Rolled 1.00x
                        <input data-ng-model="employee.rolledLoonieCount" data-ng-change="employee.rolledLoonieTotal=(employee.rolledLoonieCount * 2500) / 100.0" type="number">
                        <input data-ng-model="employee.rolledLoonieTotal" data-ng-change="employee.rolledLoonieCount=employee.rolledLoonieTotal / 25" type="number">

                        Rolled 2.00x
                        <input data-ng-model="employee.rolledToonieCount" data-ng-change="employee.rolledToonieTotal=(employee.rolledToonieCount * 5000) / 100.0" type="number">
                        <input data-ng-model="employee.rolledToonieTotal" data-ng-change="employee.rolledToonieCount=employee.rolledToonieTotal / 50" type="number">

                        Sub Total
                        {{ employee.rolledDimeTotal + employee.rolledNickelTotal + employee.rolledQuarterTotal +
                            employee.rolledLoonieTotal + employee.rolledToonieTotal + employee.nickelTotal + employee.dimeTotal +
                            employee.quarterTotal + employee.loonieTotal + employee.toonieTotal + employee.fiveTotal + employee.tenTotal +
                            employee.twentyTotal + employee.fiftyTotal + employee.hundredTotal
                            | currency:'$' }}

                        VLT Tickets
                        <input data-ng-model="employee.vltTotal" type="number" />

                        Interac
                        <input data-ng-model="employee.interacTotal" type="number" />

                        Tabs
                        <input data-ng-model="employee.tabsTotal" type="number" />

                        Receipts
                        <input data-ng-model="employee.receiptsTotal" type="number" />

                        Sub Total
                        {{ employee.vltTotal + employee.interacTotal + employee.tabsTotal + employee.receiptsTotal | currency:'$' }}

                        Over All Total
                        {{ employee.vltTotal + employee.interacTotal + employee.tabsTotal + employee.receiptsTotal +
                            employee.rolledDimeTotal + employee.rolledNickelTotal + employee.rolledQuarterTotal +
                            employee.rolledLoonieTotal + employee.rolledToonieTotal + employee.nickelTotal + employee.dimeTotal +
                            employee.quarterTotal + employee.loonieTotal + employee.toonieTotal + employee.fiveTotal + employee.tenTotal +
                            employee.twentyTotal + employee.fiftyTotal + employee.hundredTotal | currency:'$' }}

                        Subtract Float
                        {{ 250 | currency:'$' }}

                        Total
                        {{ (employee.vltTotal + employee.interacTotal + employee.tabsTotal + employee.receiptsTotal +
                            employee.rolledDimeTotal + employee.rolledNickelTotal + employee.rolledQuarterTotal +
                            employee.rolledLoonieTotal + employee.rolledToonieTotal + employee.nickelTotal + employee.dimeTotal +
                            employee.quarterTotal + employee.loonieTotal + employee.toonieTotal + employee.fiveTotal + employee.tenTotal +
                            employee.twentyTotal + employee.fiftyTotal + employee.hundredTotal) - 250 | currency:'$' }}

                        Tape Total
                        <input data-ng-model="employee.tapeTotal" type="number" />

                        Over / Short
                        {{ ((employee.vltTotal + employee.interacTotal + employee.tabsTotal + employee.receiptsTotal +
                            employee.rolledDimeTotal + employee.rolledNickelTotal + employee.rolledQuarterTotal +
                            employee.rolledLoonieTotal + employee.rolledToonieTotal + employee.nickelTotal + employee.dimeTotal +
                            employee.quarterTotal + employee.loonieTotal + employee.toonieTotal + employee.fiveTotal + employee.tenTotal +
                            employee.twentyTotal + employee.fiftyTotal + employee.hundredTotal) - 250) - employee.tapeTotal | currency:'$' }}


text:
from __future__ import print_function
from setuptools import setup
import codecs
import os
import re

here = os.path.abspath(os.path.dirname(__file__))

def read(*parts):
    # intentionally *not* adding an encoding option to open
    return codecs.open(os.path.join(here, *parts), 'r').read()

def find_version(*file_paths):
    version_file = read(*file_paths)
    version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
                              version_file, re.M)
    if version_match:
        return version_match.group(1)
    raise RuntimeError("Unable to find version string.")

long_description = read('README.md')

# Hack to avoid specifying requirements in two places, see:
# http://stackoverflow.com/questions/14399534/how-can-i-reference-requirements-txt-for-the-install-requires-kwarg-in-setuptool
requirements_file = os.path.join(os.path.dirname(__file__), "requirements.txt")
with open(requirements_file) as f:
    all_reqs = f.read().splitlines()
required = [x for x in all_reqs if not x.startswith("git+")]
setup(
    name='biorest',
    version=find_version('biorest', '__init__.py'),
    url='http://github.com/genepeeks/biorest/',
    license='MIT License',
    author='GenePeeks, Inc.',
    author_email='developers@genepeeks.com',
    description='Collection of Python REST clients for several Bio APIs',
    long_description=long_description,
    install_requires=required,
    packages=['biorest', ],
    platforms='any',
    classifiers=[
        'Programming Language :: Python',
        'Development Status :: 4 - Beta',
        'Natural Language :: English',
        'Environment :: Web Environment',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Operating System :: OS Independent',
        'Topic :: Software Development :: Libraries :: Python Modules',
        'Topic :: Internet :: WWW/HTTP',
        ],
)


text:
'use strict';

var gulp = require('gulp'),
  browserSync = require('browser-sync'),
  nodemon = require('gulp-nodemon'),
  watch = require('gulp-watch'),
  concat = require('gulp-concat-util');

gulp.task('copy', function() {
  gulp.src(['app/**/*.js'])
    .pipe(concat.scripts('stuff.js'))
    .pipe(gulp.dest('dist'));

  gulp.src(['app/**/*.html'])
    .pipe(gulp.dest('dist'));

  gulp.src(['app/**/*.css'])
    .pipe(gulp.dest('dist'));
});

gulp.task('default', ['copy', 'browser-sync'], function () {
  watch(['app/**/*.(js|html|css)'], function (cb){
    gulp.start('copy');
  })
});

gulp.task('browser-sync', ['nodemon'], function() {
	browserSync.init(null, {
    proxy: "http://localhost:5000",
    browser: "google-chrome",
    files: ["dist/*.*"],
    port: 7000
	});
});

gulp.task('nodemon', function (cb) {

	var started = false;

	return nodemon({
    verbose: true,
    ignore: ["dist/*"],
		script: './server.js'
	}).on('start', function () {
		// to avoid nodemon being started multiple times
		// thanks @matthisk
		if (!started) {
			cb();
			started = true;
		}
	});
});


text:
//
//  GDataFeedMapVersion.m
//

#if !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_MAPS_SERVICE

#import "GDataFeedMapVersion.h"
#import "GDataMapConstants.h"
#import "GDataEntryMapVersion.h"

@implementation GDataFeedMapVersion

+ (GDataFeedMapVersion *)versionFeed {

  GDataFeedMapVersion *feed = [self object];

  [feed setNamespaces:[GDataMapConstants mapsNamespaces]];

  return feed;
}

+ (NSString *)standardFeedKind {
  return kGDataCategoryMapVersion;
}

+ (void)load {
  [self registerFeedClass];
}

+ (NSString *)defaultServiceVersion {
  return kGDataMapsDefaultServiceVersion;
}

- (Class)classForEntries {
  return [GDataEntryMapVersion class];
}

@end

#endif // !GDATA_REQUIRE_SERVICE_INCLUDES || GDATA_INCLUDE_MAPS_SERVICE


text:
using System;
using System.Text;
using System.Security.Permissions;
using System.Runtime.Serialization;
using OpenADK.Library;
using OpenADK.Library.Global;
using OpenADK.Library.us.Common;

namespace OpenADK.Library.us.Gradebook{

/// <summary>Indicates whether a percent Mark is accepted (format ##0.00).</summary>
/// <remarks>
///
/// <para>Author: Generated by adkgen</para>
/// <para>Version: 2.6</para>
/// <para>Since: 2.0</para>
/// </remarks>
[Serializable]
public class Percentage : SifElement
{
	/// <summary>
	/// Creates an instance of a Percentage
	/// </summary>
	public Percentage() : base ( GradebookDTD.PERCENTAGE ){}

	/// <summary>
	/// Constructor used by the .Net Serialization formatter
	/// </summary>
	[SecurityPermission( SecurityAction.Demand, SerializationFormatter=true )]
	protected Percentage( SerializationInfo info, StreamingContext context ) : base( info, context ) {}
	/// <summary>
	/// Gets or sets the value of the <c>IsAccepted</c> attribute.
	/// </summary>
	/// <value> The <c>IsAccepted</c> attribute of this object.</value>
	/// <remarks>
	/// <para>The SIF specification defines the meaning of this attribute as: "Indicates whether a percent Mark is accepted and is used in Change events to unambiguously signal whether support for the Mark has changed, especially ended."</para>
	/// <para>Version: 2.6</para>
	/// <para>Since: 2.0</para>
	/// </remarks>
	public bool? IsAccepted
	{
		get
		{
			return (bool?) GetSifSimpleFieldValue( GradebookDTD.PERCENTAGE_ISACCEPTED ) ;
		}
		set
		{
			SetFieldValue( GradebookDTD.PERCENTAGE_ISACCEPTED, new SifBoolean( value ), value );
		}
	}

	/// <summary>
	/// Gets or sets the value of the <c><Minimum></c> element.
	/// </summary>
	/// <value> The <c>Minimum</c> element of this object.</value>
	/// <remarks>
	/// <para>The SIF specification defines the meaning of this element as: "The minimum percent value accepted for this mark. If present, the publisher of this object is required to ensure that any values present in the StudentSectionMarks object will not be lower than this value."</para>
	/// <para>Version: 2.6</para>
	/// <para>Since: 2.0</para>
	/// </remarks>
	public decimal? Minimum
	{
		get
		{
			return (decimal?) GetSifSimpleFieldValue( GradebookDTD.PERCENTAGE_MINIMUM ) ;
		}
		set
		{
			SetFieldValue( GradebookDTD.PERCENTAGE_MINIMUM, new SifDecimal( value ), value );
		}
	}

	/// <summary>
	/// Gets or sets the value of the <c><Maximum></c> element.
	/// </summary>
	/// <value> The <c>Maximum</c> element of this object.</value>
	/// <remarks>
	/// <para>The SIF specification defines the meaning of this element as: "The maximum percent value accepted for this mark. If present, the publisher of this object is required to ensure that any values present in the StudentSectionMarks object will not be higher than this value."</para>
	/// <para>Version: 2.6</para>
	/// <para>Since: 2.0</para>
	/// </remarks>
	public decimal? Maximum
	{
		get
		{
			return (decimal?) GetSifSimpleFieldValue( GradebookDTD.PERCENTAGE_MAXIMUM ) ;
		}
		set
		{
			SetFieldValue( GradebookDTD.PERCENTAGE_MAXIMUM, new SifDecimal( value ), value );
		}
	}

}}


text:
<?php

namespace PHPCR\Tests\Connecting;

use PHPCR\RepositoryFactoryInterface;

class RepositoryFactoryTest extends \PHPCR\Test\BaseCase
{
    public static function setupBeforeClass($fixtures = false)
    {
        //don't care about fixtures
        parent::setupBeforeClass($fixtures);
    }

    // 4.1 Repository
    public function testRepositoryFactory()
    {
        $class = self::$loader->getRepositoryFactoryClass();
        /** @var $factory RepositoryFactoryInterface */
        $factory = new $class();
        $repo = $factory->getRepository(self::$loader->getRepositoryFactoryParameters());
        $this->assertInstanceOf('PHPCR\RepositoryInterface', $repo);
    }
}


text:
'use strict';
module.exports = {
  up(qi, Sequelize) {
    /*
     Add altering commands here.
     Return a promise to correctly handle asynchronicity.

     Example:
     return qi.createTable('users', { id: Sequelize.INTEGER });
    */
    return qi.renameColumn('GeneratorTemplates', 'keywords', 'tags');
  },

  down(qi, Sequelize) {
    /*
     Add reverting commands here.
     Return a promise to correctly handle asynchronicity.

     Example:
     return qi.dropTable('users');
    */
    return qi.renameColumn('GeneratoTemplates', 'tags', 'keywords');
  },
};


text: Using Partitioning in Apriori Algorithm


text:
/**
 * @project : modula
 * @package : core, extend
 * @internal : declareFunctionCache.tokenizeCache
 * @type : declaration
 * @dependencies :	cache
 */

	/**
	 * define tokenizeCache for modula.js
	 */
	var
	tokenizeCache = cache( 'tokenizer' );


text:
export class DependentService {
  constructor(testService) {
    this.testService = testService
  }

  getInnerData() {
    return this.testService.getData()
  }
}


text:
class GitVersionBranchModel
{
    public string ReleaseStagingBranchPattern { get; set; }

    public string VersionTagPattern { get; set; }

    public string ReleaseTargetBranch { get; set; }

    public string DevelopBranch { get; set; }

    public string PushTarget { get; set; }
}


text:
extern peloton::CheckpointType peloton_checkpoint_mode;

namespace peloton {
namespace benchmark {
namespace logger {

void Usage(FILE* out) {
  fprintf(out,
          "Command line options :  logger <options> \n"
          "   -h --help              :  Print help message \n"
          "   -s --asynchronous-mode :  Asynchronous mode \n"
          "   -x --experiment-type   :  Experiment Type \n"
          "   -f --data-file-size    :  Data file size (MB) \n"
          "   -l --logging-type      :  Logging type \n"
          "   -t --nvm-latency       :  NVM latency \n"
          "   -q --pcommit-latency   :  pcommit latency \n"
          "   -v --flush-mode        :  Flush mode \n"
          "   -r --commit-interval   :  Group commit interval \n"
          "   -j --log-dir           :  Log directory\n"
          "   -y --benchmark-type    :  Benchmark type \n");
}

static struct option opts[] = {
    {"asynchronous_mode", optional_argument, NULL, 's'},
    {"experiment-type", optional_argument, NULL, 'x'},
    {"data-file-size", optional_argument, NULL, 'f'},
    {"logging-type", optional_argument, NULL, 'l'},
    {"nvm-latency", optional_argument, NULL, 't'},
    {"pcommit-latency", optional_argument, NULL, 'q'},
    {"flush-mode", optional_argument, NULL, 'v'},
    {"commit-interval", optional_argument, NULL, 'r'},
    {"benchmark-type", optional_argument, NULL, 'y'},
    {"log-dir", optional_argument, NULL, 'j'},
    {NULL, 0, NULL, 0}};

static void ValidateLoggingType(const configuration& state) {
  if (state.logging_type <= LOGGING_TYPE_INVALID) {
    LOG_ERROR("Invalid logging_type :: %d", state.logging_type);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("Logging_type :: %s",
           LoggingTypeToString(state.logging_type).c_str());
}

std::string BenchmarkTypeToString(BenchmarkType type) {
  switch (type) {
    case BENCHMARK_TYPE_INVALID:
      return "INVALID";

    case BENCHMARK_TYPE_YCSB:
      return "YCSB";
    case BENCHMARK_TYPE_TPCC:
      return "TPCC";

    default:
      LOG_ERROR("Invalid benchmark_type :: %d", type);
      exit(EXIT_FAILURE);
  }
  return "INVALID";
}

std::string ExperimentTypeToString(ExperimentType type) {
  switch (type) {
    case EXPERIMENT_TYPE_INVALID:
      return "INVALID";

    case EXPERIMENT_TYPE_THROUGHPUT:
      return "THROUGHPUT";
    case EXPERIMENT_TYPE_RECOVERY:
      return "RECOVERY";
    case EXPERIMENT_TYPE_STORAGE:
      return "STORAGE";
    case EXPERIMENT_TYPE_LATENCY:
      return "LATENCY";

    default:
      LOG_ERROR("Invalid experiment_type :: %d", type);
      exit(EXIT_FAILURE);
  }

  return "INVALID";
}

std::string AsynchronousTypeToString(AsynchronousType type) {
  switch (type) {
    case ASYNCHRONOUS_TYPE_INVALID:
      return "INVALID";

    case ASYNCHRONOUS_TYPE_SYNC:
      return "SYNC";
    case ASYNCHRONOUS_TYPE_ASYNC:
      return "ASYNC";
    case ASYNCHRONOUS_TYPE_DISABLED:
      return "DISABLED";
    case ASYNCHRONOUS_TYPE_NO_WRITE:
      return "NO_WRITE";

    default:
      LOG_ERROR("Invalid asynchronous_mode :: %d", type);
      exit(EXIT_FAILURE);
  }

  return "INVALID";
}

static void ValidateBenchmarkType(const configuration& state) {
  if (state.benchmark_type <= 0 || state.benchmark_type > 3) {
    LOG_ERROR("Invalid benchmark_type :: %d", state.benchmark_type);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("%s : %s", "benchmark_type",
           BenchmarkTypeToString(state.benchmark_type).c_str());
}

static void ValidateDataFileSize(const configuration& state) {
  if (state.data_file_size <= 0) {
    LOG_ERROR("Invalid data_file_size :: %lu", state.data_file_size);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("data_file_size :: %lu", state.data_file_size);
}

static void ValidateExperimentType(const configuration& state) {
  if (state.experiment_type < 0 || state.experiment_type > 4) {
    LOG_ERROR("Invalid experiment_type :: %d", state.experiment_type);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("%s : %s", "experiment_type",
           ExperimentTypeToString(state.experiment_type).c_str());
}

static void ValidateWaitTimeout(const configuration& state) {
  if (state.wait_timeout < 0) {
    LOG_ERROR("Invalid wait_timeout :: %d", state.wait_timeout);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("wait_timeout :: %d", state.wait_timeout);
}

static void ValidateFlushMode(const configuration& state) {
  if (state.flush_mode <= 0 || state.flush_mode >= 3) {
    LOG_ERROR("Invalid flush_mode :: %d", state.flush_mode);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("flush_mode :: %d", state.flush_mode);
}

static void ValidateAsynchronousMode(const configuration& state) {
  if (state.asynchronous_mode <= ASYNCHRONOUS_TYPE_INVALID ||
      state.asynchronous_mode > ASYNCHRONOUS_TYPE_NO_WRITE) {
    LOG_ERROR("Invalid asynchronous_mode :: %d", state.asynchronous_mode);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("%s : %s", "asynchronous_mode",
           AsynchronousTypeToString(state.asynchronous_mode).c_str());
}

static void ValidateNVMLatency(const configuration& state) {
  if (state.nvm_latency < 0) {
    LOG_ERROR("Invalid nvm_latency :: %d", state.nvm_latency);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("nvm_latency :: %d", state.nvm_latency);
}

static void ValidatePCOMMITLatency(const configuration& state) {
  if (state.pcommit_latency < 0) {
    LOG_ERROR("Invalid pcommit_latency :: %d", state.pcommit_latency);
    exit(EXIT_FAILURE);
  }

  LOG_INFO("pcommit_latency :: %d", state.pcommit_latency);
}

static void ValidateLogFileDir(configuration& state) {
  struct stat data_stat;
  // Check the existence of the log directory
  if (stat(state.log_file_dir.c_str(), &data_stat) != 0) {
    LOG_ERROR("log_file_dir :: %s does not exist", state.log_file_dir.c_str());
    exit(EXIT_FAILURE);
  } else if (!(data_stat.st_mode & S_IFDIR)) {
    LOG_ERROR("log_file_dir :: %s is not a directory", state.log_file_dir.c_str());
    exit(EXIT_FAILURE);
  }

  LOG_INFO("log_file_dir :: %s", state.log_file_dir.c_str());
}

void ParseArguments(int argc, char* argv[], configuration& state) {
  // Default Logger Values
  state.logging_type = LOGGING_TYPE_SSD_WAL;
  state.log_file_dir = TMP_DIR;
  state.data_file_size = 512;

  state.experiment_type = EXPERIMENT_TYPE_THROUGHPUT;
  state.wait_timeout = 200;
  state.benchmark_type = BENCHMARK_TYPE_YCSB;
  state.flush_mode = 2;
  state.nvm_latency = 0;
  state.pcommit_latency = 0;
  state.asynchronous_mode = ASYNCHRONOUS_TYPE_SYNC;
  state.checkpoint_type = CHECKPOINT_TYPE_INVALID;

  // YCSB Default Values
  ycsb::state.index = INDEX_TYPE_BWTREE;
  ycsb::state.scale_factor = 1;
  ycsb::state.duration = 10;
  ycsb::state.profile_duration = 1;
  ycsb::state.backend_count = 2;
  ycsb::state.column_count = 10;
  ycsb::state.operation_count = 10;
  ycsb::state.update_ratio = 0.5;
  ycsb::state.zipf_theta = 0.0;
  ycsb::state.exp_backoff = false;
  ycsb::state.string_mode = false;
  ycsb::state.gc_mode = false;
  ycsb::state.gc_backend_count = 1;

  // TPC-C Default Values
  tpcc::state.index = INDEX_TYPE_BWTREE;
  tpcc::state.scale_factor = 1;
  tpcc::state.duration = 10;
  tpcc::state.profile_duration = 1;
  tpcc::state.backend_count = 2;
  tpcc::state.warehouse_count = 2;
  tpcc::state.exp_backoff = false;
  tpcc::state.affinity = false;
  tpcc::state.gc_mode = false;
  tpcc::state.gc_backend_count = 1;

  // Parse args
  while (1) {
    int idx = 0;
    // logger - hs:x:f:l:t:q:v:r:y:
    // ycsb   - hemgi:k:d:p:b:c:o:u:z:n:
    // tpcc   - heagi:k:d:p:b:w:n:
    int c = getopt_long(argc, argv, "hs:x:f:l:t:q:v:r:y:emgi:k:d:p:b:c:o:u:z:n:aw:j:",
                        opts, &idx);

    if (c == -1) break;

    switch (c) {
      case 's':
        state.asynchronous_mode = (AsynchronousType)atoi(optarg);
        break;
      case 'x':
        state.experiment_type = (ExperimentType)atoi(optarg);
        break;
      case 'f':
        state.data_file_size = atoi(optarg);
        break;
      case 'j':
        state.log_file_dir = optarg;
        break;
      case 'l':
        state.logging_type = (LoggingType)atoi(optarg);
        break;
      case 't':
        state.nvm_latency = atoi(optarg);
        break;
      case 'q':
        state.pcommit_latency = atoi(optarg);
        break;
      case 'v':
        state.flush_mode = atoi(optarg);
        break;
      case 'r':
        state.wait_timeout = atoi(optarg);
        break;
      case 'y':
        state.benchmark_type = (BenchmarkType)atoi(optarg);
        break;

      case 'i': {
        char *index = optarg;
        if (strcmp(index, "btree") == 0) {
          ycsb::state.index = INDEX_TYPE_BWTREE;
          tpcc::state.index = INDEX_TYPE_BWTREE;
        } else if (strcmp(index, "bwtree") == 0) {
          ycsb::state.index = INDEX_TYPE_BWTREE;
          tpcc::state.index = INDEX_TYPE_BWTREE;
        } else {
          LOG_ERROR("Unknown index: %s", index);
          exit(EXIT_FAILURE);
        }
        break;
      }
      case 'k':
        ycsb::state.scale_factor = atoi(optarg);
        tpcc::state.scale_factor = atof(optarg);
        break;
      case 'd':
        ycsb::state.duration = atof(optarg);
        tpcc::state.duration = atof(optarg);
        break;
      case 'p':
        ycsb::state.profile_duration = atof(optarg);
        tpcc::state.profile_duration = atof(optarg);
        break;
      case 'b':
        ycsb::state.backend_count = atoi(optarg);
        tpcc::state.backend_count = atoi(optarg);
        break;
      case 'c':
        ycsb::state.column_count = atoi(optarg);
        break;
      case 'o':
        ycsb::state.operation_count = atoi(optarg);
        break;
      case 'u':
        ycsb::state.update_ratio = atof(optarg);
        break;
      case 'z':
        ycsb::state.zipf_theta = atof(optarg);
        break;
      case 'e':
        ycsb::state.exp_backoff = true;
        tpcc::state.exp_backoff = true;
        break;
      case 'm':
        ycsb::state.string_mode = true;
        break;
      case 'g':
        ycsb::state.gc_mode = true;
        tpcc::state.gc_mode = true;
        break;
      case 'n':
        ycsb::state.gc_backend_count = atof(optarg);
        tpcc::state.gc_backend_count = atof(optarg);
        break;
      case 'w':
        tpcc::state.warehouse_count = atoi(optarg);
        break;
      case 'a':
        tpcc::state.affinity = true;
        break;

      case 'h':
        Usage(stderr);
        ycsb::Usage(stderr);
        tpcc::Usage(stderr);
        exit(EXIT_FAILURE);
        break;

      default:
        fprintf(stderr, "\nUnknown option: -%c-\n", c);
        Usage(stderr);
        ycsb::Usage(stderr);
        tpcc::Usage(stderr);
        exit(EXIT_FAILURE);
        break;
    }
  }

  if (state.checkpoint_type == CHECKPOINT_TYPE_NORMAL &&
      (state.logging_type == LOGGING_TYPE_NVM_WAL ||
       state.logging_type == LOGGING_TYPE_SSD_WAL ||
       state.logging_type == LOGGING_TYPE_HDD_WAL)) {
    peloton_checkpoint_mode = CHECKPOINT_TYPE_NORMAL;
  }

  // Print Logger configuration
  ValidateLoggingType(state);
  ValidateExperimentType(state);
  ValidateAsynchronousMode(state);
  ValidateBenchmarkType(state);
  ValidateDataFileSize(state);
  ValidateLogFileDir(state);
  ValidateWaitTimeout(state);
  ValidateFlushMode(state);
  ValidateNVMLatency(state);
  ValidatePCOMMITLatency(state);

  // Print YCSB configuration
  if (state.benchmark_type == BENCHMARK_TYPE_YCSB) {
    ycsb::ValidateIndex(ycsb::state);
    ycsb::ValidateScaleFactor(ycsb::state);
    ycsb::ValidateDuration(ycsb::state);
    ycsb::ValidateProfileDuration(ycsb::state);
    ycsb::ValidateBackendCount(ycsb::state);
    ycsb::ValidateColumnCount(ycsb::state);
    ycsb::ValidateOperationCount(ycsb::state);
    ycsb::ValidateUpdateRatio(ycsb::state);
    ycsb::ValidateZipfTheta(ycsb::state);
    ycsb::ValidateGCBackendCount(ycsb::state);
  }
  // Print TPCC configuration
  else if (state.benchmark_type == BENCHMARK_TYPE_TPCC) {
    tpcc::ValidateIndex(tpcc::state);
    tpcc::ValidateScaleFactor(tpcc::state);
    tpcc::ValidateDuration(tpcc::state);
    tpcc::ValidateProfileDuration(tpcc::state);
    tpcc::ValidateBackendCount(tpcc::state);
    tpcc::ValidateWarehouseCount(tpcc::state);
    tpcc::ValidateGCBackendCount(tpcc::state);

    // Static TPCC parameters
    tpcc::state.item_count = 100000 * tpcc::state.scale_factor;
    tpcc::state.districts_per_warehouse = 10;
    tpcc::state.customers_per_district = 3000 * tpcc::state.scale_factor;
    tpcc::state.new_orders_per_district = 900 * tpcc::state.scale_factor;
  }
}

}  // namespace logger
}  // namespace benchmark
}  // namespace peloton


text:
from distutils.core import setup
import os

#-Write Versions File-#
#~~~~~~~~~~~~~~~~~~~~~#

VERSION = '0.1.9'

def write_version_py(filename=None):
    """
    This constructs a version file for the project
    """
    doc = "\"\"\"\nThis is a VERSION file and should NOT be manually altered\n\"\"\""
    doc += "\nversion = '%s'" % VERSION

    if not filename:
        filename = os.path.join(os.path.dirname(__file__), 'quantecon', 'version.py')

    fl = open(filename, 'w')
    try:
        fl.write(doc)
    finally:
        fl.close()

write_version_py()  # This is a file used to control the qe.__version__ attribute

#-Meta Information-#
#~~~~~~~~~~~~~~~~~~#

DESCRIPTION = "QuantEcon is a package to support all forms of quantitative economic modelling."       #'Core package of the QuantEcon library'

LONG_DESCRIPTION = """
**QuantEcon** is an organization run by economists for economists with the aim of coordinating
distributed development of high quality open source code for all forms of quantitative economic modelling.

The project website is located at `http://quantecon.org/ <http://quantecon.org/>`_. This website provides
more information with regards to the **quantecon** library, documentation, in addition to some resources
in regards to how you can use and/or contribute to the package.

The **quantecon** Package
-------------------------

The `repository <https://github.com/QuantEcon/QuantEcon.py>`_ includes the Python package ``quantecon``

Assuming you have `pip <https://pypi.python.org/pypi/pip>`_ on your computer --- as will be the case if you've `installed Anaconda <http://quant-econ.net/getting_started.html#installing-anaconda>`_ --- you can install the latest stable release of ``quantecon`` by typing

    pip install quantecon

at a terminal prompt

Repository
----------

The main repository is hosted on Github `QuantEcon.py <https://github.com/QuantEcon/QuantEcon.py>`_

**Note:** There is also a Julia version available for Julia users `QuantEcon.jl <https://github.com/QuantEcon/QuantEcon.jl>`_

Current Build and Coverage Status
---------------------------------

|Build Status| |Coverage Status|

.. |Build Status| image:: https://travis-ci.org/QuantEcon/QuantEcon.py.svg?branch=master
   :target: https://travis-ci.org/QuantEcon/QuantEcon.py
.. |Coverage Status| image:: https://coveralls.io/repos/QuantEcon/QuantEcon.py/badge.png
   :target: https://coveralls.io/r/QuantEcon/QuantEcon.py

Additional Links
----------------

1. `QuantEcon Course Website <http://quant-econ.net>`_

"""

LICENSE = "BSD"

#-Classifier Strings-#
#-https://pypi.python.org/pypi?%3Aaction=list_classifiers-#
CLASSIFIERS = [
    'Development Status :: 4 - Beta',
    'Operating System :: OS Independent',
    'Intended Audience :: Science/Research',
    'Programming Language :: Python',
    'Programming Language :: Python :: 2',
    'Programming Language :: Python :: 3',
    'Programming Language :: Python :: 2.7',
    'Programming Language :: Python :: 3.3',
    'Programming Language :: Python :: 3.4',
    'Topic :: Scientific/Engineering',
]

#-Setup-#
#~~~~~~~#

setup(name='quantecon',
      packages=['quantecon',
                'quantecon.markov',
                'quantecon.models',
                'quantecon.models.solow',
                'quantecon.random',
                'quantecon.tests',
                'quantecon.util',
                ],
      version=VERSION,
      description=DESCRIPTION,
      long_description=LONG_DESCRIPTION,
      license=LICENSE,
      classifiers=CLASSIFIERS,
      author='Thomas J. Sargent and John Stachurski (Project coordinators)',
      author_email='john.stachurski@gmail.com',
      url='https://github.com/QuantEcon/QuantEcon.py',  # URL to the repo
      keywords=['quantitative', 'economics']
      )


text:
"""Contains the logic for `aq update service --instance`."""

from aquilon.exceptions_ import ArgumentError
from aquilon.worker.broker import BrokerCommand  # pylint: disable=W0611
from aquilon.aqdb.model import Service, ServiceInstance
from aquilon.worker.templates.base import Plenary

class CommandUpdateServiceInstance(BrokerCommand):

    required_parameters = ["service", "instance"]

    def render(self, session, logger, service, instance, max_clients, default,
               **arguments):
        dbservice = Service.get_unique(session, name=service, compel=True)
        dbsi = ServiceInstance.get_unique(session, service=dbservice,
                                          name=instance, compel=True)
        if default:
            dbsi.max_clients = None
        elif max_clients is not None:
            dbsi.max_clients = max_clients
        else:
            raise ArgumentError("Missing --max_clients or --default argument "
                                "to update service %s instance %s." %
                                (dbservice.name, dbsi.name))
        session.add(dbsi)
        session.flush()

        plenary = Plenary.get_plenary(dbsi, logger=logger)
        plenary.write()

        return


text:
// Copyright (c) Microsoft. All rights reserved.
// Licensed under MIT license. See LICENSE file in the project root for full license information.

#ifndef JAVA_MODULE_HOST_H
#define JAVA_MODULE_HOST_H

#include <stdbool.h>
#ifdef _WIN32
#include <cstdbool>
#endif
#include "azure_c_shared_utility/vector.h"
#include "module.h"

#define JAVA_MODULE_CLASS_NAME_KEY "class_name"
#define JAVA_MODULE_ARGS_KEY "args"
#define JAVA_MODULE_CLASS_PATH_KEY "class_path"
#define JAVA_MODULE_LIBRARY_PATH_KEY "library_path"
#define JAVA_MODULE_JVM_OPTIONS_KEY "jvm_options"
#define JAVA_MODULE_JVM_OPTIONS_VERSION_KEY "version"
#define JAVA_MODULE_JVM_OPTIONS_DEBUG_KEY "debug"
#define JAVA_MODULE_JVM_OPTIONS_DEBUG_PORT_KEY "debug_port"
#define JAVA_MODULE_JVM_OPTIONS_VERBOSE_KEY "verbose"
#define JAVA_MODULE_JVM_OPTIONS_ADDITIONAL_OPTIONS_KEY "additional_options"

#ifdef __cplusplus
extern "C"
{
#endif

typedef struct JVM_OPTIONS_TAG
{
    const char* class_path;
    const char* library_path;
    int version;
    bool debug;
    int debug_port;
    bool verbose;
    VECTOR_HANDLE additional_options;
} JVM_OPTIONS;

typedef struct JAVA_MODULE_HOST_CONFIG_TAG
{
    const char* class_name;
    const char* configuration_json;
    JVM_OPTIONS* options;
} JAVA_MODULE_HOST_CONFIG;

MODULE_EXPORT const MODULE_API* MODULE_STATIC_GETAPI(JAVA_MODULE_HOST)(const MODULE_API_VERSION gateway_api_version);

#ifdef __cplusplus
}
#endif

#endif /*JAVA_MODULE_HOST_H*/


text:
scrapy_retryMiddleware
======================

A retry downloader middleware to record failed request


text:
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stddef.h>
#include <string>

#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/simple_thread.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
#include "net/quic/crypto/null_encrypter.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_packet_creator.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/quic/test_tools/quic_session_peer.h"
#include "net/quic/test_tools/reliable_quic_stream_peer.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
#include "net/tools/quic/quic_in_memory_cache.h"
#include "net/tools/quic/quic_server.h"
#include "net/tools/quic/quic_socket_utils.h"
#include "net/tools/quic/test_tools/http_message_test_utils.h"
#include "net/tools/quic/test_tools/quic_client_peer.h"
#include "net/tools/quic/test_tools/quic_epoll_connection_helper_peer.h"
#include "net/tools/quic/test_tools/quic_test_client.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::StringPiece;
using base::WaitableEvent;
using net::test::QuicConnectionPeer;
using net::test::QuicSessionPeer;
using net::test::ReliableQuicStreamPeer;
using std::string;

namespace net {
namespace tools {
namespace test {
namespace {

const char* kFooResponseBody = "Artichoke hearts make me happy.";
const char* kBarResponseBody = "Palm hearts are pretty delicious, also.";
const size_t kCongestionFeedbackFrameSize = 25;
// If kCongestionFeedbackFrameSize increase we need to expand this string
// accordingly.
const char* kLargeRequest =
    "https://www.google.com/foo/test/a/request/string/longer/than/25/bytes";

void GenerateBody(string* body, int length) {
  body->clear();
  body->reserve(length);
  for (int i = 0; i < length; ++i) {
    body->append(1, static_cast<char>(32 + i % (126 - 32)));
  }
}

// Simple wrapper class to run server in a thread.
class ServerThread : public base::SimpleThread {
 public:
  ServerThread(IPEndPoint address,
               const QuicConfig& config,
               bool strike_register_no_startup_period)
      : SimpleThread("server_thread"),
        listening_(true, false),
        quit_(true, false),
        server_(config),
        address_(address),
        port_(0) {
    if (strike_register_no_startup_period) {
      server_.SetStrikeRegisterNoStartupPeriod();
    }
  }
  virtual ~ServerThread() {
  }

  virtual void Run() OVERRIDE {
    server_.Listen(address_);

    port_lock_.Acquire();
    port_ = server_.port();
    port_lock_.Release();

    listening_.Signal();
    while (!quit_.IsSignaled()) {
      server_.WaitForEvents();
    }
    server_.Shutdown();
  }

  int GetPort() {
    port_lock_.Acquire();
    int rc = port_;
    port_lock_.Release();
    return rc;
  }

  WaitableEvent* listening() { return &listening_; }
  WaitableEvent* quit() { return &quit_; }

 private:
  WaitableEvent listening_;
  WaitableEvent quit_;
  base::Lock port_lock_;
  QuicServer server_;
  IPEndPoint address_;
  int port_;

  DISALLOW_COPY_AND_ASSIGN(ServerThread);
};

class EndToEndTest : public ::testing::TestWithParam<QuicVersion> {
 public:
  static void SetUpTestCase() {
    QuicInMemoryCache::GetInstance()->ResetForTests();
  }

 protected:
  EndToEndTest()
      : server_hostname_("example.com"),
        server_started_(false),
        strike_register_no_startup_period_(false) {
    net::IPAddressNumber ip;
    CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &ip));
    server_address_ = IPEndPoint(ip, 0);
    client_config_.SetDefaults();
    server_config_.SetDefaults();

    AddToCache("GET", kLargeRequest, "HTTP/1.1", "200", "OK", kFooResponseBody);
    AddToCache("GET", "https://www.google.com/foo",
               "HTTP/1.1", "200", "OK", kFooResponseBody);
    AddToCache("GET", "https://www.google.com/bar",
               "HTTP/1.1", "200", "OK", kBarResponseBody);
    version_ = GetParam();
  }

  virtual QuicTestClient* CreateQuicClient() {
    QuicTestClient* client = new QuicTestClient(server_address_,
                                                server_hostname_,
                                                false,  // not secure
                                                client_config_,
                                                version_);
    client->Connect();
    return client;
  }

  virtual bool Initialize() {
    // Start the server first, because CreateQuicClient() attempts
    // to connect to the server.
    StartServer();
    client_.reset(CreateQuicClient());
    return client_->client()->connected();
  }

  virtual void TearDown() {
    StopServer();
  }

  void StartServer() {
    server_thread_.reset(new ServerThread(server_address_, server_config_,
                                          strike_register_no_startup_period_));
    server_thread_->Start();
    server_thread_->listening()->Wait();
    server_address_ = IPEndPoint(server_address_.address(),
                                 server_thread_->GetPort());
    server_started_ = true;
  }

  void StopServer() {
    if (!server_started_)
      return;
    if (server_thread_.get()) {
      server_thread_->quit()->Signal();
      server_thread_->Join();
    }
  }

  void AddToCache(const StringPiece& method,
                  const StringPiece& path,
                  const StringPiece& version,
                  const StringPiece& response_code,
                  const StringPiece& response_detail,
                  const StringPiece& body) {
    BalsaHeaders request_headers, response_headers;
    request_headers.SetRequestFirstlineFromStringPieces(method,
                                                        path,
                                                        version);
    response_headers.SetRequestFirstlineFromStringPieces(version,
                                                         response_code,
                                                         response_detail);
    response_headers.AppendHeader("content-length",
                                  base::IntToString(body.length()));

    // Check if response already exists and matches.
    QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
    const QuicInMemoryCache::Response* cached_response =
        cache->GetResponse(request_headers);
    if (cached_response != NULL) {
      string cached_response_headers_str, response_headers_str;
      cached_response->headers().DumpToString(&cached_response_headers_str);
      response_headers.DumpToString(&response_headers_str);
      CHECK_EQ(cached_response_headers_str, response_headers_str);
      CHECK_EQ(cached_response->body(), body);
      return;
    }
    cache->AddResponse(request_headers, response_headers, body);
  }

  IPEndPoint server_address_;
  string server_hostname_;
  scoped_ptr<ServerThread> server_thread_;
  scoped_ptr<QuicTestClient> client_;
  bool server_started_;
  QuicConfig client_config_;
  QuicConfig server_config_;
  QuicVersion version_;
  bool strike_register_no_startup_period_;
};

// Run all end to end tests with all supported versions.
INSTANTIATE_TEST_CASE_P(EndToEndTests,
                        EndToEndTest,
                        ::testing::ValuesIn(kSupportedQuicVersions));

TEST_P(EndToEndTest, SimpleRequestResponse) {
  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  ASSERT_TRUE(Initialize());

  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
  EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
}

// TODO(rch): figure out how to detect missing v6 supprt (like on the linux
// try bots) and selectively disable this test.
TEST_P(EndToEndTest, DISABLED_SimpleRequestResponsev6) {
  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  IPAddressNumber ip;
  CHECK(net::ParseIPLiteralToNumber("::1", &ip));
  server_address_ = IPEndPoint(ip, server_address_.port());
  ASSERT_TRUE(Initialize());

  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
  EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
}

TEST_P(EndToEndTest, SeparateFinPacket) {
  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  ASSERT_TRUE(Initialize());

  HTTPMessage request(HttpConstants::HTTP_1_1,
                      HttpConstants::POST, "/foo");
  request.set_has_complete_message(false);

  client_->SendMessage(request);

  client_->SendData(string(), true);

  client_->WaitForResponse();
  EXPECT_EQ(kFooResponseBody, client_->response_body());
  EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());

  request.AddBody("foo", true);

  client_->SendMessage(request);
  client_->SendData(string(), true);
  client_->WaitForResponse();
  EXPECT_EQ(kFooResponseBody, client_->response_body());
  EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
}

TEST_P(EndToEndTest, MultipleRequestResponse) {
  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  ASSERT_TRUE(Initialize());

  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
  EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
  EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
  EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
}

TEST_P(EndToEndTest, MultipleClients) {
  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  ASSERT_TRUE(Initialize());
  scoped_ptr<QuicTestClient> client2(CreateQuicClient());

  HTTPMessage request(HttpConstants::HTTP_1_1,
                      HttpConstants::POST, "/foo");
  request.AddHeader("content-length", "3");
  request.set_has_complete_message(false);

  client_->SendMessage(request);
  client2->SendMessage(request);

  client_->SendData("bar", true);
  client_->WaitForResponse();
  EXPECT_EQ(kFooResponseBody, client_->response_body());
  EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());

  client2->SendData("eep", true);
  client2->WaitForResponse();
  EXPECT_EQ(kFooResponseBody, client2->response_body());
  EXPECT_EQ(200u, client2->response_headers()->parsed_response_code());
}

TEST_P(EndToEndTest, RequestOverMultiplePackets) {
  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  ASSERT_TRUE(Initialize());
  // Set things up so we have a small payload, to guarantee fragmentation.
  // A congestion feedback frame can't be split into multiple packets, make sure
  // that our packet have room for at least this amount after the normal headers
  // are added.

  // TODO(rch) handle this better when we have different encryption options.
  const size_t kStreamDataLength = 3;
  const QuicStreamId kStreamId = 1u;
  const QuicStreamOffset kStreamOffset = 0u;
  size_t stream_payload_size =
      QuicFramer::GetMinStreamFrameSize(
          GetParam(), kStreamId, kStreamOffset, true) + kStreamDataLength;
  size_t min_payload_size =
      std::max(kCongestionFeedbackFrameSize, stream_payload_size);
  size_t ciphertext_size = NullEncrypter().GetCiphertextSize(min_payload_size);
  // TODO(satyashekhar): Fix this when versioning is implemented.
  client_->options()->max_packet_length =
      GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion,
                          PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP) +
      ciphertext_size;

  // Make sure our request is too large to fit in one packet.
  EXPECT_GT(strlen(kLargeRequest), min_payload_size);
  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest(kLargeRequest));
  EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
}

TEST_P(EndToEndTest, MultipleFramesRandomOrder) {
  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  ASSERT_TRUE(Initialize());
  // Set things up so we have a small payload, to guarantee fragmentation.
  // A congestion feedback frame can't be split into multiple packets, make sure
  // that our packet have room for at least this amount after the normal headers
  // are added.

  // TODO(rch) handle this better when we have different encryption options.
  const size_t kStreamDataLength = 3;
  const QuicStreamId kStreamId = 1u;
  const QuicStreamOffset kStreamOffset = 0u;
  size_t stream_payload_size =
      QuicFramer::GetMinStreamFrameSize(
          GetParam(), kStreamId, kStreamOffset, true) + kStreamDataLength;
  size_t min_payload_size =
      std::max(kCongestionFeedbackFrameSize, stream_payload_size);
  size_t ciphertext_size = NullEncrypter().GetCiphertextSize(min_payload_size);
  // TODO(satyashekhar): Fix this when versioning is implemented.
  client_->options()->max_packet_length =
      GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion,
                          PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP) +
      ciphertext_size;
  client_->options()->random_reorder = true;

  // Make sure our request is too large to fit in one packet.
  EXPECT_GT(strlen(kLargeRequest), min_payload_size);
  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest(kLargeRequest));
  EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
}

TEST_P(EndToEndTest, PostMissingBytes) {
  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  ASSERT_TRUE(Initialize());

  // Add a content length header with no body.
  HTTPMessage request(HttpConstants::HTTP_1_1,
                      HttpConstants::POST, "/foo");
  request.AddHeader("content-length", "3");
  request.set_skip_message_validation(true);

  // This should be detected as stream fin without complete request,
  // triggering an error response.
  client_->SendCustomSynchronousRequest(request);
  EXPECT_EQ("bad", client_->response_body());
  EXPECT_EQ(500u, client_->response_headers()->parsed_response_code());
}

TEST_P(EndToEndTest, LargePostNoPacketLoss) {
  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  ASSERT_TRUE(Initialize());

  client_->client()->WaitForCryptoHandshakeConfirmed();

  // 1 Mb body.
  string body;
  GenerateBody(&body, 1024 * 1024);

  HTTPMessage request(HttpConstants::HTTP_1_1,
                      HttpConstants::POST, "/foo");
  request.AddBody(body, true);

  EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
}

TEST_P(EndToEndTest, LargePostWithPacketLoss) {
  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  // Connect with lower fake packet loss than we'd like to test.  Until
  // b/10126687 is fixed, losing handshake packets is pretty brutal.
  // FLAGS_fake_packet_loss_percentage = 5;
  ASSERT_TRUE(Initialize());

  // Wait for the server SHLO before upping the packet loss.
  client_->client()->WaitForCryptoHandshakeConfirmed();
  // FLAGS_fake_packet_loss_percentage = 30;

  // 10 Kb body.
  string body;
  GenerateBody(&body, 1024 * 10);

  HTTPMessage request(HttpConstants::HTTP_1_1,
                      HttpConstants::POST, "/foo");
  request.AddBody(body, true);

  EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
}

TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
  // Have the server accept 0-RTT without waiting a startup period.
  strike_register_no_startup_period_ = true;

  // Send a request and then disconnect. This prepares the client to attempt
  // a 0-RTT handshake for the next request.
  ASSERT_TRUE(Initialize());

  string body;
  GenerateBody(&body, 20480);

  HTTPMessage request(HttpConstants::HTTP_1_1,
                      HttpConstants::POST, "/foo");
  request.AddBody(body, true);

  EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
  EXPECT_EQ(2, client_->client()->session()->GetNumSentClientHellos());

  client_->Disconnect();

  // The 0-RTT handshake should succeed.
  client_->Connect();
  ASSERT_TRUE(client_->client()->connected());
  EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
  EXPECT_EQ(1, client_->client()->session()->GetNumSentClientHellos());

  client_->Disconnect();

  // Restart the server so that the 0-RTT handshake will take 1 RTT.
  StopServer();
  StartServer();

  client_->Connect();
  ASSERT_TRUE(client_->client()->connected());
  EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
  EXPECT_EQ(2, client_->client()->session()->GetNumSentClientHellos());
}

// TODO(ianswett): Enable once b/9295090 is fixed.
TEST_P(EndToEndTest, DISABLED_LargePostFEC) {
  // FLAGS_fake_packet_loss_percentage = 30;
  ASSERT_TRUE(Initialize());
  client_->options()->max_packets_per_fec_group = 6;

  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  // FLAGS_fake_packet_loss_percentage = 30;
  ASSERT_TRUE(Initialize());
  client_->options()->max_packets_per_fec_group = 6;

  string body;
  GenerateBody(&body, 10240);

  HTTPMessage request(HttpConstants::HTTP_1_1,
                      HttpConstants::POST, "/foo");
  request.AddBody(body, true);

  EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
}

/*TEST_P(EndToEndTest, PacketTooLarge) {
  FLAGS_quic_allow_oversized_packets_for_test = true;
  ASSERT_TRUE(Initialize());

  string body;
  GenerateBody(&body, kMaxPacketSize);

  HTTPMessage request(HttpConstants::HTTP_1_1,
                      HttpConstants::POST, "/foo");
  request.AddBody(body, true);
  client_->options()->max_packet_length = 20480;

  EXPECT_EQ("", client_->SendCustomSynchronousRequest(request));
  EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
  EXPECT_EQ(QUIC_PACKET_TOO_LARGE, client_->connection_error());
}*/

TEST_P(EndToEndTest, InvalidStream) {
  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  ASSERT_TRUE(Initialize());

  string body;
  GenerateBody(&body, kMaxPacketSize);

  HTTPMessage request(HttpConstants::HTTP_1_1,
                      HttpConstants::POST, "/foo");
  request.AddBody(body, true);
  // Force the client to write with a stream ID belonging to a nonexistent
  // server-side stream.
  QuicSessionPeer::SetNextStreamId(client_->client()->session(), 2);

  client_->SendCustomSynchronousRequest(request);
//  EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
  EXPECT_EQ(QUIC_PACKET_FOR_NONEXISTENT_STREAM, client_->connection_error());
}

// TODO(rch): this test seems to cause net_unittests timeouts :|
TEST_P(EndToEndTest, DISABLED_MultipleTermination) {
  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  ASSERT_TRUE(Initialize());

  HTTPMessage request(HttpConstants::HTTP_1_1,
                      HttpConstants::POST, "/foo");
  request.AddHeader("content-length", "3");
  request.set_has_complete_message(false);

  // Set the offset so we won't frame.  Otherwise when we pick up termination
  // before HTTP framing is complete, we send an error and close the stream,
  // and the second write is picked up as writing on a closed stream.
  QuicReliableClientStream* stream = client_->GetOrCreateStream();
  ASSERT_TRUE(stream != NULL);
  ReliableQuicStreamPeer::SetStreamBytesWritten(3, stream);

  client_->SendData("bar", true);

  // By default the stream protects itself from writes after terminte is set.
  // Override this to test the server handling buggy clients.
  ReliableQuicStreamPeer::SetWriteSideClosed(
      false, client_->GetOrCreateStream());

#if !defined(WIN32) && defined(GTEST_HAS_DEATH_TEST)
#if !defined(DCHECK_ALWAYS_ON)
  EXPECT_DEBUG_DEATH({
      client_->SendData("eep", true);
      client_->WaitForResponse();
      EXPECT_EQ(QUIC_MULTIPLE_TERMINATION_OFFSETS, client_->stream_error());
    },
    "Check failed: !fin_buffered_");
#else
  EXPECT_DEATH({
      client_->SendData("eep", true);
      client_->WaitForResponse();
      EXPECT_EQ(QUIC_MULTIPLE_TERMINATION_OFFSETS, client_->stream_error());
    },
    "Check failed: !fin_buffered_");
#endif
#endif
}

TEST_P(EndToEndTest, Timeout) {
  client_config_.set_idle_connection_state_lifetime(
      QuicTime::Delta::FromMicroseconds(500),
      QuicTime::Delta::FromMicroseconds(500));
  // Note: we do NOT ASSERT_TRUE: we may time out during initial handshake:
  // that's enough to validate timeout in this case.
  Initialize();
  while (client_->client()->connected()) {
    client_->client()->WaitForEvents();
  }
}

TEST_P(EndToEndTest, LimitMaxOpenStreams) {
  // Server limits the number of max streams to 2.
  server_config_.set_max_streams_per_connection(2, 2);
  // Client tries to negotiate for 10.
  client_config_.set_max_streams_per_connection(10, 5);

  ASSERT_TRUE(Initialize());
  client_->client()->WaitForCryptoHandshakeConfirmed();
  QuicConfig* client_negotiated_config = client_->client()->session()->config();
  EXPECT_EQ(2u, client_negotiated_config->max_streams_per_connection());
}

TEST_P(EndToEndTest, ResetConnection) {
  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  ASSERT_TRUE(Initialize());

  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
  EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
  client_->ResetConnection();
  EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
  EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
}

TEST_P(EndToEndTest, MaxStreamsUberTest) {
  //  FLAGS_fake_packet_loss_percentage = 1;
  ASSERT_TRUE(Initialize());
  string large_body;
  GenerateBody(&large_body, 10240);
  int max_streams = 100;

  AddToCache("GET", "/large_response", "HTTP/1.1", "200", "OK", large_body);;

  client_->client()->WaitForCryptoHandshakeConfirmed();
  // FLAGS_fake_packet_loss_percentage = 10;

  for (int i = 0; i < max_streams; ++i) {
    EXPECT_LT(0, client_->SendRequest("/large_response"));
  }

  // WaitForEvents waits 50ms and returns true if there are outstanding
  // requests.
  while (client_->client()->WaitForEvents() == true) {
  }
}

class WrongAddressWriter : public QuicPacketWriter {
 public:
  explicit WrongAddressWriter(int fd) : fd_(fd) {
    IPAddressNumber ip;
    CHECK(net::ParseIPLiteralToNumber("127.0.0.2", &ip));
    self_address_ = IPEndPoint(ip, 0);
  }

  virtual int WritePacket(const char* buffer, size_t buf_len,
                          const IPAddressNumber& real_self_address,
                          const IPEndPoint& peer_address,
                          QuicBlockedWriterInterface* blocked_writer,
                          int* error) OVERRIDE {
    return QuicSocketUtils::WritePacket(fd_, buffer, buf_len,
                                        self_address_.address(), peer_address,
                                        error);
  }

  IPEndPoint self_address_;
  int fd_;
};

TEST_P(EndToEndTest, ConnectionMigration) {
  // TODO(rtenneti): Delete this when NSS is supported.
  if (!Aes128Gcm12Encrypter::IsSupported()) {
    LOG(INFO) << "AES GCM not supported. Test skipped.";
    return;
  }

  ASSERT_TRUE(Initialize());

  EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
  EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());

  WrongAddressWriter writer(QuicClientPeer::GetFd(client_->client()));
  QuicEpollConnectionHelper* helper =
      reinterpret_cast<QuicEpollConnectionHelper*>(
          QuicConnectionPeer::GetHelper(
              client_->client()->session()->connection()));
  QuicEpollConnectionHelperPeer::SetWriter(helper, &writer);

  client_->SendSynchronousRequest("/bar");
  QuicEpollConnectionHelperPeer::SetWriter(helper, NULL);

  EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
  EXPECT_EQ(QUIC_ERROR_MIGRATING_ADDRESS, client_->connection_error());
}

}  // namespace
}  // namespace test
}  // namespace tools
}  // namespace net