Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
wip: Check for invalid property function combinations
Browse files Browse the repository at this point in the history
  • Loading branch information
boundsj committed Jan 31, 2017
1 parent e15ebcd commit 2fed47f
Show file tree
Hide file tree
Showing 9 changed files with 1,173 additions and 736 deletions.
33 changes: 23 additions & 10 deletions platform/darwin/src/MGLStyleValue_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,21 @@ class MGLStyleValueTransformer {

// Convert an mgl style value into a non interpolatable (camera with interval stops) mbgl property value
mbgl::style::PropertyValue<MBGLType> toPropertyValue(MGLStyleValue<ObjCType> *value) {
if ([value isKindOfClass:[MGLSourceStyleFunction class]] || [value isKindOfClass:[MGLCompositeStyleFunction class]]) {
[NSException raise:NSInvalidArgumentException
format:@"This property can only be set to camera functions. Use +[MGLStyleValue cameraFunctionValueWithStopType:stops:options:] instead."];
return {};
}

if ([value isKindOfClass:[MGLStyleConstantValue class]]) {
return toMBGLConstantValue((MGLStyleConstantValue<ObjCType> *)value);
} else if ([value isKindOfClass:[MGLCameraStyleFunction class]]) {
MGLCameraStyleFunction<ObjCType> *cameraStyleFunction = (MGLCameraStyleFunction<ObjCType> *)value;
switch (cameraStyleFunction.stopType) {
case MGLStyleFunctionStopTypeInterval:
return toMBGLIntervalCameraFunction(cameraStyleFunction);
break;
default:
[NSException raise:NSInvalidArgumentException
format:@"Camera functions can only support interval stops for float, boolean, and enumeration values."];
break;
}
return {};
// Intentionally ignore the stop type set by the developer becuase non interpolatable property values
// can only have interval stops. This also allows for backwards compatiblity when the developer uses
// a deprecated MGLStyleValue method (that used to create an MGLStyleFunction) to create a function
// for properties that are piecewise-constant (i.e. enum, bool, string)
return toMBGLIntervalCameraFunction(cameraStyleFunction);
} else if (value) {
[NSException raise:@"MGLAbstractClassException" format:
@"The style value %@ cannot be applied to the style. "
Expand All @@ -72,6 +73,12 @@ class MGLStyleValueTransformer {

// Convert an mgl style value into a non interpolatable (camera with exponential or interval stops) mbgl property value
mbgl::style::PropertyValue<MBGLType> toInterpolatablePropertyValue(MGLStyleValue<ObjCType> *value) {
if ([value isKindOfClass:[MGLSourceStyleFunction class]] || [value isKindOfClass:[MGLCompositeStyleFunction class]]) {
[NSException raise:NSInvalidArgumentException
format:@"This property can only be set to camera functions. Use +[MGLStyleValue cameraFunctionValueWithStopType:stops:options:] instead."];
return {};
}

if ([value isKindOfClass:[MGLStyleConstantValue class]]) {
return toMBGLConstantValue((MGLStyleConstantValue<ObjCType> *)value);
} else if ([value isKindOfClass:[MGLCameraStyleFunction class]]) {
Expand Down Expand Up @@ -243,6 +250,12 @@ class MGLStyleValueTransformer {
typename MGLEnum = ObjCEnum,
class = typename std::enable_if<std::is_enum<MGLEnum>::value>::type>
mbgl::style::PropertyValue<MBGLEnum> toEnumPropertyValue(MGLStyleValue<ObjCType> *value) {
if ([value isKindOfClass:[MGLSourceStyleFunction class]] || [value isKindOfClass:[MGLCompositeStyleFunction class]]) {
[NSException raise:NSInvalidArgumentException
format:@"This property can only be set to camera functions. Use +[MGLStyleValue cameraFunctionValueWithStopType:stops:options:] instead."];
return {};
}

if ([value isKindOfClass:[MGLStyleConstantValue class]]) {
MBGLEnum mbglValue;
getMBGLValue([(MGLStyleConstantValue<ObjCType> *)value rawValue], mbglValue);
Expand Down
60 changes: 36 additions & 24 deletions platform/darwin/test/MGLBackgroundStyleLayerTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,25 @@ - (void)testProperties {
@"background-color should be unset initially.");
MGLStyleValue<MGLColor *> *defaultStyleValue = layer.backgroundColor;

MGLStyleValue<MGLColor *> *styleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.backgroundColor = styleValue;
MGLStyleValue<MGLColor *> *constantStyleValue = [MGLStyleValue<MGLColor *> valueWithRawValue:[MGLColor redColor]];
layer.backgroundColor = constantStyleValue;
mbgl::style::PropertyValue<mbgl::Color> propertyValue = { { 1, 0, 0, 1 } };
XCTAssertEqual(rawLayer->getBackgroundColor(), propertyValue,
@"Setting backgroundColor to a constant value should update background-color.");
XCTAssertEqualObjects(layer.backgroundColor, styleValue,
XCTAssertEqualObjects(layer.backgroundColor, constantStyleValue,
@"backgroundColor should round-trip constant values.");

styleValue = [MGLStyleValue<MGLColor *> cameraFunctionValueWithStopType:MGLStyleFunctionStopTypeInterval
stops:@{@18: styleValue}
options:nil];
layer.backgroundColor = styleValue;
MGLStyleValue<MGLColor *> * functionStyleValue = [MGLStyleValue<MGLColor *> cameraFunctionValueWithStopType:MGLStyleFunctionStopTypeInterval
stops:@{@18: constantStyleValue}
options:nil];
layer.backgroundColor = functionStyleValue;

mbgl::style::IntervalStops<mbgl::Color> intervalStops = { {{18, { 1, 0, 0, 1 }}} };
propertyValue = mbgl::style::CameraFunction<mbgl::Color> { intervalStops };

XCTAssertEqual(rawLayer->getBackgroundColor(), propertyValue,
@"Setting backgroundColor to a function should update background-color.");
XCTAssertEqualObjects(layer.backgroundColor, styleValue,
XCTAssertEqualObjects(layer.backgroundColor, functionStyleValue,
@"backgroundColor should round-trip functions.");

layer.backgroundColor = nil;
Expand All @@ -62,25 +62,25 @@ - (void)testProperties {
@"background-opacity should be unset initially.");
MGLStyleValue<NSNumber *> *defaultStyleValue = layer.backgroundOpacity;

MGLStyleValue<NSNumber *> *styleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
layer.backgroundOpacity = styleValue;
MGLStyleValue<NSNumber *> *constantStyleValue = [MGLStyleValue<NSNumber *> valueWithRawValue:@0xff];
layer.backgroundOpacity = constantStyleValue;
mbgl::style::PropertyValue<float> propertyValue = { 0xff };
XCTAssertEqual(rawLayer->getBackgroundOpacity(), propertyValue,
@"Setting backgroundOpacity to a constant value should update background-opacity.");
XCTAssertEqualObjects(layer.backgroundOpacity, styleValue,
XCTAssertEqualObjects(layer.backgroundOpacity, constantStyleValue,
@"backgroundOpacity should round-trip constant values.");

styleValue = [MGLStyleValue<NSNumber *> cameraFunctionValueWithStopType:MGLStyleFunctionStopTypeInterval
stops:@{@18: styleValue}
options:nil];
layer.backgroundOpacity = styleValue;
MGLStyleValue<NSNumber *> * functionStyleValue = [MGLStyleValue<NSNumber *> cameraFunctionValueWithStopType:MGLStyleFunctionStopTypeInterval
stops:@{@18: constantStyleValue}
options:nil];
layer.backgroundOpacity = functionStyleValue;

mbgl::style::IntervalStops<float> intervalStops = { {{18, 0xff}} };
propertyValue = mbgl::style::CameraFunction<float> { intervalStops };

XCTAssertEqual(rawLayer->getBackgroundOpacity(), propertyValue,
@"Setting backgroundOpacity to a function should update background-opacity.");
XCTAssertEqualObjects(layer.backgroundOpacity, styleValue,
XCTAssertEqualObjects(layer.backgroundOpacity, functionStyleValue,
@"backgroundOpacity should round-trip functions.");

layer.backgroundOpacity = nil;
Expand All @@ -96,32 +96,44 @@ - (void)testProperties {
@"background-pattern should be unset initially.");
MGLStyleValue<NSString *> *defaultStyleValue = layer.backgroundPattern;

MGLStyleValue<NSString *> *styleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Background Pattern"];
layer.backgroundPattern = styleValue;
MGLStyleValue<NSString *> *constantStyleValue = [MGLStyleValue<NSString *> valueWithRawValue:@"Background Pattern"];
layer.backgroundPattern = constantStyleValue;
mbgl::style::PropertyValue<std::string> propertyValue = { "Background Pattern" };
XCTAssertEqual(rawLayer->getBackgroundPattern(), propertyValue,
@"Setting backgroundPattern to a constant value should update background-pattern.");
XCTAssertEqualObjects(layer.backgroundPattern, styleValue,
XCTAssertEqualObjects(layer.backgroundPattern, constantStyleValue,
@"backgroundPattern should round-trip constant values.");

styleValue = [MGLStyleValue<NSString *> cameraFunctionValueWithStopType:MGLStyleFunctionStopTypeInterval
stops:@{@18: styleValue}
options:nil];
layer.backgroundPattern = styleValue;
MGLStyleValue<NSString *> * functionStyleValue = [MGLStyleValue<NSString *> cameraFunctionValueWithStopType:MGLStyleFunctionStopTypeInterval
stops:@{@18: constantStyleValue}
options:nil];
layer.backgroundPattern = functionStyleValue;

mbgl::style::IntervalStops<std::string> intervalStops = { {{18, "Background Pattern"}} };
propertyValue = mbgl::style::CameraFunction<std::string> { intervalStops };

XCTAssertEqual(rawLayer->getBackgroundPattern(), propertyValue,
@"Setting backgroundPattern to a function should update background-pattern.");
XCTAssertEqualObjects(layer.backgroundPattern, styleValue,
XCTAssertEqualObjects(layer.backgroundPattern, functionStyleValue,
@"backgroundPattern should round-trip functions.");

layer.backgroundPattern = nil;
XCTAssertTrue(rawLayer->getBackgroundPattern().isUndefined(),
@"Unsetting backgroundPattern should return background-pattern to the default value.");
XCTAssertEqualObjects(layer.backgroundPattern, defaultStyleValue,
@"backgroundPattern should return the default value after being unset.");

functionStyleValue = [MGLStyleValue<NSString *> sourceFunctionValueWithStopType:MGLStyleFunctionStopTypeIdentity
stops:nil
attributeName:@""
options:nil];
XCTAssertThrowsSpecificNamed(layer.backgroundPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");

functionStyleValue = [MGLStyleValue<NSString *> compositeFunctionValueWithStopType:MGLStyleFunctionStopTypeInterval
stops:@{@18: constantStyleValue}
attributeName:@""
options:nil];
XCTAssertThrowsSpecificNamed(layer.backgroundPattern = functionStyleValue, NSException, NSInvalidArgumentException, @"MGLStyleValue should raise an exception if it is applied to a property that cannot support it");
}
}

Expand Down
Loading

0 comments on commit 2fed47f

Please sign in to comment.