summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortobrun <tobrun.van.nuland@gmail.com>2019-11-01 10:13:22 +0100
committertobrun <tobrun.van.nuland@gmail.com>2019-11-01 10:13:22 +0100
commit5825afac23d5cfbab3127cf5bdd09f2e815de5f4 (patch)
tree314ca31ef9a4278e0798b3de9115db2892bd8dac
parentc94184c04742e935853a2e6b26d7fe1aa94c3250 (diff)
downloadqtlocation-mapboxgl-upstream/tvn-test-ci.tar.gz
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/BaseLayerTest.kt27
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/GesturesUiTestUtils.kt516
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/IconManagerResolver.java42
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapGestureDetectorTest.kt193
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java477
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxTest.java111
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt421
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/TransformTest.kt33
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/VisibleRegionTest.kt400
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/IconTest.java138
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerTest.java63
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolygonTest.java46
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolylineTest.java42
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/fragment/MapDialogFragmentTest.kt35
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/GeoJsonConversionTest.java148
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/LatLngBoundsTest.java65
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/CacheTest.kt88
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineManagerTest.kt124
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineUtilsTest.java41
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/render/RenderTest.java74
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceMapTest.kt59
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceStandaloneTest.kt116
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceTestUtils.kt59
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/string/UppperLowerCaseTest.java47
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java141
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java453
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CustomGeometrySourceTest.kt69
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ExpressionTest.java786
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java340
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java326
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/GeoJsonSourceTests.java189
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HeatmapLayerTest.java215
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HillshadeLayerTest.java223
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.kt75
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java172
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java493
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java240
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java370
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTimingTests.java27
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/StyleLoaderTest.java59
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java1313
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs195
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs132
43 files changed, 9183 insertions, 0 deletions
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/BaseLayerTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/BaseLayerTest.kt
new file mode 100644
index 0000000000..27c040fbb6
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/BaseLayerTest.kt
@@ -0,0 +1,27 @@
+package com.mapbox.mapboxsdk.maps
+
+import android.support.test.InstrumentationRegistry
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.AppCenter
+import com.mapbox.mapboxsdk.style.layers.Layer
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+abstract class BaseLayerTest : AppCenter() {
+ private lateinit var nativeMapView: NativeMap
+
+ companion object {
+ const val WIDTH = 500
+ const val HEIGHT = WIDTH
+ }
+
+ fun before() {
+ val context = InstrumentationRegistry.getContext()
+ nativeMapView = NativeMapView(context, false, null, null, NativeMapViewTest.DummyRenderer(context))
+ nativeMapView.resizeView(WIDTH, HEIGHT)
+ }
+
+ fun setupLayer(layer: Layer) {
+ nativeMapView.addLayer(layer)
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/GesturesUiTestUtils.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/GesturesUiTestUtils.kt
new file mode 100644
index 0000000000..f3af386457
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/GesturesUiTestUtils.kt
@@ -0,0 +1,516 @@
+package com.mapbox.mapboxsdk.maps
+
+import android.graphics.PointF
+import android.os.SystemClock
+import android.support.test.espresso.Espresso
+import android.support.test.espresso.InjectEventSecurityException
+import android.support.test.espresso.UiController
+import android.support.test.espresso.ViewAction
+import android.support.test.espresso.matcher.ViewMatchers
+import android.view.MotionEvent
+import android.view.View
+import org.hamcrest.Matcher
+
+object GesturesUiTestUtils {
+
+ private const val DEFAULT_GESTURE_DURATION = 500L
+
+ fun pinch(
+ startSpan: Float,
+ endSpan: Float,
+ center: PointF? = null,
+ duration: Long = DEFAULT_GESTURE_DURATION
+ ): ViewAction {
+ return object : ViewAction {
+ override fun getConstraints(): Matcher<View> {
+ return ViewMatchers.isEnabled()
+ }
+
+ override fun getDescription(): String = "Pinch $startSpan -> $endSpan"
+
+ override fun perform(uiController: UiController, view: View) {
+ var middlePosition = center
+ if (middlePosition == null) {
+ middlePosition = getCenterPointF(view)
+ }
+
+ val startPoint1 = PointF(middlePosition.x - startSpan / 2f, middlePosition.y)
+ val startPoint2 = PointF(middlePosition.x + startSpan / 2f, middlePosition.y)
+ val endPoint1 = PointF(middlePosition.x - endSpan / 2f, middlePosition.y)
+ val endPoint2 = PointF(middlePosition.x + endSpan / 2f, middlePosition.y)
+
+ performPinch(uiController, startPoint1, startPoint2, endPoint1, endPoint2, duration)
+ }
+ }
+ }
+
+ fun quickScale(
+ deltaY: Float,
+ startPoint: PointF? = null,
+ withVelocity: Boolean = true,
+ duration: Long = DEFAULT_GESTURE_DURATION,
+ interrupt: Boolean = false
+ ): ViewAction {
+ return object : ViewAction {
+ override fun getConstraints(): Matcher<View> = ViewMatchers.isEnabled()
+
+ override fun getDescription(): String = "quick scale ${deltaY}Y"
+
+ override fun perform(uiController: UiController, view: View) {
+ var middlePosition = startPoint
+ if (middlePosition == null) {
+ middlePosition = getCenterPointF(view)
+ }
+
+ val endPoint = PointF(middlePosition.x, middlePosition.y + deltaY)
+
+ performQuickScale(uiController, middlePosition, endPoint, withVelocity, duration, interrupt)
+ }
+ }
+ }
+
+ fun move(
+ deltaX: Float,
+ deltaY: Float,
+ startPoint: PointF? = null,
+ withVelocity: Boolean = true,
+ duration: Long = DEFAULT_GESTURE_DURATION
+ ): ViewAction {
+ return object : ViewAction {
+ override fun getConstraints(): Matcher<View> = ViewMatchers.isEnabled()
+
+ override fun getDescription(): String = "move ${deltaX}X, ${deltaY}Y"
+
+ override fun perform(uiController: UiController, view: View) {
+ var middlePosition = startPoint
+ if (middlePosition == null) {
+ middlePosition = getCenterPointF(view)
+ }
+
+ val endPoint = PointF(middlePosition.x + deltaX, middlePosition.y + deltaY)
+
+ performMove(uiController, middlePosition, endPoint, withVelocity, duration)
+ }
+ }
+ }
+
+ private fun getCenterPointF(view: View): PointF {
+ val locationOnScreen = IntArray(2)
+ view.getLocationOnScreen(locationOnScreen)
+ val viewHeight = view.height * view.scaleY
+ val viewWidth = view.width * view.scaleX
+ return PointF(
+ (locationOnScreen[0] + viewWidth / 2).toInt().toFloat(),
+ (locationOnScreen[1] + viewHeight / 2).toInt().toFloat()
+ )
+ }
+
+ // https://stackoverflow.com/a/46443628/9126211
+ private fun performPinch(
+ uiController: UiController,
+ startPoint1: PointF,
+ startPoint2: PointF,
+ endPoint1: PointF,
+ endPoint2: PointF,
+ duration: Long
+ ) {
+ val eventMinInterval: Long = 10
+ val startTime = SystemClock.uptimeMillis()
+ var eventTime = startTime
+ var event: MotionEvent
+ var eventX1: Float = startPoint1.x
+ var eventY1: Float = startPoint1.y
+ var eventX2: Float = startPoint2.x
+ var eventY2: Float = startPoint2.y
+
+ // Specify the property for the two touch points
+ val properties = arrayOfNulls<MotionEvent.PointerProperties>(2)
+ val pp1 = MotionEvent.PointerProperties()
+ pp1.id = 0
+ pp1.toolType = MotionEvent.TOOL_TYPE_FINGER
+ val pp2 = MotionEvent.PointerProperties()
+ pp2.id = 1
+ pp2.toolType = MotionEvent.TOOL_TYPE_FINGER
+
+ properties[0] = pp1
+ properties[1] = pp2
+
+ // Specify the coordinations of the two touch points
+ // NOTE: you MUST set the pressure and size value, or it doesn't work
+ val pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(2)
+ val pc1 = MotionEvent.PointerCoords()
+ pc1.x = eventX1
+ pc1.y = eventY1
+ pc1.pressure = 1f
+ pc1.size = 1f
+ val pc2 = MotionEvent.PointerCoords()
+ pc2.x = eventX2
+ pc2.y = eventY2
+ pc2.pressure = 1f
+ pc2.size = 1f
+ pointerCoords[0] = pc1
+ pointerCoords[1] = pc2
+
+ /*
+ * Events sequence of zoom gesture:
+ *
+ * 1. Send ACTION_DOWN event of one start point
+ * 2. Send ACTION_POINTER_DOWN of two start points
+ * 3. Send ACTION_MOVE of two middle points
+ * 4. Repeat step 3 with updated middle points (x,y), until reach the end points
+ * 5. Send ACTION_POINTER_UP of two end points
+ * 6. Send ACTION_UP of one end point
+ */
+
+ try {
+ // Step 1
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_DOWN, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+
+ // Step 2
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_POINTER_DOWN + (pp2.id shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), 2,
+ properties, pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+
+ // Step 3, 4
+ val moveEventNumber = duration / eventMinInterval
+
+ val stepX1: Float
+ val stepY1: Float
+ val stepX2: Float
+ val stepY2: Float
+
+ stepX1 = (endPoint1.x - startPoint1.x) / moveEventNumber
+ stepY1 = (endPoint1.y - startPoint1.y) / moveEventNumber
+ stepX2 = (endPoint2.x - startPoint2.x) / moveEventNumber
+ stepY2 = (endPoint2.y - startPoint2.y) / moveEventNumber
+
+ for (i in 0 until moveEventNumber) {
+ // Update the move events
+ eventTime += eventMinInterval
+ eventX1 += stepX1
+ eventY1 += stepY1
+ eventX2 += stepX2
+ eventY2 += stepY2
+
+ pc1.x = eventX1
+ pc1.y = eventY1
+ pc2.x = eventX2
+ pc2.y = eventY2
+
+ pointerCoords[0] = pc1
+ pointerCoords[1] = pc2
+
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_MOVE, 2, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+ }
+
+ // Step 5
+ pc1.x = endPoint1.x
+ pc1.y = endPoint1.y
+ pc2.x = endPoint2.x
+ pc2.y = endPoint2.y
+ pointerCoords[0] = pc1
+ pointerCoords[1] = pc2
+
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_POINTER_UP + (pp2.id shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), 2, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+
+ // Step 6
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_UP, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+ } catch (ex: InjectEventSecurityException) {
+ throw RuntimeException("Could not perform pinch", ex)
+ }
+ }
+
+ private fun performQuickScale(
+ uiController: UiController,
+ startPoint: PointF,
+ endPoint: PointF,
+ withVelocity: Boolean,
+ duration: Long,
+ interrupt: Boolean
+ ) {
+ val eventMinInterval: Long = 10
+ val tapDownMinInterval: Long = 40 // ViewConfiguration#DOUBLE_TAP_MIN_TIME = 40
+ val startTime = SystemClock.uptimeMillis()
+ var eventTime = startTime
+ var event: MotionEvent
+ var eventX1: Float = startPoint.x
+ var eventY1: Float = startPoint.y
+
+ var properties = arrayOfNulls<MotionEvent.PointerProperties>(1)
+ val pp1 = MotionEvent.PointerProperties()
+ pp1.id = 0
+ pp1.toolType = MotionEvent.TOOL_TYPE_FINGER
+ properties[0] = pp1
+
+ var pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(1)
+ val pc1 = MotionEvent.PointerCoords()
+ pc1.x = eventX1
+ pc1.y = eventY1
+ pc1.pressure = 1f
+ pc1.size = 1f
+ pointerCoords[0] = pc1
+
+ /*
+ * Events sequence of quick scale gesture:
+ *
+ * 1. Send ACTION_DOWN
+ * 2. Send ACTION_UP
+ * 3. Send ACTION_DOWN
+ * 4. Send ACTION_MOVE with updated middle points (x,y), until reach the end points
+ * 5. Send ACTION_UP of one end point
+ */
+ try {
+ // Step 1
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_DOWN, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+
+ // Step 2
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_UP, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+
+ // Step 3
+ eventTime += tapDownMinInterval
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_DOWN, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+
+ // Step 4
+ val moveEventNumber = duration / eventMinInterval
+
+ val stepX1: Float
+ val stepY1: Float
+
+ stepX1 = (endPoint.x - startPoint.x) / moveEventNumber
+ stepY1 = (endPoint.y - startPoint.y) / moveEventNumber
+
+ var interrupted = false
+
+ for (i in 0 until moveEventNumber) {
+ // Update the move events
+ eventTime += eventMinInterval
+ eventX1 += stepX1
+ eventY1 += stepY1
+
+ pc1.x = eventX1
+ pc1.y = eventY1
+
+ pointerCoords[0] = pc1
+
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_MOVE, if (interrupted) 2 else 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+
+ if (interrupt && i == moveEventNumber / 2) {
+ // Specify the property for the two touch points
+ properties = arrayOfNulls<MotionEvent.PointerProperties>(2)
+ val pp2 = MotionEvent.PointerProperties()
+ pp2.id = 1
+ pp2.toolType = MotionEvent.TOOL_TYPE_FINGER
+
+ properties[0] = pp1
+ properties[1] = pp2
+
+ // Specify the coordinations of the two touch points
+ // NOTE: you MUST set the pressure and size value, or it doesn't work
+ pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(2)
+ val pc2 = MotionEvent.PointerCoords()
+ pc2.x = startPoint.x
+ pc2.y = startPoint.y
+ pc2.pressure = 1f
+ pc2.size = 1f
+ pointerCoords[0] = pc1
+ pointerCoords[1] = pc2
+
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_POINTER_DOWN + (pp2.id shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), 2,
+ properties, pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+ interrupted = true
+ }
+ }
+
+ if (!withVelocity) {
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_MOVE, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+ }
+
+ // Step 5
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_UP, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+ } catch (ex: InjectEventSecurityException) {
+ throw RuntimeException("Could not perform quick scale", ex)
+ }
+ }
+
+ private fun performMove(
+ uiController: UiController,
+ startPoint: PointF,
+ endPoint: PointF,
+ withVelocity: Boolean,
+ duration: Long
+ ) {
+ val eventMinInterval: Long = 10
+ val startTime = SystemClock.uptimeMillis()
+ var eventTime = startTime
+ var event: MotionEvent
+ var eventX1: Float = startPoint.x
+ var eventY1: Float = startPoint.y
+
+ val properties = arrayOfNulls<MotionEvent.PointerProperties>(1)
+ val pp1 = MotionEvent.PointerProperties()
+ pp1.id = 0
+ pp1.toolType = MotionEvent.TOOL_TYPE_FINGER
+ properties[0] = pp1
+
+ val pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(1)
+ val pc1 = MotionEvent.PointerCoords()
+ pc1.x = eventX1
+ pc1.y = eventY1
+ pc1.pressure = 1f
+ pc1.size = 1f
+ pointerCoords[0] = pc1
+
+ /*
+ * Events sequence of move gesture:
+ *
+ * 1. Send ACTION_DOWN
+ * 2. Send ACTION_MOVE with updated middle points (x,y), until reach the end points
+ * 3. Send ACTION_UP
+ */
+ try {
+ // Step 1
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_DOWN, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+
+ // Step 2
+ val moveEventNumber = duration / eventMinInterval
+
+ val stepX1: Float
+ val stepY1: Float
+
+ stepX1 = (endPoint.x - startPoint.x) / moveEventNumber
+ stepY1 = (endPoint.y - startPoint.y) / moveEventNumber
+
+ for (i in 0 until moveEventNumber) {
+ // Update the move events
+ eventTime += eventMinInterval
+ eventX1 += stepX1
+ eventY1 += stepY1
+
+ pc1.x = eventX1
+ pc1.y = eventY1
+
+ pointerCoords[0] = pc1
+
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_MOVE, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+ }
+
+ if (!withVelocity) {
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_MOVE, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+ }
+
+ // Step 3
+ eventTime += eventMinInterval
+ event = MotionEvent.obtain(
+ startTime, eventTime,
+ MotionEvent.ACTION_UP, 1, properties,
+ pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
+ )
+ injectMotionEventToUiController(uiController, event)
+ } catch (ex: InjectEventSecurityException) {
+ throw RuntimeException("Could not perform quick scale", ex)
+ }
+ }
+
+ /**
+ * Safely call uiController.injectMotionEvent(event): Detect any error and "convert" it to an
+ * IllegalStateException
+ */
+ @Throws(InjectEventSecurityException::class)
+ private fun injectMotionEventToUiController(uiController: UiController, event: MotionEvent) {
+ val injectEventSucceeded = uiController.injectMotionEvent(event)
+ if (!injectEventSucceeded) {
+ throw IllegalStateException("Error performing event $event")
+ }
+ }
+}
+
+fun Int.loopFor(millis: Long) {
+ Espresso.onView(ViewMatchers.withId(this)).perform(object : ViewAction {
+ override fun getDescription(): String = "waiting for $millis"
+
+ override fun getConstraints(): Matcher<View> = ViewMatchers.isEnabled()
+
+ override fun perform(uiController: UiController?, view: View?) {
+ uiController?.loopMainThreadForAtLeast(millis)
+ }
+ })
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/IconManagerResolver.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/IconManagerResolver.java
new file mode 100644
index 0000000000..3e226a7ec5
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/IconManagerResolver.java
@@ -0,0 +1,42 @@
+package com.mapbox.mapboxsdk.maps;
+
+import com.mapbox.mapboxsdk.annotations.Icon;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+import timber.log.Timber;
+
+public class IconManagerResolver {
+
+ private IconManager iconManager;
+
+ public IconManagerResolver(MapboxMap mapboxMap) {
+ try {
+ Field annotationManagerField = MapboxMap.class.getDeclaredField("annotationManager");
+ annotationManagerField.setAccessible(true);
+ AnnotationManager annotationManager = (AnnotationManager) annotationManagerField.get(mapboxMap);
+
+ Field iconManagerField = AnnotationManager.class.getDeclaredField("iconManager");
+ iconManagerField.setAccessible(true);
+ iconManager = (IconManager) iconManagerField.get(annotationManager);
+ } catch (Exception exception) {
+ Timber.e(exception, "Could not create IconManagerResolver, unable to reflect.");
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public Map<Icon, Integer> getIconMap() {
+ try {
+ Field field = IconManager.class.getDeclaredField("iconMap");
+ field.setAccessible(true);
+ return (Map<Icon, Integer>) field.get(iconManager);
+ } catch (NoSuchFieldException exception) {
+ Timber.e(exception, "Could not getIconMap, unable to reflect.");
+ } catch (IllegalAccessException exception) {
+ Timber.e(exception, "Could not getIconMap, unable to reflect.");
+ }
+ return new HashMap<>();
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapGestureDetectorTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapGestureDetectorTest.kt
new file mode 100644
index 0000000000..525c576df4
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapGestureDetectorTest.kt
@@ -0,0 +1,193 @@
+package com.mapbox.mapboxsdk.maps
+
+import android.support.test.espresso.Espresso.onView
+import android.support.test.espresso.matcher.ViewMatchers.withId
+import com.mapbox.mapboxsdk.camera.CameraPosition
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
+import com.mapbox.mapboxsdk.constants.MapboxConstants
+import com.mapbox.mapboxsdk.geometry.LatLng
+import com.mapbox.mapboxsdk.maps.GesturesUiTestUtils.move
+import com.mapbox.mapboxsdk.maps.GesturesUiTestUtils.quickScale
+import com.mapbox.mapboxsdk.testapp.R
+import com.mapbox.mapboxsdk.testapp.activity.BaseTest
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.SimpleMapActivity
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+
+class MapGestureDetectorTest : BaseTest() {
+ override fun getActivityClass() = SimpleMapActivity::class.java
+
+ private var maxWidth: Int = 0
+ private var maxHeight: Int = 0
+
+ @Before
+ fun setup() {
+ maxWidth = mapView.width
+ maxHeight = mapView.height
+ }
+
+ @Test
+ fun sanity_quickZoom() {
+ validateTestSetup()
+ var initialZoom: Double? = null
+ rule.runOnUiThread {
+ initialZoom = mapboxMap.cameraPosition.zoom
+ }
+ onView(withId(R.id.mapView)).perform(quickScale(maxHeight / 2f, withVelocity = false))
+ rule.runOnUiThread {
+ Assert.assertTrue(mapboxMap.cameraPosition.zoom > initialZoom!!)
+ }
+ }
+
+ @Test
+ fun quickZoomDisabled_phantomQuickZoom_moveStillEnabled_15091() {
+ // regression test for https://github.com/mapbox/mapbox-gl-native/issues/15091
+ validateTestSetup()
+ var initialCameraPosition: CameraPosition? = null
+ rule.runOnUiThread {
+ // zoom in so we can move vertically
+ mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.0))
+ initialCameraPosition = mapboxMap.cameraPosition
+ mapboxMap.uiSettings.isQuickZoomGesturesEnabled = false
+ }
+
+ onView(withId(R.id.mapView)).perform(quickScale(maxHeight / 2f))
+ rule.runOnUiThread {
+ // camera did not move
+ Assert.assertEquals(initialCameraPosition!!, mapboxMap.cameraPosition)
+ }
+
+ // move to expected target
+ onView(withId(R.id.mapView)).perform(move(-maxWidth / 2f, -maxHeight / 2f, withVelocity = false))
+ rule.runOnUiThread {
+ Assert.assertNotEquals(initialCameraPosition!!.target.latitude, mapboxMap.cameraPosition.target.latitude, 1.0)
+ Assert.assertNotEquals(initialCameraPosition!!.target.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
+ }
+ }
+
+ @Test
+ fun quickZoom_doNotMove_14227() {
+ // test for https://github.com/mapbox/mapbox-gl-native/issues/14227
+ validateTestSetup()
+ var initialTarget: LatLng? = null
+ rule.runOnUiThread {
+ initialTarget = mapboxMap.cameraPosition.target
+ }
+
+ onView(withId(R.id.mapView)).perform(quickScale(maxHeight / 2f))
+ rule.runOnUiThread {
+ // camera did not move
+ Assert.assertEquals(initialTarget!!.latitude, mapboxMap.cameraPosition.target.latitude, 1.0)
+ Assert.assertEquals(initialTarget!!.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
+ }
+ }
+
+ @Test
+ fun quickZoom_interrupted_moveStillEnabled_14598() {
+ // test for https://github.com/mapbox/mapbox-gl-native/issues/14598
+ validateTestSetup()
+ onView(withId(R.id.mapView)).perform(quickScale(maxHeight / 2f, interrupt = true))
+
+ var initialCameraPosition: CameraPosition? = null
+ rule.runOnUiThread {
+ // zoom in so we can move vertically
+ mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.0))
+ initialCameraPosition = mapboxMap.cameraPosition
+ mapboxMap.uiSettings.isQuickZoomGesturesEnabled = false
+ }
+
+ // move to expected target
+ onView(withId(R.id.mapView)).perform(move(-maxWidth / 2f, -maxHeight / 2f, withVelocity = false))
+ rule.runOnUiThread {
+ Assert.assertNotEquals(initialCameraPosition!!.target.latitude, mapboxMap.cameraPosition.target.latitude, 1.0)
+ Assert.assertNotEquals(initialCameraPosition!!.target.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
+ }
+ }
+
+ @Test
+ fun quickZoom_ignoreDoubleTap() {
+ // test for https://github.com/mapbox/mapbox-gl-native/issues/14013
+ validateTestSetup()
+ var initialZoom: Double? = null
+ rule.runOnUiThread {
+ mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(2.0))
+ initialZoom = mapboxMap.cameraPosition.zoom
+ }
+ onView(withId(R.id.mapView)).perform(quickScale(-(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold * 2), withVelocity = false, duration = 1000L))
+ R.id.mapView.loopFor(MapboxConstants.ANIMATION_DURATION.toLong())
+ rule.runOnUiThread {
+ Assert.assertTrue(mapboxMap.cameraPosition.zoom < initialZoom!!)
+ }
+ }
+
+ @Test
+ fun doubleTap_minimalMovement() {
+ validateTestSetup()
+ var initialZoom: Double? = null
+ rule.runOnUiThread {
+ initialZoom = mapboxMap.cameraPosition.zoom
+ }
+ onView(withId(R.id.mapView)).perform(quickScale(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold / 2, withVelocity = false, duration = 50L))
+ R.id.mapView.loopFor(MapboxConstants.ANIMATION_DURATION.toLong())
+ rule.runOnUiThread {
+ Assert.assertEquals(initialZoom!! + 1, mapboxMap.cameraPosition.zoom, 0.1)
+ }
+ }
+
+ @Test
+ fun doubleTap_overMaxThreshold_ignore_14013() {
+ // test for https://github.com/mapbox/mapbox-gl-native/issues/14013
+ validateTestSetup()
+ var initialZoom: Double? = null
+ rule.runOnUiThread {
+ initialZoom = mapboxMap.cameraPosition.zoom
+ mapboxMap.uiSettings.isQuickZoomGesturesEnabled = false
+ }
+ onView(withId(R.id.mapView)).perform(quickScale(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold * 2, withVelocity = false, duration = 50L))
+ R.id.mapView.loopFor(MapboxConstants.ANIMATION_DURATION.toLong())
+ rule.runOnUiThread {
+ Assert.assertEquals(initialZoom!!, mapboxMap.cameraPosition.zoom, 0.01)
+ }
+ }
+
+ @Test
+ fun doubleTap_interrupted_moveStillEnabled() {
+ validateTestSetup()
+
+ rule.runOnUiThread {
+ mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.0))
+ }
+
+ onView(withId(R.id.mapView)).perform(quickScale(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold / 2, withVelocity = false, duration = 50L, interrupt = true))
+
+ var initialCameraPosition: CameraPosition? = null
+ rule.runOnUiThread {
+ // zoom in so we can move vertically
+ mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.0))
+ initialCameraPosition = mapboxMap.cameraPosition
+ mapboxMap.uiSettings.isQuickZoomGesturesEnabled = false
+ }
+
+ // move to expected target
+ onView(withId(R.id.mapView)).perform(move(-maxWidth / 2f, -maxHeight / 2f, withVelocity = false))
+ rule.runOnUiThread {
+ Assert.assertNotEquals(initialCameraPosition!!.target.latitude, mapboxMap.cameraPosition.target.latitude, 1.0)
+ Assert.assertNotEquals(initialCameraPosition!!.target.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
+ }
+ }
+
+ @Test
+ fun quickZoom_roundTripping() {
+ validateTestSetup()
+ rule.runOnUiThread {
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(51.0, 16.0), 3.0))
+ }
+ onView(withId(R.id.mapView)).perform(quickScale(300f, withVelocity = false, duration = 750L))
+ onView(withId(R.id.mapView)).perform(quickScale(-300f, withVelocity = false, duration = 750L))
+
+ rule.runOnUiThread {
+ Assert.assertEquals(3.0, mapboxMap.cameraPosition.zoom, 0.0001)
+ }
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
new file mode 100644
index 0000000000..00ec1fe601
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
@@ -0,0 +1,477 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.graphics.Color;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.view.View;
+import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
+import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.MarkerOptions;
+import com.mapbox.mapboxsdk.annotations.Polygon;
+import com.mapbox.mapboxsdk.annotations.PolygonOptions;
+import com.mapbox.mapboxsdk.annotations.Polyline;
+import com.mapbox.mapboxsdk.annotations.PolylineOptions;
+import com.mapbox.mapboxsdk.exceptions.InvalidMarkerPositionException;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
+import org.hamcrest.Matcher;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * This test is responsible for testing the public API.
+ * <p>
+ * Methods executed on MapboxMap are called from a ViewAction to ensure correct synchronisation
+ * with the application UI-thread.
+ * </p>
+ * @deprecated remove this file when removing deprecated annotations
+ */
+@Deprecated
+public class MapboxMapTest extends EspressoTest {
+
+ //
+ // InfoWindow
+ //
+
+ @Test
+ public void testConcurrentInfoWindowEnabled() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(true);
+ assertTrue("ConcurrentWindows should be true", mapboxMap.isAllowConcurrentMultipleOpenInfoWindows());
+ }));
+ }
+
+ @Test
+ public void testConcurrentInfoWindowDisabled() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(false);
+ assertFalse("ConcurrentWindows should be false", mapboxMap.isAllowConcurrentMultipleOpenInfoWindows());
+ }));
+ }
+
+ @Test
+ public void testInfoWindowAdapter() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MapboxMap.InfoWindowAdapter infoWindowAdapter = marker -> null;
+ mapboxMap.setInfoWindowAdapter(infoWindowAdapter);
+ assertEquals("InfoWindowAdpter should be the same", infoWindowAdapter, mapboxMap.getInfoWindowAdapter());
+ }));
+ }
+
+ //
+ // Annotations
+ //
+
+ @Test
+ public void testAddMarker() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ assertTrue("Marker should be contained", mapboxMap.getMarkers().contains(marker));
+ }));
+ }
+
+ @Test(expected = InvalidMarkerPositionException.class)
+ public void testAddMarkerInvalidPosition() {
+ new MarkerOptions().getMarker();
+ }
+
+ @Test
+ public void testAddMarkers() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions1 = new MarkerOptions().position(new LatLng()).title("a");
+ MarkerOptions markerOptions2 = new MarkerOptions().position(new LatLng()).title("b");
+ markerList.add(markerOptions1);
+ markerList.add(markerOptions2);
+ List<Marker> markers = mapboxMap.addMarkers(markerList);
+ assertEquals("Markers size should be 2", 2, mapboxMap.getMarkers().size());
+ assertTrue(mapboxMap.getMarkers().contains(markers.get(0)));
+ assertTrue(mapboxMap.getMarkers().contains(markers.get(1)));
+ }));
+ }
+
+ @Test
+ public void testAddMarkersEmpty() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ mapboxMap.addMarkers(markerList);
+ assertEquals("Markers size should be 0", 0, mapboxMap.getMarkers().size());
+ }));
+ }
+
+ @Test
+ public void testAddMarkersSingleMarker() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions = new MarkerOptions().title("a").position(new LatLng());
+ markerList.add(markerOptions);
+ List<Marker> markers = mapboxMap.addMarkers(markerList);
+ assertEquals("Markers size should be 1", 1, mapboxMap.getMarkers().size());
+ assertTrue(mapboxMap.getMarkers().contains(markers.get(0)));
+ }));
+ }
+
+ @Test
+ public void testAddPolygon() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ PolygonOptions polygonOptions = new PolygonOptions().add(new LatLng());
+ Polygon polygon = mapboxMap.addPolygon(polygonOptions);
+ assertTrue("Polygon should be contained", mapboxMap.getPolygons().contains(polygon));
+ }));
+ }
+
+ @Test
+ public void testAddEmptyPolygon() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ PolygonOptions polygonOptions = new PolygonOptions();
+ Polygon polygon = mapboxMap.addPolygon(polygonOptions);
+ assertTrue("Polygon should be ignored", !mapboxMap.getPolygons().contains(polygon));
+ }));
+ }
+
+ @Test
+ public void testAddPolygons() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<PolygonOptions> polygonList = new ArrayList<>();
+ PolygonOptions polygonOptions1 = new PolygonOptions().fillColor(Color.BLACK).add(new LatLng());
+ PolygonOptions polygonOptions2 = new PolygonOptions().fillColor(Color.WHITE).add(new LatLng());
+ PolygonOptions polygonOptions3 = new PolygonOptions();
+ polygonList.add(polygonOptions1);
+ polygonList.add(polygonOptions2);
+ polygonList.add(polygonOptions3);
+ mapboxMap.addPolygons(polygonList);
+ assertEquals("Polygons size should be 2", 2, mapboxMap.getPolygons().size());
+ assertTrue(mapboxMap.getPolygons().contains(polygonOptions1.getPolygon()));
+ assertTrue(mapboxMap.getPolygons().contains(polygonOptions2.getPolygon()));
+ assertTrue("Polygon should be ignored", !mapboxMap.getPolygons().contains(polygonOptions3.getPolygon()));
+ }));
+ }
+
+ @Test
+ public void addPolygonsEmpty() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ mapboxMap.addPolygons(new ArrayList<PolygonOptions>());
+ assertEquals("Polygons size should be 0", 0, mapboxMap.getPolygons().size());
+ }));
+ }
+
+ @Test
+ public void addPolygonsSingle() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<PolygonOptions> polygonList = new ArrayList<>();
+ PolygonOptions polygonOptions = new PolygonOptions().fillColor(Color.BLACK).add(new LatLng());
+ polygonList.add(polygonOptions);
+ mapboxMap.addPolygons(polygonList);
+ assertEquals("Polygons size should be 1", 1, mapboxMap.getPolygons().size());
+ assertTrue(mapboxMap.getPolygons().contains(polygonOptions.getPolygon()));
+ }));
+ }
+
+ @Test
+ public void testAddPolyline() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ PolylineOptions polylineOptions = new PolylineOptions().add(new LatLng());
+ Polyline polyline = mapboxMap.addPolyline(polylineOptions);
+ assertTrue("Polyline should be contained", mapboxMap.getPolylines().contains(polyline));
+ }));
+ }
+
+ @Test
+ public void testAddEmptyPolyline() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ PolylineOptions polylineOptions = new PolylineOptions();
+ Polyline polyline = mapboxMap.addPolyline(polylineOptions);
+ assertTrue("Polyline should be ignored", !mapboxMap.getPolylines().contains(polyline));
+ }));
+ }
+
+ @Test
+ public void testAddPolylines() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<PolylineOptions> polylineList = new ArrayList<>();
+ PolylineOptions polygonOptions1 = new PolylineOptions().color(Color.BLACK).add(new LatLng());
+ PolylineOptions polygonOptions2 = new PolylineOptions().color(Color.WHITE).add(new LatLng());
+ PolylineOptions polygonOptions3 = new PolylineOptions();
+ polylineList.add(polygonOptions1);
+ polylineList.add(polygonOptions2);
+ polylineList.add(polygonOptions3);
+ mapboxMap.addPolylines(polylineList);
+ assertEquals("Polygons size should be 2", 2, mapboxMap.getPolylines().size());
+ assertTrue(mapboxMap.getPolylines().contains(polygonOptions1.getPolyline()));
+ assertTrue(mapboxMap.getPolylines().contains(polygonOptions2.getPolyline()));
+ assertTrue(
+ "Polyline should be ignored", !mapboxMap.getPolylines().contains(polygonOptions3.getPolyline())
+ );
+ }));
+ }
+
+ @Test
+ public void testAddPolylinesEmpty() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ mapboxMap.addPolylines(new ArrayList<PolylineOptions>());
+ assertEquals("Polygons size should be 0", 0, mapboxMap.getPolylines().size());
+ }));
+ }
+
+ @Test
+ public void testAddPolylinesSingle() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<PolylineOptions> polylineList = new ArrayList<>();
+ PolylineOptions polygonOptions = new PolylineOptions().color(Color.BLACK).add(new LatLng());
+ polylineList.add(polygonOptions);
+ mapboxMap.addPolylines(polylineList);
+ assertEquals("Polygons size should be 1", 1, mapboxMap.getPolylines().size());
+ assertTrue(mapboxMap.getPolylines().contains(polygonOptions.getPolyline()));
+ }));
+ }
+
+ @Test
+ public void testRemoveMarker() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ mapboxMap.removeMarker(marker);
+ assertTrue("Markers should be empty", mapboxMap.getMarkers().isEmpty());
+ }));
+ }
+
+ @Test
+ public void testRemovePolygon() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ PolygonOptions polygonOptions = new PolygonOptions();
+ Polygon polygon = mapboxMap.addPolygon(polygonOptions);
+ mapboxMap.removePolygon(polygon);
+ assertTrue("Polygons should be empty", mapboxMap.getPolylines().isEmpty());
+ }));
+ }
+
+ @Test
+ public void testRemovePolyline() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ PolylineOptions polylineOptions = new PolylineOptions();
+ Polyline polyline = mapboxMap.addPolyline(polylineOptions);
+ mapboxMap.removePolyline(polyline);
+ assertTrue("Polylines should be empty", mapboxMap.getPolylines().isEmpty());
+ }));
+ }
+
+ @Test
+ public void testRemoveAnnotation() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ mapboxMap.removeAnnotation(marker);
+ assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
+ }));
+ }
+
+ @Test
+ public void testRemoveAnnotationById() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ mapboxMap.addMarker(markerOptions);
+ // id will always be 0 in unit tests
+ mapboxMap.removeAnnotation(0);
+ assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
+ }));
+ }
+
+ @Test
+ public void testRemoveAnnotations() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
+ MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
+ markerList.add(markerOptions1);
+ markerList.add(markerOptions2);
+ mapboxMap.addMarkers(markerList);
+ mapboxMap.removeAnnotations();
+ assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
+ }));
+ }
+
+ @Test
+ public void testClear() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
+ MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
+ markerList.add(markerOptions1);
+ markerList.add(markerOptions2);
+ mapboxMap.addMarkers(markerList);
+ mapboxMap.clear();
+ assertTrue("Annotations should be empty", mapboxMap.getAnnotations().isEmpty());
+ }));
+ }
+
+ @Test
+ public void testRemoveAnnotationsByList() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions1 = new MarkerOptions().title("a").position(new LatLng());
+ MarkerOptions markerOptions2 = new MarkerOptions().title("b").position(new LatLng());
+ markerList.add(markerOptions1);
+ markerList.add(markerOptions2);
+ List<Marker> markers = mapboxMap.addMarkers(markerList);
+ Marker marker = mapboxMap.addMarker(new MarkerOptions().position(new LatLng()).title("c"));
+ mapboxMap.removeAnnotations(markers);
+ assertTrue("Annotations should not be empty", mapboxMap.getAnnotations().size() == 1);
+ assertTrue("Marker should be contained", mapboxMap.getAnnotations().contains(marker));
+ }));
+ }
+
+ @Test
+ public void testGetAnnotationById() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker initialMarker = mapboxMap.addMarker(markerOptions);
+ Marker retrievedMarker = (Marker) mapboxMap.getAnnotation(0);
+ assertEquals("Markers should match", initialMarker, retrievedMarker);
+ }));
+ }
+
+ @Test
+ public void testGetAnnotations() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(
+ new MapboxMapAction((uiController, view) ->
+ assertNotNull("Annotations should be non null", mapboxMap.getAnnotations()))
+ );
+ }
+
+ @Test
+ public void testGetMarkers() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(
+ new MapboxMapAction((uiController, view) ->
+ assertNotNull("Markers should be non null", mapboxMap.getMarkers()))
+ );
+ }
+
+ @Test
+ public void testGetPolygons() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) ->
+ assertNotNull("Polygons should be non null", mapboxMap.getPolygons()))
+ );
+ }
+
+ @Test
+ public void testGetPolylines() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) ->
+ assertNotNull("Polylines should be non null", mapboxMap.getPolylines()))
+ );
+ }
+
+ @Test
+ public void testGetSelectedMarkers() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) ->
+ assertNotNull("Selected markers should be non null", mapboxMap.getSelectedMarkers()))
+ );
+ }
+
+ @Test
+ public void testSelectMarker() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ mapboxMap.selectMarker(marker);
+ assertTrue("Marker should be contained", mapboxMap.getSelectedMarkers().contains(marker));
+ }));
+ }
+
+ @Test
+ public void testDeselectMarker() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker = mapboxMap.addMarker(markerOptions);
+ mapboxMap.selectMarker(marker);
+ mapboxMap.deselectMarker(marker);
+ assertTrue("Selected markers should be empty", mapboxMap.getSelectedMarkers().isEmpty());
+ }));
+ }
+
+ @Test
+ public void testDeselectMarkers() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng());
+ Marker marker1 = mapboxMap.addMarker(markerOptions);
+ Marker marker2 = mapboxMap.addMarker(markerOptions);
+ mapboxMap.selectMarker(marker1);
+ mapboxMap.selectMarker(marker2);
+ mapboxMap.deselectMarkers();
+ assertTrue("Selected markers should be empty", mapboxMap.getSelectedMarkers().isEmpty());
+ }));
+ }
+
+ public class MapboxMapAction implements ViewAction {
+
+ private InvokeViewAction invokeViewAction;
+
+ MapboxMapAction(InvokeViewAction invokeViewAction) {
+ this.invokeViewAction = invokeViewAction;
+ }
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ invokeViewAction.onViewAction(uiController, view);
+ }
+ }
+
+ interface InvokeViewAction {
+ void onViewAction(UiController uiController, View view);
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxTest.java
new file mode 100644
index 0000000000..5b737dd4d2
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxTest.java
@@ -0,0 +1,111 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.AppCenter;
+import com.mapbox.mapboxsdk.Mapbox;
+import com.mapbox.mapboxsdk.exceptions.MapboxConfigurationException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.assertTrue;
+
+@RunWith(AndroidJUnit4.class)
+public class MapboxTest extends AppCenter {
+
+ private static final String ACCESS_TOKEN = "pk.0000000001";
+ private static final String ACCESS_TOKEN_2 = "pk.0000000002";
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private String realToken;
+
+ @Before
+ public void setup() {
+ realToken = Mapbox.getAccessToken();
+ }
+
+ @Test
+ @UiThreadTest
+ public void testConnected() {
+ assertTrue(Mapbox.isConnected());
+
+ // test manual connectivity
+ Mapbox.setConnected(true);
+ assertTrue(Mapbox.isConnected());
+ Mapbox.setConnected(false);
+ assertFalse(Mapbox.isConnected());
+
+ // reset to Android connectivity
+ Mapbox.setConnected(null);
+ assertTrue(Mapbox.isConnected());
+ }
+
+ @Test
+ @UiThreadTest
+ public void setAccessToken() {
+ Mapbox.setAccessToken(ACCESS_TOKEN);
+ assertSame(ACCESS_TOKEN, Mapbox.getAccessToken());
+ Mapbox.setAccessToken(ACCESS_TOKEN_2);
+ assertSame(ACCESS_TOKEN_2, Mapbox.getAccessToken());
+ }
+
+ @Test
+ @UiThreadTest
+ public void setInvalidAccessToken() {
+ final String invalidAccessToken = "xyz";
+ expectedException.expect(MapboxConfigurationException.class);
+ expectedException.expectMessage(
+ "A valid access token parameter is required when using a Mapbox service."
+ + "\nPlease see https://www.mapbox.com/help/create-api-access-token/ to learn how to create one."
+ + "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens."
+ + "Currently provided token is: " + invalidAccessToken
+ );
+
+ Mapbox.setAccessToken(invalidAccessToken);
+ assertNull(Mapbox.getTelemetry());
+ Mapbox.getSkuToken();
+ }
+
+ @Test
+ @UiThreadTest
+ public void setNullAccessToken() {
+ expectedException.expect(MapboxConfigurationException.class);
+ expectedException.expectMessage(
+ "A valid access token parameter is required when using a Mapbox service."
+ + "\nPlease see https://www.mapbox.com/help/create-api-access-token/ to learn how to create one."
+ + "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens."
+ + "Currently provided token is: " + null
+ );
+
+ Mapbox.setAccessToken(null);
+ assertNull(Mapbox.getTelemetry());
+ Mapbox.getSkuToken();
+ }
+
+ @Test
+ @UiThreadTest
+ public void setValidAccessToken() {
+ final String invalidAccessToken = "xyz";
+ Mapbox.setAccessToken(invalidAccessToken);
+ Mapbox.setAccessToken(ACCESS_TOKEN);
+ assertNotNull(Mapbox.getTelemetry());
+ assertNotNull(Mapbox.getSkuToken());
+ }
+
+ @After
+ public void tearDown() {
+ Mapbox.setAccessToken(realToken);
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt
new file mode 100644
index 0000000000..dc313b5f64
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/NativeMapViewTest.kt
@@ -0,0 +1,421 @@
+package com.mapbox.mapboxsdk.maps
+
+import android.content.Context
+import android.graphics.PointF
+import android.support.test.InstrumentationRegistry
+import android.support.test.annotation.UiThreadTest
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.AppCenter
+import com.mapbox.mapboxsdk.camera.CameraPosition
+import com.mapbox.mapboxsdk.geometry.LatLng
+import com.mapbox.mapboxsdk.geometry.LatLngBounds
+import com.mapbox.mapboxsdk.geometry.ProjectedMeters
+import com.mapbox.mapboxsdk.maps.renderer.MapRenderer
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions
+import com.mapbox.mapboxsdk.testapp.utils.TestConstants
+import junit.framework.Assert.*
+import org.junit.After
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class NativeMapViewTest : AppCenter() {
+
+ private lateinit var nativeMapView: NativeMap
+
+ companion object {
+ const val DELTA = 0.000001
+ const val DELTA_BIG = 1.0
+ const val BEARING_TEST = 60.0
+ const val PITCH_TEST = 40.0
+ const val ZOOM_TEST = 16.0
+ val PADDING_TEST = doubleArrayOf(80.0, 150.0, 0.0, 0.0)
+ const val WIDTH = 500
+ const val HEIGHT = WIDTH
+ val LATLNG_TEST = LatLng(12.0, 34.0)
+ }
+
+ @Before
+ @UiThreadTest
+ fun before() {
+ val context = InstrumentationRegistry.getContext()
+ nativeMapView = NativeMapView(context, 2.0f, false, null, null, DummyRenderer(context))
+ nativeMapView.resizeView(WIDTH, HEIGHT)
+ }
+
+ @After
+ @UiThreadTest
+ fun after() {
+ nativeMapView.destroy()
+ }
+
+ @Test
+ @UiThreadTest
+ fun testSetStyleUrl() {
+ val expected = Style.DARK
+ nativeMapView.styleUri = expected
+ val actual = nativeMapView.styleUri
+ assertEquals("Style URL should match", expected, actual)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testSetStyleJson() {
+ val expected = "{}"
+ nativeMapView.styleJson = expected
+ val actual = nativeMapView.styleJson
+ assertEquals("Style JSON should match", expected, actual)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testBearing() {
+ val expected = BEARING_TEST
+ nativeMapView.setBearing(expected, 0)
+ val actual = nativeMapView.bearing
+ assertEquals("Bearing should match", expected, actual, DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testLatLng() {
+ val expected = LATLNG_TEST
+ nativeMapView.setLatLng(expected, 0)
+ val actual = nativeMapView.latLng
+ assertEquals("Latitude should match", expected.latitude, actual.latitude, DELTA)
+ assertEquals("Longitude should match", expected.longitude, actual.longitude, DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testLatLngPadding() {
+ val expected = LATLNG_TEST
+ nativeMapView.contentPadding = PADDING_TEST
+ nativeMapView.setLatLng(expected, 0)
+ val actual = nativeMapView.latLng
+ assertEquals("Latitude should match", expected.latitude, actual.latitude, DELTA)
+ assertEquals("Longitude should match", expected.longitude, actual.longitude, DELTA)
+ Assert.assertArrayEquals(PADDING_TEST, nativeMapView.cameraPosition.padding, DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testLatLngDefault() {
+ val expected = LatLng()
+ val actual = nativeMapView.latLng
+ assertEquals("Latitude should match", expected.latitude, actual.latitude, DELTA)
+ assertEquals("Longitude should match", expected.longitude, actual.longitude, DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testBearingDefault() {
+ val expected = 0.0
+ val actual = nativeMapView.bearing
+ assertEquals("Bearing should match", expected, actual, DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testPitch() {
+ val expected = PITCH_TEST
+ nativeMapView.setPitch(expected, 0)
+ val actual = nativeMapView.pitch
+ assertEquals("Pitch should match", expected, actual, DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testPitchDefault() {
+ val expected = 0.0
+ val actual = nativeMapView.pitch
+ assertEquals("Pitch should match", expected, actual, DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testZoom() {
+ val expected = ZOOM_TEST
+ nativeMapView.setZoom(expected, PointF(0.0f, 0.0f), 0)
+ val actual = nativeMapView.zoom
+ assertEquals("Zoom should match", expected, actual, DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testZoomDefault() {
+ val expected = 0.0
+ val actual = nativeMapView.zoom
+ assertEquals("Zoom should match", expected, actual, DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testJumpTo() {
+ val expected = CameraPosition.Builder()
+ .bearing(BEARING_TEST)
+ .target(LATLNG_TEST)
+ .tilt(PITCH_TEST)
+ .zoom(ZOOM_TEST)
+ .padding(PADDING_TEST)
+ .build()
+ // verify that the lazily set padding is ignored when a value is provided with the camera
+ nativeMapView.contentPadding = doubleArrayOf(1.0, 2.0, 3.0, 4.0)
+ nativeMapView.jumpTo(LATLNG_TEST, ZOOM_TEST, PITCH_TEST, BEARING_TEST, PADDING_TEST)
+ val actual = nativeMapView.cameraPosition
+ assertEquals("Latitude should match", expected.target.latitude, actual.target.latitude, DELTA)
+ assertEquals("Longitude should match", expected.target.longitude, actual.target.longitude, DELTA)
+ assertEquals("Bearing should match", expected.bearing, actual.bearing, DELTA)
+ assertEquals("Pitch should match", expected.tilt, actual.tilt, DELTA)
+ assertEquals("Zoom should match", expected.zoom, actual.zoom, DELTA)
+ Assert.assertArrayEquals(expected.padding, actual.padding, DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testLatLngForPixel() {
+ val expected = LATLNG_TEST
+ nativeMapView.setLatLng(LATLNG_TEST, 0)
+ val actual = nativeMapView.latLngForPixel(
+ PointF((WIDTH / 2).toFloat(), (HEIGHT / 2).toFloat())
+ )
+ assertEquals("Latitude should match", expected.latitude, actual.latitude, DELTA_BIG)
+ assertEquals("Longitude should match", expected.longitude, actual.longitude, DELTA_BIG)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testPixelForLatLng() {
+ val expected = PointF((WIDTH / 2).toFloat(), (HEIGHT / 2).toFloat())
+ nativeMapView.setLatLng(LATLNG_TEST, 0)
+ val actual = nativeMapView.pixelForLatLng(LATLNG_TEST)
+ assertEquals("X should match", expected.x.toDouble(), actual.x.toDouble(), DELTA_BIG)
+ assertEquals("Y should match", expected.y.toDouble(), actual.y.toDouble(), DELTA_BIG)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testPrefetchTilesTrue() {
+ val expected = true
+ nativeMapView.prefetchTiles = true
+ val actual = nativeMapView.prefetchTiles
+ assertEquals("Flag should match", expected, actual)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testPrefetchTilesFalse() {
+ val expected = false
+ nativeMapView.prefetchTiles = false
+ val actual = nativeMapView.prefetchTiles
+ assertEquals("Flag should match", expected, actual)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testPrefetchTilesDefault() {
+ val expected = true
+ val actual = nativeMapView.prefetchTiles
+ assertEquals("Flag should match", expected, actual)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testPrefetchZoomDelta() {
+ val expected = 2
+ nativeMapView.prefetchZoomDelta = 2
+ val actual = nativeMapView.prefetchZoomDelta
+ assertEquals("Prefetch zoom delta should match", expected, actual)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testPrefetchZoomDeltaDefault() {
+ val expected = 4
+ val actual = nativeMapView.prefetchZoomDelta
+ assertEquals("Prefetch zoom delta should match", expected, actual)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testSetContentPadding() {
+ val expected = doubleArrayOf(1.0, 2.0, 3.0, 4.0)
+ nativeMapView.contentPadding = expected
+ val actual = nativeMapView.contentPadding
+ assertEquals("Left should match", expected[0], actual[0])
+ assertEquals("Top should match", expected[1], actual[1])
+ assertEquals("Right should match", expected[2], actual[2])
+ assertEquals("Bottom should match", expected[3], actual[3])
+ }
+
+ @Test
+ @UiThreadTest
+ fun testSetMinZoom() {
+ val expected = 12.0
+ nativeMapView.minZoom = expected
+ val actual = nativeMapView.minZoom
+ assertEquals("Min zoom should match", expected, actual)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testSetMaxZoom() {
+ val expected = 12.0
+ nativeMapView.maxZoom = expected
+ val actual = nativeMapView.maxZoom
+ assertEquals("Max zoom should match", expected, actual)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testGetProjectedMetersAtLatitude() {
+ val expected = 77973.67021115532
+ val actual = nativeMapView.getMetersPerPixelAtLatitude(5.0)
+ assertEquals("Get projected meters should match", expected, actual)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testLatLngForProjectedMeters() {
+ val expected = LatLng(0.01796630538796444, 0.02694945852363162)
+ val actual = nativeMapView.latLngForProjectedMeters(ProjectedMeters(2000.0, 3000.0))
+ assertEquals("Lat for projected meters", expected.latitude, actual.latitude, DELTA)
+ assertEquals("Lng for projected meters", expected.longitude, actual.longitude, DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testFlyTo() {
+ val expected = CameraPosition.Builder()
+ .zoom(12.0)
+ .tilt(30.0)
+ .target(LatLng(12.0, 14.0))
+ .bearing(20.0)
+ .padding(PADDING_TEST)
+ .build()
+ // verify that the lazily set padding is ignored when a value is provided with the camera
+ nativeMapView.contentPadding = doubleArrayOf(1.0, 2.0, 3.0, 4.0)
+ nativeMapView.flyTo(expected.target, expected.zoom, expected.bearing, expected.tilt, PADDING_TEST, 0)
+ val actual = nativeMapView.cameraPosition
+ assertEquals("Bearing should match", expected.bearing, actual.bearing, TestConstants.BEARING_DELTA)
+ assertEquals("Latitude should match", expected.target.latitude, actual.target.latitude, TestConstants.LAT_LNG_DELTA)
+ assertEquals("Longitude should match", expected.target.longitude, actual.target.longitude, TestConstants.LAT_LNG_DELTA)
+ assertEquals("Tilt should match", expected.tilt, actual.tilt, TestConstants.TILT_DELTA)
+ assertEquals("Zoom should match", expected.zoom, actual.zoom, TestConstants.ZOOM_DELTA)
+ Assert.assertArrayEquals(expected.padding, actual.padding, DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testEaseTo() {
+ val expected = CameraPosition.Builder()
+ .zoom(12.0)
+ .tilt(30.0)
+ .target(LatLng(12.0, 14.0))
+ .bearing(20.0)
+ .padding(PADDING_TEST)
+ .build()
+ // verify that the lazily set padding is ignored when a value is provided with the camera
+ nativeMapView.contentPadding = doubleArrayOf(1.0, 2.0, 3.0, 4.0)
+ nativeMapView.easeTo(expected.target, expected.zoom, expected.bearing, expected.tilt, PADDING_TEST, 0, false)
+ val actual = nativeMapView.cameraPosition
+ assertEquals("Bearing should match", expected.bearing, actual.bearing, TestConstants.BEARING_DELTA)
+ assertEquals("Latitude should match", expected.target.latitude, actual.target.latitude, TestConstants.LAT_LNG_DELTA)
+ assertEquals("Longitude should match", expected.target.longitude, actual.target.longitude, TestConstants.LAT_LNG_DELTA)
+ assertEquals("Tilt should match", expected.tilt, actual.tilt, TestConstants.TILT_DELTA)
+ assertEquals("Zoom should match", expected.zoom, actual.zoom, TestConstants.ZOOM_DELTA)
+ Assert.assertArrayEquals(expected.padding, actual.padding, DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testResetPosition() {
+ val expected = CameraPosition.Builder()
+ .zoom(0.0)
+ .tilt(0.0)
+ .target(LatLng(0.0, 0.0))
+ .bearing(0.0)
+ .padding(PADDING_TEST)
+ .build()
+ nativeMapView.jumpTo(LatLng(1.0, 2.0), 12.0, 23.0, 1.0, PADDING_TEST)
+ nativeMapView.resetPosition()
+ val actual = nativeMapView.cameraPosition
+ assertEquals("Bearing should match", expected.bearing, actual.bearing, TestConstants.BEARING_DELTA)
+ assertEquals("Latitude should match", expected.target.latitude, actual.target.latitude, TestConstants.LAT_LNG_DELTA)
+ assertEquals("Longitude should match", expected.target.longitude, actual.target.longitude, TestConstants.LAT_LNG_DELTA)
+ assertEquals("Tilt should match", expected.tilt, actual.tilt, TestConstants.TILT_DELTA)
+ assertEquals("Zoom should match", expected.zoom, actual.zoom, TestConstants.ZOOM_DELTA)
+ Assert.assertArrayEquals(expected.padding, actual.padding, DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testGetCameraForLatLngBounds() {
+ val expected = CameraPosition.Builder()
+ .zoom(3.5258764777024005)
+ .tilt(0.0)
+ .target(LatLng(23.182767623652808, 13.999999999994088))
+ .bearing(0.0)
+ .build()
+ val actual = nativeMapView.getCameraForLatLngBounds(
+ LatLngBounds.from(30.0, 16.0, 16.0, 12.0),
+ intArrayOf(0, 0, 0, 0),
+ 0.0,
+ 0.0
+ )
+ assertEquals("Bearing should match", expected.bearing, actual.bearing, TestConstants.BEARING_DELTA)
+ assertEquals("Latitude should match", expected.target.latitude, actual.target.latitude, TestConstants.LAT_LNG_DELTA)
+ assertEquals("Longitude should match", expected.target.longitude, actual.target.longitude, TestConstants.LAT_LNG_DELTA)
+ assertEquals("Tilt should match", expected.tilt, actual.tilt, TestConstants.TILT_DELTA)
+ assertEquals("Zoom should match", expected.zoom, actual.zoom, TestConstants.ZOOM_DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testMoveBy() {
+ val expected = CameraPosition.Builder()
+ .zoom(0.0)
+ .tilt(0.0)
+ .target(LatLng(4.21494310024160, -4.218749958739409))
+ .bearing(0.0)
+ .build()
+ nativeMapView.moveBy(12.0, 12.0, 0)
+ val actual = nativeMapView.cameraPosition
+ assertEquals("Bearing should match", expected.bearing, actual.bearing, TestConstants.BEARING_DELTA)
+ assertEquals("Latitude should match", expected.target.latitude, actual.target.latitude, TestConstants.LAT_LNG_DELTA)
+ assertEquals("Longitude should match", expected.target.longitude, actual.target.longitude, TestConstants.LAT_LNG_DELTA)
+ assertEquals("Tilt should match", expected.tilt, actual.tilt, TestConstants.TILT_DELTA)
+ assertEquals("Zoom should match", expected.zoom, actual.zoom, TestConstants.ZOOM_DELTA)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testTransitionOptions() {
+ val transitionOptions = TransitionOptions(500, 500)
+ nativeMapView.transitionOptions = transitionOptions
+ assertTrue(transitionOptions.isEnablePlacementTransitions)
+ assertEquals(transitionOptions, nativeMapView.transitionOptions)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testTransitionOptions_disablePlacementTransitions() {
+ val transitionOptions = TransitionOptions(500, 500, false)
+ nativeMapView.transitionOptions = transitionOptions
+ assertFalse(transitionOptions.isEnablePlacementTransitions)
+ assertEquals(transitionOptions, nativeMapView.transitionOptions)
+ }
+
+ class DummyRenderer(context: Context) : MapRenderer(context, null) {
+
+ override fun requestRender() {
+ // no-op
+ }
+
+ override fun queueEvent(runnable: Runnable?) {
+ // no-op
+ }
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/TransformTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/TransformTest.kt
new file mode 100644
index 0000000000..6b59411ae8
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/TransformTest.kt
@@ -0,0 +1,33 @@
+package com.mapbox.mapboxsdk.maps
+
+import android.support.test.espresso.UiController
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
+import com.mapbox.mapboxsdk.geometry.LatLng
+import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke
+import com.mapbox.mapboxsdk.testapp.activity.EspressoTest
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class TransformTest : EspressoTest() {
+
+ companion object {
+ val initialCameraUpdate = CameraUpdateFactory.newLatLngZoom(LatLng(12.0, 12.0), 12.0)!!
+ }
+
+ @Test
+ fun mapboxMapScrollByWithPadding() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(initialCameraUpdate)
+ mapboxMap.scrollBy(400.0f, 0.0f)
+ val expectedCameraPosition = mapboxMap.cameraPosition
+
+ mapboxMap.moveCamera(initialCameraUpdate)
+ mapboxMap.setPadding(250, 250, 0, 0)
+ mapboxMap.scrollBy(400.0f, 0.0f)
+ val actualCameraPosition = mapboxMap.cameraPosition
+
+ assertEquals("Camera position should match", expectedCameraPosition, actualCameraPosition)
+ }
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/VisibleRegionTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/VisibleRegionTest.kt
new file mode 100644
index 0000000000..12dff5d452
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/VisibleRegionTest.kt
@@ -0,0 +1,400 @@
+package com.mapbox.mapboxsdk.maps
+
+import android.graphics.PointF
+import android.support.test.espresso.UiController
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
+import com.mapbox.mapboxsdk.geometry.LatLng
+import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke
+import com.mapbox.mapboxsdk.testapp.activity.BaseTest
+import com.mapbox.mapboxsdk.testapp.activity.espresso.PixelTestActivity
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class VisibleRegionTest : BaseTest() {
+
+ override fun getActivityClass(): Class<*> {
+ return PixelTestActivity::class.java
+ }
+
+ override
+ fun beforeTest() {
+ super.beforeTest()
+ mapView = (rule.activity as PixelTestActivity).mapView
+ }
+
+ @Test
+ fun visibleRegionTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(0f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
+ )
+ val visibleRegion = mapboxMap.projection.visibleRegion
+ assertTrue(latLngs.all { visibleRegion.latLngBounds.contains(it) })
+ }
+ }
+
+ @Test
+ fun paddedVisibleRegionTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(0f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
+ )
+
+ mapboxMap.setPadding(
+ mapView.width / 4,
+ mapView.height / 4,
+ mapView.width / 4,
+ mapView.height / 4)
+
+ val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
+ val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
+ assertTrue(filtered.size == 1)
+ assertTrue(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)))
+ }
+ }
+
+ @Test
+ fun paddedLeftVisibleRegionTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(0f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
+ )
+
+ mapboxMap.setPadding(mapView.width / 4, 0, 0, 0)
+
+ val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
+ val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
+ assertTrue(filtered.size == 6)
+ assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f)))
+ }
+ }
+
+ @Test
+ fun paddedTopVisibleRegionTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(0f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
+ )
+
+ mapboxMap.setPadding(0, mapView.height / 4, 0, 0)
+
+ val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
+ val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
+ assertTrue(filtered.size == 6)
+ assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f)))
+ }
+ }
+
+ @Test
+ fun paddedRightVisibleRegionTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(0f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
+ )
+
+ mapboxMap.setPadding(0, 0, mapView.width / 4, 0)
+
+ val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
+ val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
+ assertTrue(filtered.size == 6)
+ assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)))
+ }
+ }
+
+ @Test
+ fun paddedBottomVisibleRegionTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(0f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
+ )
+
+ mapboxMap.setPadding(0, 0, 0, mapView.height / 4)
+
+ val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
+ val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
+ assertTrue(filtered.size == 6)
+ assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat())))
+ }
+ }
+
+ @Test
+ fun visibleRegionOverDatelineTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(0f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
+ )
+ val visibleRegion = mapboxMap.projection.visibleRegion
+ assertTrue(latLngs.all { visibleRegion.latLngBounds.contains(it) })
+ }
+ }
+
+ @Test
+ fun paddedVisibleRegionOverDatelineTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(0f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
+ )
+
+ mapboxMap.setPadding(
+ mapView.width / 4,
+ mapView.height / 4,
+ mapView.width / 4,
+ mapView.height / 4)
+
+ val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
+ val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
+ assertTrue(filtered.size == 1)
+ assertTrue(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)))
+ }
+ }
+
+ @Test
+ fun paddedLeftVisibleRegionOverDatelineTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(0f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
+ )
+
+ mapboxMap.setPadding(mapView.width / 4, 0, 0, 0)
+
+ val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
+ val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
+ assertTrue(filtered.size == 6)
+ assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f)))
+ }
+ }
+
+ @Test
+ fun paddedTopVisibleRegionOverDatelineTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { ui: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
+ ui.loopMainThreadForAtLeast(5000)
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(0f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
+ )
+
+ mapboxMap.setPadding(0, mapView.height / 4, 0, 0)
+
+ val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
+ val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
+ assertTrue(filtered.size == 6)
+ assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f)))
+ }
+ }
+
+ @Test
+ fun paddedRightVisibleRegionOverDatelineTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(0f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
+ )
+
+ mapboxMap.setPadding(0, 0, mapView.width / 4, 0)
+
+ val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
+ val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
+ assertTrue(filtered.size == 6)
+ assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)))
+ }
+ }
+
+ @Test
+ fun paddedBottomVisibleRegionOverDatelineTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(0f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
+ mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
+ )
+
+ mapboxMap.setPadding(0, 0, 0, mapView.height / 4)
+
+ val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
+ val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
+ assertTrue(filtered.size == 6)
+ assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat())))
+ }
+ }
+
+ @Test
+ fun visibleRotatedRegionTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
+ val d = Math.min(mapboxMap.width, mapboxMap.height) / 4
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f - d / 2f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f + d / 2f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f - d / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f + d / 2f)
+ )
+
+ for (bearing in 45 until 360 step 45) {
+ mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(bearing.toDouble()))
+ val visibleRegion = mapboxMap.projection.visibleRegion
+ assertTrue(latLngs.all { visibleRegion.latLngBounds.contains(it) })
+ }
+ }
+ }
+
+ @Test
+ fun visibleRotatedRegionOverDatelineTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
+ val d = Math.min(mapboxMap.width, mapboxMap.height) / 4
+ val latLngs = listOf(
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f - d / 2f, mapView.height / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f + d / 2f, mapView.height / 2f)
+ .also { it.longitude += 360 },
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f - d / 2f),
+ mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f + d / 2f)
+ )
+
+ for (bearing in 45 until 360 step 45) {
+ mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(bearing.toDouble()))
+ val visibleRegion = mapboxMap.projection.visibleRegion
+ assertTrue(latLngs.all { visibleRegion.latLngBounds.contains(it) })
+ }
+ }
+ }
+
+ private fun MapboxMap.getLatLngFromScreenCoords(x: Float, y: Float): LatLng {
+ return this.projection.fromScreenLocation(PointF(x, y))
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/IconTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/IconTest.java
new file mode 100644
index 0000000000..559213af3d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/IconTest.java
@@ -0,0 +1,138 @@
+package com.mapbox.mapboxsdk.testapp.annotations;
+
+import android.app.Activity;
+import android.support.test.annotation.UiThreadTest;
+import android.support.v4.content.res.ResourcesCompat;
+import com.mapbox.mapboxsdk.annotations.Icon;
+import com.mapbox.mapboxsdk.annotations.IconFactory;
+import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.MarkerOptions;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.IconManagerResolver;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
+import com.mapbox.mapboxsdk.testapp.utils.IconUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Map;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+/**
+ * Tests integration between Icons and Markers
+ */
+public class IconTest extends EspressoTest {
+
+ private Map<Icon, Integer> iconMap;
+
+ @Before
+ public void beforeTest() {
+ super.beforeTest();
+ iconMap = new IconManagerResolver(mapboxMap).getIconMap();
+ }
+
+ @Test
+ @UiThreadTest
+ public void testAddSameIconMarker() {
+ validateTestSetup();
+ Icon defaultMarker = IconFactory.getInstance(rule.getActivity()).defaultMarker();
+ mapboxMap.addMarker(new MarkerOptions().position(new LatLng()));
+ mapboxMap.addMarker(new MarkerOptions().position(new LatLng(1, 1)));
+ assertEquals(1, iconMap.size());
+ assertEquals(2, iconMap.get(defaultMarker), 0);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testAddDifferentIconMarker() {
+ validateTestSetup();
+ Icon icon = IconFactory.getInstance(rule.getActivity()).fromResource(R.drawable.mapbox_logo_icon);
+ mapboxMap.addMarker(new MarkerOptions().icon(icon).position(new LatLng()));
+ mapboxMap.addMarker(new MarkerOptions().position(new LatLng(1, 1)));
+ assertEquals(iconMap.size(), 2);
+ assertTrue(iconMap.containsKey(icon));
+ assertTrue(iconMap.get(icon) == 1);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testAddRemoveIconMarker() {
+ validateTestSetup();
+ Icon icon = IconFactory.getInstance(rule.getActivity()).fromResource(R.drawable.mapbox_logo_icon);
+ Marker marker = mapboxMap.addMarker(new MarkerOptions().icon(icon).position(new LatLng()));
+ mapboxMap.addMarker(new MarkerOptions().position(new LatLng(1, 1)));
+ assertEquals(iconMap.size(), 2);
+ assertTrue(iconMap.containsKey(icon));
+ assertTrue(iconMap.get(icon) == 1);
+
+ mapboxMap.removeMarker(marker);
+ assertEquals(iconMap.size(), 1);
+ assertFalse(iconMap.containsKey(icon));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testAddRemoveDefaultMarker() {
+ validateTestSetup();
+ Marker marker = mapboxMap.addMarker(new MarkerOptions().position(new LatLng(1, 1)));
+ assertEquals(iconMap.size(), 1);
+
+ mapboxMap.removeMarker(marker);
+ assertEquals(iconMap.size(), 0);
+
+ mapboxMap.addMarker(new MarkerOptions().position(new LatLng()));
+ assertEquals(iconMap.size(), 1);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testAddRemoveMany() {
+ validateTestSetup();
+ Activity activity = rule.getActivity();
+ IconFactory iconFactory = IconFactory.getInstance(activity);
+
+ // add 2 default icon markers
+ Marker defaultMarkerOne = mapboxMap.addMarker(new MarkerOptions().position(new LatLng(1, 1)));
+ Marker defaultMarkerTwo = mapboxMap.addMarker(new MarkerOptions().position(new LatLng(2, 1)));
+
+ // add 4 unique icon markers
+ mapboxMap.addMarker(new MarkerOptions()
+ .icon(iconFactory.fromResource(R.drawable.mapbox_logo_icon))
+ .position(new LatLng(3, 1))
+ );
+ mapboxMap.addMarker(new MarkerOptions()
+ .icon(iconFactory.fromResource(R.drawable.mapbox_compass_icon))
+ .position(new LatLng(4, 1))
+ );
+ mapboxMap.addMarker(new MarkerOptions()
+ .icon(IconUtils.drawableToIcon(activity, R.drawable.ic_stars,
+ ResourcesCompat.getColor(activity.getResources(),
+ R.color.blueAccent, activity.getTheme())))
+ .position(new LatLng(5, 1))
+ );
+ mapboxMap.addMarker(new MarkerOptions()
+ .icon(iconFactory.fromResource(R.drawable.ic_android))
+ .position(new LatLng(6, 1))
+ );
+
+ assertEquals("Amount of icons should match 5", 5, iconMap.size());
+ assertEquals("Refcounter of default marker should match 2", 2, iconMap.get(iconFactory.defaultMarker()), 0);
+
+ mapboxMap.removeMarker(defaultMarkerOne);
+
+ assertEquals("Amount of icons should match 5", 5, iconMap.size());
+ assertEquals("Refcounter of default marker should match 1", 1, iconMap.get(iconFactory.defaultMarker()), 0);
+
+ mapboxMap.removeMarker(defaultMarkerTwo);
+
+ assertEquals("Amount of icons should match 4", 4, iconMap.size());
+ assertNull("DefaultMarker shouldn't exist anymore", iconMap.get(iconFactory.defaultMarker()));
+
+ mapboxMap.clear();
+ assertEquals("Amount of icons should match 0", 0, iconMap.size());
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerTest.java
new file mode 100644
index 0000000000..2328023a3d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/MarkerTest.java
@@ -0,0 +1,63 @@
+package com.mapbox.mapboxsdk.testapp.annotations;
+
+import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.MarkerOptions;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
+import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
+import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
+import static org.junit.Assert.assertEquals;
+
+public class MarkerTest extends EspressoTest {
+
+ private Marker marker;
+
+ @Test
+ @Ignore
+ public void addMarkerTest() {
+ validateTestSetup();
+ MapboxMapAction.invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertEquals("Markers should be empty", 0, mapboxMap.getMarkers().size());
+
+ MarkerOptions options = new MarkerOptions();
+ options.setPosition(new LatLng());
+ options.setSnippet(TestConstants.TEXT_MARKER_SNIPPET);
+ options.setTitle(TestConstants.TEXT_MARKER_TITLE);
+ marker = mapboxMap.addMarker(options);
+
+ assertEquals("Markers size should be 1, ", 1, mapboxMap.getMarkers().size());
+ assertEquals("Marker id should be 0", 0, marker.getId());
+ assertEquals("Marker target should match", new LatLng(), marker.getPosition());
+ assertEquals("Marker snippet should match", TestConstants.TEXT_MARKER_SNIPPET, marker.getSnippet());
+ assertEquals("Marker target should match", TestConstants.TEXT_MARKER_TITLE, marker.getTitle());
+ mapboxMap.clear();
+ assertEquals("Markers should be empty", 0, mapboxMap.getMarkers().size());
+ });
+ }
+
+ @Test
+ @Ignore
+ public void showInfoWindowTest() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ final MarkerOptions options = new MarkerOptions();
+ options.setPosition(new LatLng());
+ options.setSnippet(TestConstants.TEXT_MARKER_SNIPPET);
+ options.setTitle(TestConstants.TEXT_MARKER_TITLE);
+ marker = mapboxMap.addMarker(options);
+ mapboxMap.selectMarker(marker);
+ });
+ onView(withText(TestConstants.TEXT_MARKER_TITLE)).check(matches(isDisplayed()));
+ onView(withText(TestConstants.TEXT_MARKER_SNIPPET)).check(matches(isDisplayed()));
+ }
+
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolygonTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolygonTest.java
new file mode 100644
index 0000000000..b604bb7da1
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolygonTest.java
@@ -0,0 +1,46 @@
+package com.mapbox.mapboxsdk.testapp.annotations;
+
+import android.graphics.Color;
+
+import com.mapbox.mapboxsdk.annotations.Polygon;
+import com.mapbox.mapboxsdk.annotations.PolygonOptions;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
+import static org.junit.Assert.assertEquals;
+
+public class PolygonTest extends EspressoTest {
+
+ @Test
+ @Ignore
+ public void addPolygonTest() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLngOne = new LatLng();
+ LatLng latLngTwo = new LatLng(1, 0);
+ LatLng latLngThree = new LatLng(1, 1);
+
+ assertEquals("Polygons should be empty", 0, mapboxMap.getPolygons().size());
+
+ final PolygonOptions options = new PolygonOptions();
+ options.strokeColor(Color.BLUE);
+ options.fillColor(Color.RED);
+ options.add(latLngOne);
+ options.add(latLngTwo);
+ options.add(latLngThree);
+ Polygon polygon = mapboxMap.addPolygon(options);
+
+ assertEquals("Polygons should be 1", 1, mapboxMap.getPolygons().size());
+ assertEquals("Polygon id should be 0", 0, polygon.getId());
+ assertEquals("Polygon points size should match", 3, polygon.getPoints().size());
+ assertEquals("Polygon stroke color should match", Color.BLUE, polygon.getStrokeColor());
+ assertEquals("Polygon target should match", Color.RED, polygon.getFillColor());
+ mapboxMap.clear();
+ assertEquals("Polygons should be empty", 0, mapboxMap.getPolygons().size());
+ });
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolylineTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolylineTest.java
new file mode 100644
index 0000000000..f977e25981
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/annotations/PolylineTest.java
@@ -0,0 +1,42 @@
+package com.mapbox.mapboxsdk.testapp.annotations;
+
+import android.graphics.Color;
+
+import com.mapbox.mapboxsdk.annotations.Polyline;
+import com.mapbox.mapboxsdk.annotations.PolylineOptions;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
+import static org.junit.Assert.assertEquals;
+
+public class PolylineTest extends EspressoTest {
+
+ @Test
+ @Ignore
+ public void addPolylineTest() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLngOne = new LatLng();
+ LatLng latLngTwo = new LatLng(1, 0);
+
+ assertEquals("Polygons should be empty", 0, mapboxMap.getPolygons().size());
+
+ final PolylineOptions options = new PolylineOptions();
+ options.color(Color.BLUE);
+ options.add(latLngOne);
+ options.add(latLngTwo);
+ Polyline polyline = mapboxMap.addPolyline(options);
+
+ assertEquals("Polylines should be 1", 1, mapboxMap.getPolylines().size());
+ assertEquals("Polyline id should be 0", 0, polyline.getId());
+ assertEquals("Polyline points size should match", 2, polyline.getPoints().size());
+ assertEquals("Polyline stroke color should match", Color.BLUE, polyline.getColor());
+ mapboxMap.clear();
+ assertEquals("Polyline should be empty", 0, mapboxMap.getPolylines().size());
+ });
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/fragment/MapDialogFragmentTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/fragment/MapDialogFragmentTest.kt
new file mode 100644
index 0000000000..f695f3efe2
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/fragment/MapDialogFragmentTest.kt
@@ -0,0 +1,35 @@
+package com.mapbox.mapboxsdk.testapp.fragment
+
+import android.support.test.espresso.Espresso
+import android.support.test.espresso.Espresso.onView
+import android.support.test.espresso.action.ViewActions.click
+import android.support.test.espresso.matcher.ViewMatchers.withId
+import android.support.test.filters.LargeTest
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.AppCenter
+import com.mapbox.mapboxsdk.testapp.R
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.MapInDialogActivity
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Regression test that validates that a map inside a DialogFragment can be opened and closed.
+ */
+@RunWith(AndroidJUnit4::class)
+@LargeTest
+class MapDialogFragmentTest : AppCenter() {
+
+ @get:Rule
+ var activityRule: ActivityTestRule<MapInDialogActivity> = ActivityTestRule(MapInDialogActivity::class.java)
+
+ @Test
+ @Ignore
+ fun openCloseDialog() {
+ onView(withId(R.id.button_open_dialog)).perform(click())
+ Thread.sleep(2500)
+ Espresso.pressBack()
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/GeoJsonConversionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/GeoJsonConversionTest.java
new file mode 100644
index 0000000000..81d10a5f15
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/GeoJsonConversionTest.java
@@ -0,0 +1,148 @@
+package com.mapbox.mapboxsdk.testapp.geometry;
+
+import android.support.test.annotation.UiThreadTest;
+import com.google.gson.JsonArray;
+import com.mapbox.geojson.Feature;
+import com.mapbox.geojson.Point;
+import com.mapbox.geojson.Polygon;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
+import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
+import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
+import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
+import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
+import com.mapbox.mapboxsdk.testapp.utils.TestingAsyncUtils;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
+import static com.mapbox.geojson.Feature.fromGeometry;
+import static com.mapbox.geojson.FeatureCollection.fromFeatures;
+import static com.mapbox.geojson.GeometryCollection.fromGeometries;
+import static com.mapbox.geojson.LineString.fromLngLats;
+import static com.mapbox.geojson.MultiLineString.fromLineString;
+import static com.mapbox.geojson.MultiPolygon.fromPolygon;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+import static org.junit.Assert.assertFalse;
+
+/**
+ * Instrumentation test to validate java geojson conversion to c++
+ */
+public class GeoJsonConversionTest extends EspressoTest {
+
+ // Regression test for #12343
+ @Test
+ @UiThreadTest
+ public void testEmptyFeatureCollection() {
+ validateTestSetup();
+ mapboxMap.getStyle().addSource(
+ new GeoJsonSource("test-id",
+ fromFeatures(singletonList(fromGeometry(fromGeometries(emptyList()))))
+ )
+ );
+ mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testPointFeatureCollection() {
+ validateTestSetup();
+ mapboxMap.getStyle().addSource(
+ new GeoJsonSource("test-id",
+ fromFeatures(singletonList(fromGeometry(Point.fromLngLat(0.0, 0.0))))
+ )
+ );
+ mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testMultiPointFeatureCollection() {
+ validateTestSetup();
+ mapboxMap.getStyle().addSource(
+ new GeoJsonSource("test-id",
+ fromFeatures(singletonList(fromGeometry(fromLngLats(emptyList()))))
+ )
+ );
+ mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testPolygonFeatureCollection() {
+ validateTestSetup();
+ mapboxMap.getStyle().addSource(
+ new GeoJsonSource("test-id",
+ fromFeatures(singletonList(fromGeometry(Polygon.fromLngLats(emptyList()))))
+ )
+ );
+ mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testMultiPolygonFeatureCollection() {
+ validateTestSetup();
+ mapboxMap.getStyle().addSource(
+ new GeoJsonSource("test-id",
+ fromFeatures(singletonList(fromGeometry(fromPolygon(Polygon.fromLngLats(emptyList())))))
+ )
+ );
+ mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineStringFeatureCollection() {
+ validateTestSetup();
+ mapboxMap.getStyle().addSource(
+ new GeoJsonSource("test-id",
+ fromFeatures(singletonList(fromGeometry(fromLngLats(emptyList()))))
+ )
+ );
+ mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testMultiLineStringFeatureCollection() {
+ validateTestSetup();
+ mapboxMap.getStyle().addSource(
+ new GeoJsonSource("test-id",
+ fromFeatures(singletonList(fromGeometry(fromLineString(fromLngLats(emptyList())))))
+ )
+ );
+ mapboxMap.getStyle().addLayer(new SymbolLayer("test-id", "test-id"));
+ }
+
+
+ @Test
+ public void testNegativeNumberPropertyConversion() {
+ validateTestSetup();
+ onView(isRoot()).perform(new MapboxMapAction((uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng();
+ Feature feature = Feature.fromGeometry(Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude()));
+
+ JsonArray foregroundJsonArray = new JsonArray();
+ foregroundJsonArray.add(0f);
+ foregroundJsonArray.add(-3f);
+ feature.addProperty("property", foregroundJsonArray);
+
+ GeoJsonSource source = new GeoJsonSource("source", feature);
+ mapboxMap.getStyle().addSource(source);
+
+ SymbolLayer layer = new SymbolLayer("layer", "source")
+ .withProperties(
+ PropertyFactory.iconOffset(Expression.get("property")),
+ PropertyFactory.iconImage("zoo-15")
+ );
+ mapboxMap.getStyle().addLayer(layer);
+
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng)).isEmpty());
+ }, mapboxMap));
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/LatLngBoundsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/LatLngBoundsTest.java
new file mode 100644
index 0000000000..607d7cd635
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/geometry/LatLngBoundsTest.java
@@ -0,0 +1,65 @@
+package com.mapbox.mapboxsdk.testapp.geometry;
+
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.geometry.LatLngBounds;
+import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
+import com.mapbox.mapboxsdk.testapp.activity.BaseTest;
+import com.mapbox.mapboxsdk.testapp.activity.feature.QueryRenderedFeaturesBoxHighlightActivity;
+import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+
+/**
+ * Instrumentation test to validate integration of LatLngBounds
+ */
+public class LatLngBoundsTest extends BaseTest {
+
+ private static final double MAP_BEARING = 50;
+
+ @Override
+ protected Class getActivityClass() {
+ return QueryRenderedFeaturesBoxHighlightActivity.class;
+ }
+
+ @Test
+ public void testLatLngBounds() {
+ // regression test for #9322
+ validateTestSetup();
+ MapboxMapAction.invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLngBounds bounds = new LatLngBounds.Builder()
+ .include(new LatLng(48.8589506, 2.2773457))
+ .include(new LatLng(47.2383171, -1.6309316))
+ .build();
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0));
+ });
+ }
+
+ @Test
+ public void testLatLngBoundsBearing() {
+ // regression test for #12549
+ validateTestSetup();
+ MapboxMapAction.invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLngBounds bounds = new LatLngBounds.Builder()
+ .include(new LatLng(48.8589506, 2.2773457))
+ .include(new LatLng(47.2383171, -1.6309316))
+ .build();
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0));
+ mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(MAP_BEARING));
+ assertEquals(
+ "Initial bearing should match for latlngbounds",
+ mapboxMap.getCameraPosition().bearing,
+ MAP_BEARING,
+ TestConstants.BEARING_DELTA
+ );
+
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0));
+ assertEquals("Bearing should match after resetting latlngbounds",
+ mapboxMap.getCameraPosition().bearing,
+ MAP_BEARING,
+ TestConstants.BEARING_DELTA);
+ });
+ }
+
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/CacheTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/CacheTest.kt
new file mode 100644
index 0000000000..a3214c9f11
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/CacheTest.kt
@@ -0,0 +1,88 @@
+package com.mapbox.mapboxsdk.testapp.offline
+
+import android.content.Context
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.offline.OfflineManager
+import com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity
+import java.util.concurrent.CountDownLatch
+import org.junit.Assert
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class CacheTest {
+
+ @Rule
+ @JvmField
+ var rule = ActivityTestRule(FeatureOverviewActivity::class.java)
+
+ private val context: Context by lazy { rule.activity }
+
+ private val countDownLatch = CountDownLatch(1)
+
+ @Test
+ fun testSetMaximumAmbientCacheSize() {
+ rule.activity.runOnUiThread {
+ OfflineManager.getInstance(context).setMaximumAmbientCacheSize(10000000, object : OfflineManager.FileSourceCallback {
+ override fun onSuccess() {
+ countDownLatch.countDown()
+ }
+
+ override fun onError(message: String) {
+ Assert.assertNull("onError should not be called", message)
+ }
+ })
+ }
+ countDownLatch.await()
+ }
+
+ @Test
+ fun testSetClearAmbientCache() {
+ rule.activity.runOnUiThread {
+ OfflineManager.getInstance(context).clearAmbientCache(object : OfflineManager.FileSourceCallback {
+ override fun onSuccess() {
+ countDownLatch.countDown()
+ }
+
+ override fun onError(message: String) {
+ Assert.assertNull("onError should not be called", message)
+ }
+ })
+ }
+ countDownLatch.await()
+ }
+
+ @Test
+ fun testSetInvalidateAmbientCache() {
+ rule.activity.runOnUiThread {
+ OfflineManager.getInstance(context).invalidateAmbientCache(object : OfflineManager.FileSourceCallback {
+ override fun onSuccess() {
+ countDownLatch.countDown()
+ }
+
+ override fun onError(message: String) {
+ Assert.assertNull("onError should not be called", message)
+ }
+ })
+ }
+ countDownLatch.await()
+ }
+
+ @Test
+ fun testSetResetDatabase() {
+ rule.activity.runOnUiThread {
+ OfflineManager.getInstance(context).resetDatabase(object : OfflineManager.FileSourceCallback {
+ override fun onSuccess() {
+ countDownLatch.countDown()
+ }
+
+ override fun onError(message: String) {
+ Assert.assertNull("onError should not be called", message)
+ }
+ })
+ }
+ countDownLatch.await()
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineManagerTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineManagerTest.kt
new file mode 100644
index 0000000000..e07dc1e9f1
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineManagerTest.kt
@@ -0,0 +1,124 @@
+package com.mapbox.mapboxsdk.testapp.offline
+
+import android.content.Context
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.AppCenter
+import com.mapbox.mapboxsdk.offline.OfflineManager
+import com.mapbox.mapboxsdk.offline.OfflineRegion
+import com.mapbox.mapboxsdk.storage.FileSource
+import com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity
+import com.mapbox.mapboxsdk.testapp.utils.FileUtils
+import java.io.IOException
+import java.util.concurrent.CountDownLatch
+import org.junit.FixMethodOrder
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(AndroidJUnit4::class)
+class OfflineManagerTest : AppCenter() {
+
+ companion object {
+ private const val TEST_DB_FILE_NAME = "offline_test.db"
+ private lateinit var mergedRegion: OfflineRegion
+ }
+
+ @Rule
+ @JvmField
+ var rule = ActivityTestRule(FeatureOverviewActivity::class.java)
+
+ private val context: Context by lazy { rule.activity }
+
+ @Test(timeout = 30_000)
+ fun a_copyFileFromAssets() {
+ val latch = CountDownLatch(1)
+ rule.activity.runOnUiThread {
+ FileUtils.CopyFileFromAssetsTask(rule.activity, object : FileUtils.OnFileCopiedFromAssetsListener {
+ override fun onFileCopiedFromAssets() {
+ latch.countDown()
+ }
+
+ override fun onError() {
+ throw IOException("Unable to copy DB file.")
+ }
+ }).execute(TEST_DB_FILE_NAME, FileSource.getResourcesCachePath(rule.activity))
+ }
+ latch.await()
+ }
+
+ @Test(timeout = 30_000)
+ fun b_mergeRegion() {
+ val latch = CountDownLatch(1)
+ rule.activity.runOnUiThread {
+ OfflineManager.getInstance(context).mergeOfflineRegions(
+ FileSource.getResourcesCachePath(rule.activity) + "/" + TEST_DB_FILE_NAME,
+ object : OfflineManager.MergeOfflineRegionsCallback {
+ override fun onMerge(offlineRegions: Array<out OfflineRegion>?) {
+ assert(offlineRegions?.size == 1)
+ latch.countDown()
+ }
+
+ override fun onError(error: String?) {
+ throw RuntimeException("Unable to merge external offline database. $error")
+ }
+ })
+ }
+ latch.await()
+ }
+
+ @Test(timeout = 30_000)
+ fun c_listRegion() {
+ val latch = CountDownLatch(1)
+ rule.activity.runOnUiThread {
+ OfflineManager.getInstance(context).listOfflineRegions(object : OfflineManager.ListOfflineRegionsCallback {
+ override fun onList(offlineRegions: Array<out OfflineRegion>?) {
+ assert(offlineRegions?.size == 1)
+ mergedRegion = offlineRegions!![0]
+ latch.countDown()
+ }
+
+ override fun onError(error: String?) {
+ throw RuntimeException("Unable to merge external offline database. $error")
+ }
+ })
+ }
+ latch.await()
+ }
+
+ @Test(timeout = 30_000)
+ fun d_invalidateRegion() {
+ val latch = CountDownLatch(1)
+ rule.activity.runOnUiThread {
+ mergedRegion.invalidate(object : OfflineRegion.OfflineRegionInvalidateCallback {
+ override fun onInvalidate() {
+ latch.countDown()
+ }
+
+ override fun onError(error: String?) {
+ throw RuntimeException("Unable to delete region")
+ }
+ })
+ }
+ latch.await()
+ }
+
+ @Test(timeout = 30_000)
+ fun e_deleteRegion() {
+ val latch = CountDownLatch(1)
+ rule.activity.runOnUiThread {
+ mergedRegion.delete(object : OfflineRegion.OfflineRegionDeleteCallback {
+ override fun onDelete() {
+ latch.countDown()
+ }
+
+ override fun onError(error: String?) {
+ throw RuntimeException("Unable to delete region")
+ }
+ })
+ }
+ latch.await()
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineUtilsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineUtilsTest.java
new file mode 100644
index 0000000000..48eb8e832d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/offline/OfflineUtilsTest.java
@@ -0,0 +1,41 @@
+package com.mapbox.mapboxsdk.testapp.offline;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.AppCenter;
+import com.mapbox.mapboxsdk.testapp.utils.OfflineUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+
+import static com.mapbox.mapboxsdk.testapp.activity.offline.OfflineActivity.JSON_CHARSET;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+
+@RunWith(AndroidJUnit4.class)
+public class OfflineUtilsTest extends AppCenter {
+
+ private static final String REGION_NAME = "hello world";
+ private static final String CONVERTED_REGION_NAME = "{\"FIELD_REGION_NAME\":\"hello world\"}";
+
+ @Test
+ public void testOfflineUtilsConvertToBytes() throws UnsupportedEncodingException {
+ byte[] expected = CONVERTED_REGION_NAME.getBytes(JSON_CHARSET);
+ byte[] actual = OfflineUtils.convertRegionName(REGION_NAME);
+ assertTrue("Bytes arrays should match", Arrays.equals(expected, actual));
+ }
+
+ @Test
+ public void testOfflineUtilsConvertToString() throws UnsupportedEncodingException {
+ String actual = OfflineUtils.convertRegionName(CONVERTED_REGION_NAME.getBytes(JSON_CHARSET));
+ assertEquals("Strings should match", REGION_NAME, actual);
+ }
+
+ @Test
+ public void testOfflineUtilsConvertNoOp() {
+ String convertNoOp = OfflineUtils.convertRegionName(OfflineUtils.convertRegionName(REGION_NAME));
+ assertEquals("Strings should match", REGION_NAME, convertNoOp);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/render/RenderTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/render/RenderTest.java
new file mode 100644
index 0000000000..c74e110b6c
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/render/RenderTest.java
@@ -0,0 +1,74 @@
+package com.mapbox.mapboxsdk.testapp.render;
+
+import android.Manifest;
+import android.support.test.espresso.IdlingPolicies;
+import android.support.test.espresso.IdlingRegistry;
+import android.support.test.espresso.IdlingResourceTimeoutException;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.rule.GrantPermissionRule;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.AppCenter;
+import com.mapbox.mapboxsdk.testapp.activity.render.RenderTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.SnapshotterIdlingResource;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import timber.log.Timber;
+
+import java.util.concurrent.TimeUnit;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+/**
+ * Instrumentation render tests
+ */
+@RunWith(AndroidJUnit4.class)
+public class RenderTest extends AppCenter {
+
+ private static final int RENDER_TEST_TIMEOUT = 30;
+ private SnapshotterIdlingResource idlingResource;
+
+ @Rule
+ public ActivityTestRule<RenderTestActivity> activityRule = new ActivityTestRule<>(RenderTestActivity.class);
+
+ @Rule
+ public GrantPermissionRule writeRule = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+
+ @Rule
+ public GrantPermissionRule readRule = GrantPermissionRule.grant(Manifest.permission.READ_EXTERNAL_STORAGE);
+
+ @Before
+ public void beforeTest() {
+ IdlingPolicies.setMasterPolicyTimeout(RENDER_TEST_TIMEOUT, TimeUnit.MINUTES);
+ setupIdlingResource();
+ }
+
+ private void setupIdlingResource() {
+ try {
+ Timber.e("@Before test: register idle resource");
+ IdlingPolicies.setIdlingResourceTimeout(RENDER_TEST_TIMEOUT, TimeUnit.MINUTES);
+ IdlingRegistry.getInstance().register(idlingResource = new SnapshotterIdlingResource(activityRule.getActivity()));
+ } catch (IdlingResourceTimeoutException idlingResourceTimeoutException) {
+ throw new RuntimeException("Idling out!");
+ }
+ }
+
+ @Test
+ @Ignore
+ public void testRender() {
+ onView(withId(android.R.id.content)).check(matches(isDisplayed()));
+ }
+
+ @After
+ public void afterTest() {
+ Timber.e("@After test: unregister idle resource");
+ IdlingRegistry.getInstance().unregister(idlingResource);
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceMapTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceMapTest.kt
new file mode 100644
index 0000000000..d08507470e
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceMapTest.kt
@@ -0,0 +1,59 @@
+package com.mapbox.mapboxsdk.testapp.storage
+
+import android.support.test.annotation.UiThreadTest
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.AppCenter
+import com.mapbox.mapboxsdk.storage.FileSource
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity
+import java.util.concurrent.CountDownLatch
+import junit.framework.Assert
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestName
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+open class FileSourceMapTest : AppCenter() {
+
+ private lateinit var fileSourceTestUtils: FileSourceTestUtils
+
+ @get:Rule
+ val rule = ActivityTestRule(EspressoTestActivity::class.java)
+
+ @get:Rule
+ val testName = TestName()
+
+ @Before
+ @UiThreadTest
+ fun setup() {
+ fileSourceTestUtils = FileSourceTestUtils(rule.activity)
+ fileSourceTestUtils.setup()
+ }
+
+ @Test
+ fun changeResourcesPathWhileMapVisible() {
+ val latch = CountDownLatch(1)
+ rule.activity.runOnUiThread {
+ FileSource.setResourcesCachePath(fileSourceTestUtils.testPath, object : FileSource.ResourcesCachePathChangeCallback {
+ override fun onSuccess(path: String) {
+ Assert.fail("Requested resources change while the map is running should fail")
+ }
+
+ override fun onError(message: String) {
+ Assert.assertEquals("Cannot set path, file source is activated." +
+ " Make sure that the map or a resources download is not running.", message)
+ latch.countDown()
+ }
+ })
+ }
+ latch.await()
+ }
+
+ @After
+ fun cleanup() {
+ fileSourceTestUtils.cleanup()
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceStandaloneTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceStandaloneTest.kt
new file mode 100644
index 0000000000..59f0d04237
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceStandaloneTest.kt
@@ -0,0 +1,116 @@
+package com.mapbox.mapboxsdk.testapp.storage
+
+import android.support.test.annotation.UiThreadTest
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.AppCenter
+import com.mapbox.mapboxsdk.storage.FileSource
+import com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import org.junit.*
+import org.junit.rules.TestName
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class FileSourceStandaloneTest : AppCenter() {
+
+ private lateinit var fileSourceTestUtils: FileSourceTestUtils
+ private lateinit var fileSource: FileSource
+
+ @get:Rule
+ val rule = ActivityTestRule(FeatureOverviewActivity::class.java)
+
+ @get:Rule
+ val testName = TestName()
+
+ @Before
+ @UiThreadTest
+ fun setup() {
+ fileSource = FileSource.getInstance(rule.activity)
+ fileSourceTestUtils = FileSourceTestUtils(rule.activity)
+ fileSourceTestUtils.setup()
+ }
+
+ @Test
+ @UiThreadTest
+ fun testDefault() {
+ Assert.assertFalse("FileSource should not be active", fileSource.isActivated)
+ }
+
+ @Test
+ @UiThreadTest
+ fun testActivateDeactivate() {
+ Assert.assertFalse("1) FileSource should not be active", fileSource.isActivated)
+ fileSource.activate()
+ Assert.assertTrue("2) FileSource should be active", fileSource.isActivated)
+ fileSource.deactivate()
+ Assert.assertFalse("3) FileSource should not be active", fileSource.isActivated)
+ }
+
+ @Test
+ fun pathChangeTest() {
+ Assert.assertFalse("FileSource should not be active", fileSource.isActivated)
+ Assert.assertEquals(fileSourceTestUtils.originalPath, FileSource.getResourcesCachePath(rule.activity))
+
+ fileSourceTestUtils.changePath(fileSourceTestUtils.testPath)
+ Assert.assertEquals(fileSourceTestUtils.testPath, FileSource.getResourcesCachePath(rule.activity))
+
+ fileSourceTestUtils.changePath(fileSourceTestUtils.originalPath)
+ Assert.assertEquals(fileSourceTestUtils.originalPath, FileSource.getResourcesCachePath(rule.activity))
+ }
+
+ @Test
+ fun overridePathChangeCallTest() {
+ val firstLatch = CountDownLatch(1)
+ val secondLatch = CountDownLatch(1)
+ rule.activity.runOnUiThread {
+ FileSource.setResourcesCachePath(
+ fileSourceTestUtils.testPath,
+ object : FileSource.ResourcesCachePathChangeCallback {
+ override fun onSuccess(path: String) {
+ Assert.assertEquals(fileSourceTestUtils.testPath, path)
+ firstLatch.countDown()
+ }
+
+ override fun onError(message: String) {
+ Assert.fail("First attempt should succeed.")
+ }
+ })
+
+ FileSource.setResourcesCachePath(
+ fileSourceTestUtils.testPath2,
+ object : FileSource.ResourcesCachePathChangeCallback {
+ override fun onSuccess(path: String) {
+ Assert.fail("Second attempt should fail because first one is in progress.")
+ }
+
+ override fun onError(message: String) {
+ Assert.assertEquals("Another resources cache path change is in progress", message)
+ secondLatch.countDown()
+ }
+ })
+ }
+
+ if (!secondLatch.await(5, TimeUnit.SECONDS)) {
+ rule.runOnUiThread {
+ // if we fail to call a callback, the file source is not going to be deactivated
+ fileSource.deactivate()
+ }
+ Assert.fail("Second attempt should fail.")
+ }
+
+ if (!firstLatch.await(5, TimeUnit.SECONDS)) {
+ rule.runOnUiThread {
+ // if we fail to call a callback, the file source is not going to be deactivated
+ fileSource.deactivate()
+ }
+ Assert.fail("First attempt should succeed.")
+ }
+ }
+
+ @After
+ fun cleanup() {
+ fileSourceTestUtils.cleanup()
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceTestUtils.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceTestUtils.kt
new file mode 100644
index 0000000000..6bd97056a6
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/storage/FileSourceTestUtils.kt
@@ -0,0 +1,59 @@
+package com.mapbox.mapboxsdk.testapp.storage
+
+import android.app.Activity
+import android.support.annotation.WorkerThread
+import com.mapbox.mapboxsdk.AppCenter
+import com.mapbox.mapboxsdk.storage.FileSource
+import java.io.File
+import java.util.concurrent.CountDownLatch
+import junit.framework.Assert
+
+class FileSourceTestUtils(private val activity: Activity) : AppCenter() {
+ val originalPath = FileSource.getResourcesCachePath(activity)
+ val testPath = "$originalPath/test"
+ val testPath2 = "$originalPath/test2"
+
+ private val paths = listOf(testPath, testPath2)
+
+ fun setup() {
+ for (path in paths) {
+ val testFile = File(path)
+ testFile.mkdirs()
+ }
+ }
+
+ @WorkerThread
+ fun cleanup() {
+ val currentPath = FileSource.getResourcesCachePath(activity)
+ if (currentPath != originalPath) {
+ changePath(originalPath)
+ }
+
+ for (path in paths) {
+ val testFile = File(path)
+ if (testFile.exists()) {
+ testFile.deleteRecursively()
+ }
+ }
+ }
+
+ @WorkerThread
+ fun changePath(requestedPath: String) {
+ val latch = CountDownLatch(1)
+ activity.runOnUiThread {
+ FileSource.setResourcesCachePath(
+ requestedPath,
+ object : FileSource.ResourcesCachePathChangeCallback {
+ override fun onSuccess(path: String) {
+ Assert.assertEquals(requestedPath, path)
+ latch.countDown()
+ }
+
+ override fun onError(message: String) {
+ Assert.fail("Resource path change failed - path: $requestedPath, message: $message")
+ }
+ })
+ }
+ latch.await()
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/string/UppperLowerCaseTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/string/UppperLowerCaseTest.java
new file mode 100644
index 0000000000..0ef8051a3f
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/string/UppperLowerCaseTest.java
@@ -0,0 +1,47 @@
+package com.mapbox.mapboxsdk.testapp.string;
+
+import android.support.test.runner.AndroidJUnit4;
+import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static junit.framework.Assert.assertEquals;
+
+/**
+ * Test verifying if String#toUpperCase and String#toLowerCase produces desired results
+ * <p>
+ * See core test in https://github.com/mapbox/mapbox-gl-native/blob/master/test/util/text_conversions.test.cpp
+ * </p>
+ */
+@RunWith(AndroidJUnit4.class)
+public class UppperLowerCaseTest extends EspressoTest {
+
+ @Test
+ public void testToUpperCase() {
+ assertEquals("STREET", "strEEt".toUpperCase()); // EN
+ assertEquals("ROAD", "rOAd".toUpperCase()); // EN
+
+ assertEquals("STRASSE", "straße".toUpperCase()); // DE
+ assertEquals("MASSE", "maße".toUpperCase()); // DE
+ assertEquals("WEISSKOPFSEEADLER", "weißkopfseeadler".toUpperCase()); // DE
+
+ assertEquals("BÊNÇÃO", "bênção".toUpperCase()); // PT
+ assertEquals("AZƏRBAYCAN", "Azərbaycan".toUpperCase()); // AZ
+ assertEquals("ὈΔΥΣΣΕΎΣ", "Ὀδυσσεύς".toUpperCase()); // GR
+ }
+
+ @Test
+ public void testToLowerCase() {
+ assertEquals("street", "strEEt".toLowerCase()); // EN
+ assertEquals("road", "rOAd".toLowerCase()); // EN
+
+ assertEquals("straße", "Straße".toLowerCase()); // DE
+ assertEquals("strasse", "STRASSE".toLowerCase()); // DE
+ assertEquals("masse", "MASSE".toLowerCase()); // DE
+ assertEquals("weisskopfseeadler", "weiSSkopfseeadler".toLowerCase()); // DE
+
+ assertEquals("bênção", "BÊNÇÃO".toLowerCase()); // PT
+ assertEquals("azərbaycan", "AZƏRBAYCAN".toLowerCase()); //
+ }
+
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java
new file mode 100644
index 0000000000..d3edfb852d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java
@@ -0,0 +1,141 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
+
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.maps.BaseLayerTest;
+import org.junit.Before;
+import timber.log.Timber;
+
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.BackgroundLayer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
+
+/**
+ * Basic smoke tests for BackgroundLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class BackgroundLayerTest extends BaseLayerTest {
+
+ private BackgroundLayer layer;
+
+ @Before
+ @UiThreadTest
+ public void beforeTest(){
+ super.before();
+ layer = new BackgroundLayer("my-layer");
+ setupLayer(layer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSetVisibility() {
+ Timber.i("Visibility");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testBackgroundColorTransition() {
+ Timber.i("background-colorTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setBackgroundColorTransition(options);
+ assertEquals(layer.getBackgroundColorTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testBackgroundColorAsConstant() {
+ Timber.i("background-color");
+ assertNotNull(layer);
+ assertNull(layer.getBackgroundColor().getValue());
+
+ // Set and Get
+ String propertyValue = "rgba(255,128,0,0.7)";
+ layer.setProperties(backgroundColor(propertyValue));
+ assertEquals(layer.getBackgroundColor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testBackgroundColorAsIntConstant() {
+ Timber.i("background-color");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(backgroundColor(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.getBackgroundColorAsInt(), Color.argb(127, 255, 127, 0));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testBackgroundPatternTransition() {
+ Timber.i("background-patternTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setBackgroundPatternTransition(options);
+ assertEquals(layer.getBackgroundPatternTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testBackgroundPatternAsConstant() {
+ Timber.i("background-pattern");
+ assertNotNull(layer);
+ assertNull(layer.getBackgroundPattern().getValue());
+
+ // Set and Get
+ String propertyValue = "pedestrian-polygon";
+ layer.setProperties(backgroundPattern(propertyValue));
+ assertEquals(layer.getBackgroundPattern().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testBackgroundOpacityTransition() {
+ Timber.i("background-opacityTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setBackgroundOpacityTransition(options);
+ assertEquals(layer.getBackgroundOpacityTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testBackgroundOpacityAsConstant() {
+ Timber.i("background-opacity");
+ assertNotNull(layer);
+ assertNull(layer.getBackgroundOpacity().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(backgroundOpacity(propertyValue));
+ assertEquals(layer.getBackgroundOpacity().getValue(), propertyValue);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java
new file mode 100644
index 0000000000..146cfc2209
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java
@@ -0,0 +1,453 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
+
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.maps.BaseLayerTest;
+import org.junit.Before;
+import timber.log.Timber;
+
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.CircleLayer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
+
+/**
+ * Basic smoke tests for CircleLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class CircleLayerTest extends BaseLayerTest {
+
+ private CircleLayer layer;
+
+ @Before
+ @UiThreadTest
+ public void beforeTest(){
+ super.before();
+ layer = new CircleLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ setupLayer(layer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSourceId() {
+ Timber.i("SourceId");
+ assertNotNull(layer);
+ assertEquals(layer.getSourceId(), "composite");
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSetVisibility() {
+ Timber.i("Visibility");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSourceLayer() {
+ Timber.i("SourceLayer");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFilter() {
+ Timber.i("Filter");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getFilter(), null);
+
+ // Set
+ Expression filter = eq(get("undefined"), literal(1.0));
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
+
+ // Set constant
+ filter = literal(true);
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
+ }
+
+
+
+ @Test
+ @UiThreadTest
+ public void testCircleRadiusTransition() {
+ Timber.i("circle-radiusTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleRadiusTransition(options);
+ assertEquals(layer.getCircleRadiusTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleRadiusAsConstant() {
+ Timber.i("circle-radius");
+ assertNotNull(layer);
+ assertNull(layer.getCircleRadius().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(circleRadius(propertyValue));
+ assertEquals(layer.getCircleRadius().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleRadiusAsExpression() {
+ Timber.i("circle-radius-expression");
+ assertNotNull(layer);
+ assertNull(layer.getCircleRadius().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(circleRadius(expression));
+ assertEquals(layer.getCircleRadius().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleColorTransition() {
+ Timber.i("circle-colorTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleColorTransition(options);
+ assertEquals(layer.getCircleColorTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleColorAsConstant() {
+ Timber.i("circle-color");
+ assertNotNull(layer);
+ assertNull(layer.getCircleColor().getValue());
+
+ // Set and Get
+ String propertyValue = "rgba(255,128,0,0.7)";
+ layer.setProperties(circleColor(propertyValue));
+ assertEquals(layer.getCircleColor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleColorAsExpression() {
+ Timber.i("circle-color-expression");
+ assertNotNull(layer);
+ assertNull(layer.getCircleColor().getExpression());
+
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(circleColor(expression));
+ assertEquals(layer.getCircleColor().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleColorAsIntConstant() {
+ Timber.i("circle-color");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleColor(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.getCircleColorAsInt(), Color.argb(127, 255, 127, 0));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleBlurTransition() {
+ Timber.i("circle-blurTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleBlurTransition(options);
+ assertEquals(layer.getCircleBlurTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleBlurAsConstant() {
+ Timber.i("circle-blur");
+ assertNotNull(layer);
+ assertNull(layer.getCircleBlur().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(circleBlur(propertyValue));
+ assertEquals(layer.getCircleBlur().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleBlurAsExpression() {
+ Timber.i("circle-blur-expression");
+ assertNotNull(layer);
+ assertNull(layer.getCircleBlur().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(circleBlur(expression));
+ assertEquals(layer.getCircleBlur().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleOpacityTransition() {
+ Timber.i("circle-opacityTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleOpacityTransition(options);
+ assertEquals(layer.getCircleOpacityTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleOpacityAsConstant() {
+ Timber.i("circle-opacity");
+ assertNotNull(layer);
+ assertNull(layer.getCircleOpacity().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(circleOpacity(propertyValue));
+ assertEquals(layer.getCircleOpacity().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleOpacityAsExpression() {
+ Timber.i("circle-opacity-expression");
+ assertNotNull(layer);
+ assertNull(layer.getCircleOpacity().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(circleOpacity(expression));
+ assertEquals(layer.getCircleOpacity().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleTranslateTransition() {
+ Timber.i("circle-translateTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleTranslateTransition(options);
+ assertEquals(layer.getCircleTranslateTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleTranslateAsConstant() {
+ Timber.i("circle-translate");
+ assertNotNull(layer);
+ assertNull(layer.getCircleTranslate().getValue());
+
+ // Set and Get
+ Float[] propertyValue = new Float[] {0f, 0f};
+ layer.setProperties(circleTranslate(propertyValue));
+ assertEquals(layer.getCircleTranslate().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleTranslateAnchorAsConstant() {
+ Timber.i("circle-translate-anchor");
+ assertNotNull(layer);
+ assertNull(layer.getCircleTranslateAnchor().getValue());
+
+ // Set and Get
+ String propertyValue = CIRCLE_TRANSLATE_ANCHOR_MAP;
+ layer.setProperties(circleTranslateAnchor(propertyValue));
+ assertEquals(layer.getCircleTranslateAnchor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCirclePitchScaleAsConstant() {
+ Timber.i("circle-pitch-scale");
+ assertNotNull(layer);
+ assertNull(layer.getCirclePitchScale().getValue());
+
+ // Set and Get
+ String propertyValue = CIRCLE_PITCH_SCALE_MAP;
+ layer.setProperties(circlePitchScale(propertyValue));
+ assertEquals(layer.getCirclePitchScale().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCirclePitchAlignmentAsConstant() {
+ Timber.i("circle-pitch-alignment");
+ assertNotNull(layer);
+ assertNull(layer.getCirclePitchAlignment().getValue());
+
+ // Set and Get
+ String propertyValue = CIRCLE_PITCH_ALIGNMENT_MAP;
+ layer.setProperties(circlePitchAlignment(propertyValue));
+ assertEquals(layer.getCirclePitchAlignment().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleStrokeWidthTransition() {
+ Timber.i("circle-stroke-widthTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleStrokeWidthTransition(options);
+ assertEquals(layer.getCircleStrokeWidthTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleStrokeWidthAsConstant() {
+ Timber.i("circle-stroke-width");
+ assertNotNull(layer);
+ assertNull(layer.getCircleStrokeWidth().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(circleStrokeWidth(propertyValue));
+ assertEquals(layer.getCircleStrokeWidth().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleStrokeWidthAsExpression() {
+ Timber.i("circle-stroke-width-expression");
+ assertNotNull(layer);
+ assertNull(layer.getCircleStrokeWidth().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(circleStrokeWidth(expression));
+ assertEquals(layer.getCircleStrokeWidth().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleStrokeColorTransition() {
+ Timber.i("circle-stroke-colorTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleStrokeColorTransition(options);
+ assertEquals(layer.getCircleStrokeColorTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleStrokeColorAsConstant() {
+ Timber.i("circle-stroke-color");
+ assertNotNull(layer);
+ assertNull(layer.getCircleStrokeColor().getValue());
+
+ // Set and Get
+ String propertyValue = "rgba(255,128,0,0.7)";
+ layer.setProperties(circleStrokeColor(propertyValue));
+ assertEquals(layer.getCircleStrokeColor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleStrokeColorAsExpression() {
+ Timber.i("circle-stroke-color-expression");
+ assertNotNull(layer);
+ assertNull(layer.getCircleStrokeColor().getExpression());
+
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(circleStrokeColor(expression));
+ assertEquals(layer.getCircleStrokeColor().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleStrokeColorAsIntConstant() {
+ Timber.i("circle-stroke-color");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleStrokeColor(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.getCircleStrokeColorAsInt(), Color.argb(127, 255, 127, 0));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleStrokeOpacityTransition() {
+ Timber.i("circle-stroke-opacityTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleStrokeOpacityTransition(options);
+ assertEquals(layer.getCircleStrokeOpacityTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleStrokeOpacityAsConstant() {
+ Timber.i("circle-stroke-opacity");
+ assertNotNull(layer);
+ assertNull(layer.getCircleStrokeOpacity().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(circleStrokeOpacity(propertyValue));
+ assertEquals(layer.getCircleStrokeOpacity().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testCircleStrokeOpacityAsExpression() {
+ Timber.i("circle-stroke-opacity-expression");
+ assertNotNull(layer);
+ assertNull(layer.getCircleStrokeOpacity().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(circleStrokeOpacity(expression));
+ assertEquals(layer.getCircleStrokeOpacity().getExpression(), expression);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CustomGeometrySourceTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CustomGeometrySourceTest.kt
new file mode 100644
index 0000000000..9c2eb3df81
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CustomGeometrySourceTest.kt
@@ -0,0 +1,69 @@
+package com.mapbox.mapboxsdk.testapp.style
+
+import android.support.test.espresso.Espresso.onView
+import android.support.test.espresso.matcher.ViewMatchers.isRoot
+import com.mapbox.mapboxsdk.style.sources.CustomGeometrySource.THREAD_POOL_LIMIT
+import com.mapbox.mapboxsdk.style.sources.CustomGeometrySource.THREAD_PREFIX
+import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke
+import com.mapbox.mapboxsdk.testapp.action.OrientationAction.orientationLandscape
+import com.mapbox.mapboxsdk.testapp.action.OrientationAction.orientationPortrait
+import com.mapbox.mapboxsdk.testapp.action.WaitAction
+import com.mapbox.mapboxsdk.testapp.activity.BaseTest
+import com.mapbox.mapboxsdk.testapp.activity.style.GridSourceActivity
+import com.mapbox.mapboxsdk.testapp.activity.style.GridSourceActivity.ID_GRID_LAYER
+import com.mapbox.mapboxsdk.testapp.activity.style.GridSourceActivity.ID_GRID_SOURCE
+import com.mapbox.mapboxsdk.testapp.utils.TestingAsyncUtils
+import org.junit.Assert
+import org.junit.Test
+
+class CustomGeometrySourceTest : BaseTest() {
+
+ override fun getActivityClass(): Class<*> = GridSourceActivity::class.java
+
+ @Test
+ fun sourceNotLeakingThreadsTest() {
+ validateTestSetup()
+ WaitAction.invoke(4000)
+ onView(isRoot()).perform(orientationLandscape())
+ WaitAction.invoke(2000)
+ onView(isRoot()).perform(orientationPortrait())
+ WaitAction.invoke(2000)
+ Assert.assertFalse("Threads should be shutdown when the source is destroyed.",
+ Thread.getAllStackTraces().keys.filter {
+ it.name.startsWith(THREAD_PREFIX)
+ }.count() > THREAD_POOL_LIMIT)
+ }
+
+ @Test
+ fun threadsShutdownWhenSourceRemovedTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { uiController, mapboxMap ->
+ mapboxMap.style!!.removeLayer(ID_GRID_LAYER)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
+ mapboxMap.style!!.removeSource(ID_GRID_SOURCE)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
+ Assert.assertTrue("There should be no threads running when the source is removed.",
+ Thread.getAllStackTraces().keys.filter {
+ it.name.startsWith(THREAD_PREFIX)
+ }.count() == 0)
+ }
+ }
+
+ @Test
+ fun threadsRestartedWhenSourceReAddedTest() {
+ validateTestSetup()
+ invoke(mapboxMap) { uiController, mapboxMap ->
+ mapboxMap.style!!.removeLayer((rule.activity as GridSourceActivity).layer)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
+ mapboxMap.style!!.removeSource(ID_GRID_SOURCE)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
+ mapboxMap.style!!.addSource((rule.activity as GridSourceActivity).source)
+ mapboxMap.style!!.addLayer((rule.activity as GridSourceActivity).layer)
+ TestingAsyncUtils.waitForLayer(uiController, mapView)
+ Assert.assertTrue("Threads should be restarted when the source is re-added to the map.",
+ Thread.getAllStackTraces().keys.filter {
+ it.name.startsWith(THREAD_PREFIX)
+ }.count() == THREAD_POOL_LIMIT)
+ }
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ExpressionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ExpressionTest.java
new file mode 100644
index 0000000000..95bd651cff
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ExpressionTest.java
@@ -0,0 +1,786 @@
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.geojson.Feature;
+import com.mapbox.geojson.Point;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.CircleLayer;
+import com.mapbox.mapboxsdk.style.layers.FillLayer;
+import com.mapbox.mapboxsdk.style.layers.Layer;
+import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
+import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
+import com.mapbox.mapboxsdk.style.sources.Source;
+import com.mapbox.mapboxsdk.style.types.Formatted;
+import com.mapbox.mapboxsdk.style.types.FormattedSection;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
+import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
+import com.mapbox.mapboxsdk.testapp.utils.TestingAsyncUtils;
+import com.mapbox.mapboxsdk.utils.ColorUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.FormatOption.formatFontScale;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.FormatOption.formatTextColor;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.FormatOption.formatTextFont;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.NumberFormatOption.currency;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.NumberFormatOption.locale;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.NumberFormatOption.maxFractionDigits;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.NumberFormatOption.minFractionDigits;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.collator;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.color;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.format;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.formatEntry;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.match;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.number;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.numberFormat;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.rgb;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.rgba;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.step;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.string;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.switchCase;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.toColor;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillAntialias;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillOutlineColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.textField;
+import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+@RunWith(AndroidJUnit4.class)
+public class ExpressionTest extends EspressoTest {
+
+ private FillLayer layer;
+
+ @Test
+ public void testConstantExpressionConversion() {
+ validateTestSetup();
+ setupStyle();
+ Timber.i("camera function");
+
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ // create color expression
+ Expression inputExpression = rgba(255.0f, 0.0f, 0.0f, 1.0f);
+
+ // set color expression
+ layer.setProperties(
+ fillColor(inputExpression)
+ );
+
+ // get color value
+ int color = layer.getFillColor().getColorInt();
+
+ // compare
+ assertEquals("input expression should match", Color.RED, color);
+ });
+ }
+
+ @Test
+ public void testGetExpressionWrapping() {
+ validateTestSetup();
+ setupStyle();
+ Timber.i("camera function");
+
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ // create get expression
+ Expression inputExpression = get("fill");
+
+ // set get expression
+ layer.setProperties(
+ fillColor(inputExpression)
+ );
+
+ // get actual expression
+ Expression actualExpression = layer.getFillColor().getExpression();
+
+ // create wrapped expected expression
+ Expression expectedExpression = toColor(get("fill"));
+
+ // compare
+ assertEquals("input expression should match", expectedExpression, actualExpression);
+ });
+ }
+
+ @Test
+ public void testCameraFunction() {
+ validateTestSetup();
+ setupStyle();
+ Timber.i("camera function");
+
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ // create camera function expression
+ Expression inputExpression = interpolate(
+ exponential(0.5f), zoom(),
+ stop(1.0f, rgba(255.0f, 0.0f, 0.0f, 1.0f)),
+ stop(5.0f, rgba(0.0f, 0.0f, 255.0f, 1.0f)),
+ stop(10.0f, rgba(0.0f, 255.0f, 0.0f, 1.0f))
+ );
+
+ // set camera function expression
+ layer.setProperties(
+ fillColor(inputExpression)
+ );
+
+ // get camera function expression
+ Expression outputExpression = layer.getFillColor().getExpression();
+
+ // compare
+ assertEquals("input expression should match", inputExpression, outputExpression);
+ });
+ }
+
+ @Test
+ public void testSourceFunction() {
+ validateTestSetup();
+ setupStyle();
+ Timber.i("camera function");
+
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ // create camera function expression
+ Expression inputExpression = toColor(get("fill"));
+
+ // set camera function expression
+ layer.setProperties(
+ fillColor(inputExpression)
+ );
+
+ // get camera function expression
+ Expression outputExpression = layer.getFillColor().getExpression();
+
+ // compare
+ assertEquals("input expression should match", inputExpression, outputExpression);
+ });
+ }
+
+ @Test
+ public void testCompositeFunction() {
+ validateTestSetup();
+ setupStyle();
+ Timber.i("camera function");
+
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ // create camera function expression
+ Expression inputExpression = step(zoom(),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f),
+ stop(7.0f, match(
+ string(get("name")),
+ literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
+ )),
+ stop(8.0f, match(
+ string(get("name")),
+ literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
+ ))
+ );
+
+ // set camera function expression
+ layer.setProperties(
+ fillColor(inputExpression)
+ );
+
+ // get camera function expression
+ Expression outputExpression = layer.getFillColor().getExpression();
+
+ // compare
+ assertEquals("input expression should match", inputExpression, outputExpression);
+ });
+ }
+
+ @Test
+ public void testLiteralProperty() {
+ validateTestSetup();
+ setupStyle();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ layer.setProperties(
+ fillColor(literal("#4286f4"))
+ );
+ });
+ }
+
+ @Test
+ public void testLiteralMatchExpression() {
+ validateTestSetup();
+ setupStyle();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ Expression expression = match(literal("something"), literal(0f),
+ stop("1", get("1")),
+ stop("2", get("2")),
+ stop("3", get("3")),
+ stop("4", get("4"))
+ );
+
+ layer.setProperties(
+ fillColor(expression)
+ );
+ expression.toArray();
+ });
+ }
+
+ @Test
+ public void testCollatorExpression() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+
+ Expression expression1 = eq(literal("Łukasz"), literal("lukasz"), collator(true, true));
+ Expression expression2 = eq(literal("Łukasz"), literal("lukasz"), collator(literal(false), eq(literal(1),
+ literal(1)), literal("en")));
+ Expression expression3 = eq(literal("Łukasz"), literal("lukasz"), collator(literal(false), eq(literal(2),
+ literal(1))));
+
+ mapboxMap.getStyle()
+ .addSource(new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude())));
+ Layer layer = new CircleLayer("layer", "source")
+ .withProperties(circleColor(
+ switchCase(
+ expression1, literal(ColorUtils.colorToRgbaString(Color.GREEN)),
+ literal(ColorUtils.colorToRgbaString(Color.RED))
+ )
+ ));
+ mapboxMap.getStyle().addLayer(layer);
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+ assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
+ .isEmpty());
+
+ layer.setProperties(circleColor(
+ switchCase(
+ expression2, literal(ColorUtils.colorToRgbaString(Color.GREEN)),
+ literal(ColorUtils.colorToRgbaString(Color.RED))
+ )
+ ));
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+ assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
+ .isEmpty());
+
+ layer.setProperties(circleColor(
+ switchCase(
+ expression3, literal(ColorUtils.colorToRgbaString(Color.GREEN)),
+ literal(ColorUtils.colorToRgbaString(Color.RED))
+ )
+ ));
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+ assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
+ .isEmpty());
+ });
+ }
+
+ @Test
+ public void testConstFormatExpression() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ mapboxMap.getStyle()
+ .addSource(new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude())));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ Expression expression = format(
+ formatEntry("test")
+ );
+ layer.setProperties(textField(expression));
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
+ .isEmpty());
+ assertNull(layer.getTextField().getExpression());
+ assertEquals(new Formatted(new FormattedSection("test")), layer.getTextField().getValue());
+ });
+ }
+
+ @Test
+ public void testConstFormatExpressionFontScaleParam() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ mapboxMap.getStyle()
+ .addSource(new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude())));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ Expression expression = format(
+ formatEntry("test", formatFontScale(1.75))
+ );
+ layer.setProperties(textField(expression));
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
+ .isEmpty());
+ assertNull(layer.getTextField().getExpression());
+ assertEquals(new Formatted(new FormattedSection("test", 1.75)), layer.getTextField().getValue());
+ });
+ }
+
+ @Test
+ public void testConstFormatExpressionTextFontParam() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ mapboxMap.getStyle()
+ .addSource(new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude())));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ Expression expression = format(
+ formatEntry(
+ literal("test"),
+ formatTextFont(new String[] {"DIN Offc Pro Regular", "Arial Unicode MS Regular"})
+ )
+ );
+ layer.setProperties(textField(expression));
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(
+ mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer").isEmpty()
+ );
+ assertNull(layer.getTextField().getExpression());
+ assertEquals(new Formatted(
+ new FormattedSection("test",
+ new String[] {"DIN Offc Pro Regular", "Arial Unicode MS Regular"})
+ ), layer.getTextField().getValue());
+ });
+ }
+
+ @Test
+ public void testConstFormatExpressionTextColorParam() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ mapboxMap.getStyle()
+ .addSource(new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude())));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ Expression expression = format(
+ formatEntry(
+ literal("test"),
+ formatTextColor(literal("yellow"))
+ )
+ );
+ layer.setProperties(textField(expression));
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(
+ mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer").isEmpty()
+ );
+ assertNull(layer.getTextField().getExpression());
+ assertEquals(new Formatted(
+ new FormattedSection("test", null, null, "rgba(255,255,0,1)")
+ ), layer.getTextField().getValue());
+ });
+ }
+
+ @Test
+ public void testConstFormatExpressionAllParams() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ mapboxMap.getStyle()
+ .addSource(new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude())));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ Expression expression = format(
+ formatEntry(
+ "test",
+ formatFontScale(0.5),
+ formatTextFont(new String[] {"DIN Offc Pro Regular", "Arial Unicode MS Regular"}),
+ formatTextColor(rgb(126, 0, 0))
+ )
+ );
+ layer.setProperties(textField(expression));
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(
+ mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer").isEmpty()
+ );
+ assertNull(layer.getTextField().getExpression());
+ assertEquals(new Formatted(
+ new FormattedSection("test",
+ 0.5,
+ new String[] {"DIN Offc Pro Regular", "Arial Unicode MS Regular"},
+ "rgba(126,0,0,1)")
+ ), layer.getTextField().getValue());
+ });
+ }
+
+ @Test
+ public void testConstFormatExpressionMultipleInputs() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ mapboxMap.getStyle()
+ .addSource(new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude())));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ Expression expression = format(
+ formatEntry(
+ "test",
+ formatFontScale(1.5),
+ formatTextFont(new String[] {"DIN Offc Pro Regular", "Arial Unicode MS Regular"})
+ ),
+ formatEntry("\ntest2", formatFontScale(2), formatTextColor(Color.BLUE)),
+ formatEntry("\ntest3", formatFontScale(2.5), formatTextColor(toColor(literal("rgba(0, 128, 255, 0.5)"))))
+ );
+ layer.setProperties(textField(expression));
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(
+ mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer").isEmpty()
+ );
+ assertNull(layer.getTextField().getExpression());
+ assertEquals(new Formatted(
+ new FormattedSection("test", 1.5,
+ new String[] {"DIN Offc Pro Regular", "Arial Unicode MS Regular"}),
+ new FormattedSection("\ntest2", 2.0, null, "rgba(0,0,255,1)"),
+ new FormattedSection("\ntest3", 2.5, null, "rgba(0,128,255,0.5)")
+ ), layer.getTextField().getValue());
+ });
+ }
+
+ @Test
+ public void testVariableFormatExpression() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ Feature feature = Feature.fromGeometry(Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude()));
+ feature.addStringProperty("test_property", "test");
+ feature.addNumberProperty("test_property_number", 1.5);
+ feature.addStringProperty("test_property_color", "green");
+ mapboxMap.getStyle().addSource(new GeoJsonSource("source", feature));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ Expression expression = format(
+ formatEntry(
+ get("test_property"),
+ Expression.FormatOption.formatFontScale(number(get("test_property_number"))),
+ formatTextFont(new String[] {"Arial Unicode MS Regular", "DIN Offc Pro Regular"}),
+ formatTextColor(toColor(get("test_property_color")))
+ )
+ );
+ layer.setProperties(textField(expression));
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
+ .isEmpty());
+ assertEquals(expression, layer.getTextField().getExpression());
+ assertNull(layer.getTextField().getValue());
+ });
+ }
+
+ @Test
+ public void testVariableFormatExpressionMultipleInputs() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ Feature feature = Feature.fromGeometry(Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude()));
+ feature.addStringProperty("test_property", "test");
+ feature.addNumberProperty("test_property_number", 1.5);
+ feature.addStringProperty("test_property_color", "rgba(0, 255, 0, 1)");
+ mapboxMap.getStyle().addSource(new GeoJsonSource("source", feature));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ Expression expression = format(
+ formatEntry(
+ get("test_property"),
+ formatFontScale(1.25),
+ formatTextFont(new String[] {"Arial Unicode MS Regular", "DIN Offc Pro Regular"}),
+ formatTextColor(toColor(get("test_property_color")))
+ ),
+ formatEntry("\ntest2", formatFontScale(2))
+ );
+ layer.setProperties(textField(expression), textColor("rgba(128, 0, 0, 1)"));
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
+ .isEmpty());
+ assertEquals(expression, layer.getTextField().getExpression());
+ assertNull(layer.getTextField().getValue());
+ });
+ }
+
+ @Test
+ public void testFormatExpressionPlainTextCoercion() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ mapboxMap.getStyle()
+ .addSource(new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude())));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ layer.setProperties(textField("test"));
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
+ .isEmpty());
+ assertNull(layer.getTextField().getExpression());
+ assertEquals(new Formatted(
+ new FormattedSection("test")), layer.getTextField().getValue());
+ });
+ }
+
+ @Test
+ public void testTextFieldFormattedArgument() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ mapboxMap.getStyle()
+ .addSource(new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude())));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ Formatted formatted = new Formatted(
+ new FormattedSection("test", 1.5),
+ new FormattedSection("\ntest", 0.5, new String[] {"Arial Unicode MS Regular", "DIN Offc Pro Regular"}),
+ new FormattedSection("test", null, null, "rgba(0,255,0,1)")
+ );
+ layer.setProperties(textField(formatted), textColor("rgba(128,0,0,1)"));
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(mapboxMap.queryRenderedFeatures(mapboxMap.getProjection().toScreenLocation(latLng), "layer")
+ .isEmpty());
+ assertNull(layer.getTextField().getExpression());
+ assertEquals(formatted, layer.getTextField().getValue());
+ });
+ }
+
+ @Test
+ public void testNumberFormatCurrencyExpression() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ mapboxMap.getStyle()
+ .addSource(new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude())));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ layer.setProperties(
+ textField(
+ numberFormat(12.345, locale("en-US"), currency("USD"))
+ )
+ );
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(mapboxMap.queryRenderedFeatures(
+ mapboxMap.getProjection().toScreenLocation(latLng), "layer").isEmpty()
+ );
+ assertNull(layer.getTextField().getExpression());
+ assertEquals("$12.35", layer.getTextField().getValue().getFormattedSections()[0].getText());
+ });
+ }
+
+ @Test
+ public void testNumberFormatMaxExpression() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ mapboxMap.getStyle()
+ .addSource(new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude())));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ layer.setProperties(
+ textField(
+ numberFormat(12.34567890, maxFractionDigits(5), minFractionDigits(0))
+ )
+ );
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(mapboxMap.queryRenderedFeatures(
+ mapboxMap.getProjection().toScreenLocation(latLng), "layer").isEmpty()
+ );
+ assertNull(layer.getTextField().getExpression());
+ assertEquals("12.34568", layer.getTextField().getValue().getFormattedSections()[0].getText());
+ });
+ }
+
+ @Test
+ public void testNumberFormatMinExpression() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ mapboxMap.getStyle()
+ .addSource(new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude())));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ layer.setProperties(
+ textField(
+ numberFormat(12.0000001, maxFractionDigits(5), minFractionDigits(0))
+ )
+ );
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(mapboxMap.queryRenderedFeatures(
+ mapboxMap.getProjection().toScreenLocation(latLng), "layer").isEmpty()
+ );
+ assertNull(layer.getTextField().getExpression());
+ assertEquals("12", layer.getTextField().getValue().getFormattedSections()[0].getText());
+ });
+ }
+
+ @Test
+ public void testNumberFormatLocaleExpression() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ mapboxMap.getStyle()
+ .addSource(new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude())));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ layer.setProperties(
+ textField(
+ numberFormat(12.0000001, locale("nl-BE"), maxFractionDigits(5), minFractionDigits(1))
+ )
+ );
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(mapboxMap.queryRenderedFeatures(
+ mapboxMap.getProjection().toScreenLocation(latLng), "layer").isEmpty()
+ );
+ assertNull(layer.getTextField().getExpression());
+ assertEquals("12,0", layer.getTextField().getValue().getFormattedSections()[0].getText());
+ });
+ }
+
+ @Test
+ public void testNumberFormatNonConstantExpression() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ Feature feature = Feature.fromGeometry(Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude()));
+ feature.addNumberProperty("number_value", 12.345678);
+ feature.addStringProperty("locale_value", "nl-BE");
+ feature.addNumberProperty("max_value", 5);
+ feature.addNumberProperty("min_value", 1);
+
+
+ mapboxMap.getStyle().addSource(new GeoJsonSource("source", feature));
+ SymbolLayer layer = new SymbolLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ Expression numberFormatExpression = numberFormat(
+ number(number(get("number_value"))),
+ locale(string(get("locale_value"))),
+ maxFractionDigits(number(get("max_value"))),
+ minFractionDigits(number(get("min_value")))
+ );
+
+ layer.setProperties(textField(numberFormatExpression));
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+
+ assertFalse(mapboxMap.queryRenderedFeatures(
+ mapboxMap.getProjection().toScreenLocation(latLng), "layer").isEmpty()
+ );
+
+ assertNotNull(layer.getTextField().getExpression());
+
+ // Expressions evaluated to string are wrapped by a format expression, take array index 1 to get original
+ Object[] returnExpression = (Object[]) layer.getTextField().getExpression().toArray()[1];
+ Object[] setExpression = numberFormatExpression.toArray();
+ assertEquals("Number format should match",returnExpression[0], setExpression[0]);
+ assertArrayEquals("Get value expression should match",
+ (Object[]) returnExpression[1],
+ (Object[]) setExpression[1]
+ );
+
+ // number format objects
+ HashMap<String, Object> returnMap = (HashMap<String, Object>) returnExpression[2];
+ HashMap<String, Object> setMap = (HashMap<String, Object>) returnExpression[2];
+
+ assertArrayEquals("Number format min fraction digits should match ",
+ (Object[]) returnMap.get("min-fraction-digits"),
+ (Object[]) setMap.get("min-fraction-digits")
+ );
+
+ assertArrayEquals("Number format max fraction digits should match ",
+ (Object[]) returnMap.get("max-fraction-digits"),
+ (Object[]) setMap.get("max-fraction-digits")
+ );
+
+ assertArrayEquals("Number format min fraction digits should match ",
+ (Object[]) returnMap.get("locale"),
+ (Object[]) setMap.get("locale")
+ );
+ });
+
+ }
+
+ /**
+ * Regression test for #15532
+ */
+ @Test
+ public void testDoubleConversion() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ LatLng latLng = new LatLng(51, 17);
+ mapboxMap.getStyle().addSource(
+ new GeoJsonSource("source", Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude()))
+ );
+
+ CircleLayer layer = new CircleLayer("layer", "source");
+ mapboxMap.getStyle().addLayer(layer);
+
+ Expression input = interpolate(
+ exponential(0.5f), zoom(),
+ stop(-0.1, color(Color.RED)),
+ stop(0, color(Color.BLUE))
+ );
+
+ layer.setProperties(circleColor(input));
+
+ Expression output = layer.getCircleColor().getExpression();
+ assertArrayEquals("Expression should match", input.toArray(), output.toArray());
+ });
+ }
+
+ private void setupStyle() {
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ // Add a source
+ Source source;
+ try {
+ source = new GeoJsonSource("amsterdam-parks-source",
+ ResourceUtils.readRawResource(rule.getActivity(), R.raw.amsterdam));
+ mapboxMap.getStyle().addSource(source);
+ } catch (IOException ioException) {
+ return;
+ }
+
+ // Add a fill layer
+ mapboxMap.getStyle().addLayer(layer = new FillLayer("amsterdam-parks-layer", source.getId())
+ .withProperties(
+ fillColor(rgba(0.0f, 0.0f, 0.0f, 0.5f)),
+ fillOutlineColor(rgb(0, 0, 255)),
+ fillAntialias(true)
+ )
+ );
+ });
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java
new file mode 100644
index 0000000000..cdfd030f9b
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java
@@ -0,0 +1,340 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
+
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.maps.BaseLayerTest;
+import org.junit.Before;
+import timber.log.Timber;
+
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
+
+/**
+ * Basic smoke tests for FillExtrusionLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class FillExtrusionLayerTest extends BaseLayerTest {
+
+ private FillExtrusionLayer layer;
+
+ @Before
+ @UiThreadTest
+ public void beforeTest(){
+ super.before();
+ layer = new FillExtrusionLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ setupLayer(layer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSourceId() {
+ Timber.i("SourceId");
+ assertNotNull(layer);
+ assertEquals(layer.getSourceId(), "composite");
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSetVisibility() {
+ Timber.i("Visibility");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSourceLayer() {
+ Timber.i("SourceLayer");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFilter() {
+ Timber.i("Filter");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getFilter(), null);
+
+ // Set
+ Expression filter = eq(get("undefined"), literal(1.0));
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
+
+ // Set constant
+ filter = literal(true);
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
+ }
+
+
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionOpacityTransition() {
+ Timber.i("fill-extrusion-opacityTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionOpacityTransition(options);
+ assertEquals(layer.getFillExtrusionOpacityTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionOpacityAsConstant() {
+ Timber.i("fill-extrusion-opacity");
+ assertNotNull(layer);
+ assertNull(layer.getFillExtrusionOpacity().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(fillExtrusionOpacity(propertyValue));
+ assertEquals(layer.getFillExtrusionOpacity().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionColorTransition() {
+ Timber.i("fill-extrusion-colorTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionColorTransition(options);
+ assertEquals(layer.getFillExtrusionColorTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionColorAsConstant() {
+ Timber.i("fill-extrusion-color");
+ assertNotNull(layer);
+ assertNull(layer.getFillExtrusionColor().getValue());
+
+ // Set and Get
+ String propertyValue = "rgba(255,128,0,0.7)";
+ layer.setProperties(fillExtrusionColor(propertyValue));
+ assertEquals(layer.getFillExtrusionColor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionColorAsExpression() {
+ Timber.i("fill-extrusion-color-expression");
+ assertNotNull(layer);
+ assertNull(layer.getFillExtrusionColor().getExpression());
+
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(fillExtrusionColor(expression));
+ assertEquals(layer.getFillExtrusionColor().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionColorAsIntConstant() {
+ Timber.i("fill-extrusion-color");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillExtrusionColor(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.getFillExtrusionColorAsInt(), Color.argb(127, 255, 127, 0));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionTranslateTransition() {
+ Timber.i("fill-extrusion-translateTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionTranslateTransition(options);
+ assertEquals(layer.getFillExtrusionTranslateTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionTranslateAsConstant() {
+ Timber.i("fill-extrusion-translate");
+ assertNotNull(layer);
+ assertNull(layer.getFillExtrusionTranslate().getValue());
+
+ // Set and Get
+ Float[] propertyValue = new Float[] {0f, 0f};
+ layer.setProperties(fillExtrusionTranslate(propertyValue));
+ assertEquals(layer.getFillExtrusionTranslate().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionTranslateAnchorAsConstant() {
+ Timber.i("fill-extrusion-translate-anchor");
+ assertNotNull(layer);
+ assertNull(layer.getFillExtrusionTranslateAnchor().getValue());
+
+ // Set and Get
+ String propertyValue = FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP;
+ layer.setProperties(fillExtrusionTranslateAnchor(propertyValue));
+ assertEquals(layer.getFillExtrusionTranslateAnchor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionPatternTransition() {
+ Timber.i("fill-extrusion-patternTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionPatternTransition(options);
+ assertEquals(layer.getFillExtrusionPatternTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionPatternAsConstant() {
+ Timber.i("fill-extrusion-pattern");
+ assertNotNull(layer);
+ assertNull(layer.getFillExtrusionPattern().getValue());
+
+ // Set and Get
+ String propertyValue = "pedestrian-polygon";
+ layer.setProperties(fillExtrusionPattern(propertyValue));
+ assertEquals(layer.getFillExtrusionPattern().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionPatternAsExpression() {
+ Timber.i("fill-extrusion-pattern-expression");
+ assertNotNull(layer);
+ assertNull(layer.getFillExtrusionPattern().getExpression());
+
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(fillExtrusionPattern(expression));
+ assertEquals(layer.getFillExtrusionPattern().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionHeightTransition() {
+ Timber.i("fill-extrusion-heightTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionHeightTransition(options);
+ assertEquals(layer.getFillExtrusionHeightTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionHeightAsConstant() {
+ Timber.i("fill-extrusion-height");
+ assertNotNull(layer);
+ assertNull(layer.getFillExtrusionHeight().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(fillExtrusionHeight(propertyValue));
+ assertEquals(layer.getFillExtrusionHeight().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionHeightAsExpression() {
+ Timber.i("fill-extrusion-height-expression");
+ assertNotNull(layer);
+ assertNull(layer.getFillExtrusionHeight().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(fillExtrusionHeight(expression));
+ assertEquals(layer.getFillExtrusionHeight().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionBaseTransition() {
+ Timber.i("fill-extrusion-baseTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionBaseTransition(options);
+ assertEquals(layer.getFillExtrusionBaseTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionBaseAsConstant() {
+ Timber.i("fill-extrusion-base");
+ assertNotNull(layer);
+ assertNull(layer.getFillExtrusionBase().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(fillExtrusionBase(propertyValue));
+ assertEquals(layer.getFillExtrusionBase().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionBaseAsExpression() {
+ Timber.i("fill-extrusion-base-expression");
+ assertNotNull(layer);
+ assertNull(layer.getFillExtrusionBase().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(fillExtrusionBase(expression));
+ assertEquals(layer.getFillExtrusionBase().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillExtrusionVerticalGradientAsConstant() {
+ Timber.i("fill-extrusion-vertical-gradient");
+ assertNotNull(layer);
+ assertNull(layer.getFillExtrusionVerticalGradient().getValue());
+
+ // Set and Get
+ Boolean propertyValue = true;
+ layer.setProperties(fillExtrusionVerticalGradient(propertyValue));
+ assertEquals(layer.getFillExtrusionVerticalGradient().getValue(), propertyValue);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java
new file mode 100644
index 0000000000..f6e3cc8548
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java
@@ -0,0 +1,326 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
+
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.maps.BaseLayerTest;
+import org.junit.Before;
+import timber.log.Timber;
+
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.FillLayer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
+
+/**
+ * Basic smoke tests for FillLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class FillLayerTest extends BaseLayerTest {
+
+ private FillLayer layer;
+
+ @Before
+ @UiThreadTest
+ public void beforeTest(){
+ super.before();
+ layer = new FillLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ setupLayer(layer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSourceId() {
+ Timber.i("SourceId");
+ assertNotNull(layer);
+ assertEquals(layer.getSourceId(), "composite");
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSetVisibility() {
+ Timber.i("Visibility");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSourceLayer() {
+ Timber.i("SourceLayer");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFilter() {
+ Timber.i("Filter");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getFilter(), null);
+
+ // Set
+ Expression filter = eq(get("undefined"), literal(1.0));
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
+
+ // Set constant
+ filter = literal(true);
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
+ }
+
+
+
+ @Test
+ @UiThreadTest
+ public void testFillAntialiasAsConstant() {
+ Timber.i("fill-antialias");
+ assertNotNull(layer);
+ assertNull(layer.getFillAntialias().getValue());
+
+ // Set and Get
+ Boolean propertyValue = true;
+ layer.setProperties(fillAntialias(propertyValue));
+ assertEquals(layer.getFillAntialias().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillOpacityTransition() {
+ Timber.i("fill-opacityTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillOpacityTransition(options);
+ assertEquals(layer.getFillOpacityTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillOpacityAsConstant() {
+ Timber.i("fill-opacity");
+ assertNotNull(layer);
+ assertNull(layer.getFillOpacity().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(fillOpacity(propertyValue));
+ assertEquals(layer.getFillOpacity().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillOpacityAsExpression() {
+ Timber.i("fill-opacity-expression");
+ assertNotNull(layer);
+ assertNull(layer.getFillOpacity().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(fillOpacity(expression));
+ assertEquals(layer.getFillOpacity().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillColorTransition() {
+ Timber.i("fill-colorTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillColorTransition(options);
+ assertEquals(layer.getFillColorTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillColorAsConstant() {
+ Timber.i("fill-color");
+ assertNotNull(layer);
+ assertNull(layer.getFillColor().getValue());
+
+ // Set and Get
+ String propertyValue = "rgba(255,128,0,0.7)";
+ layer.setProperties(fillColor(propertyValue));
+ assertEquals(layer.getFillColor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillColorAsExpression() {
+ Timber.i("fill-color-expression");
+ assertNotNull(layer);
+ assertNull(layer.getFillColor().getExpression());
+
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(fillColor(expression));
+ assertEquals(layer.getFillColor().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillColorAsIntConstant() {
+ Timber.i("fill-color");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillColor(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.getFillColorAsInt(), Color.argb(127, 255, 127, 0));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillOutlineColorTransition() {
+ Timber.i("fill-outline-colorTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillOutlineColorTransition(options);
+ assertEquals(layer.getFillOutlineColorTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillOutlineColorAsConstant() {
+ Timber.i("fill-outline-color");
+ assertNotNull(layer);
+ assertNull(layer.getFillOutlineColor().getValue());
+
+ // Set and Get
+ String propertyValue = "rgba(255,128,0,0.7)";
+ layer.setProperties(fillOutlineColor(propertyValue));
+ assertEquals(layer.getFillOutlineColor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillOutlineColorAsExpression() {
+ Timber.i("fill-outline-color-expression");
+ assertNotNull(layer);
+ assertNull(layer.getFillOutlineColor().getExpression());
+
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(fillOutlineColor(expression));
+ assertEquals(layer.getFillOutlineColor().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillOutlineColorAsIntConstant() {
+ Timber.i("fill-outline-color");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillOutlineColor(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.getFillOutlineColorAsInt(), Color.argb(127, 255, 127, 0));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillTranslateTransition() {
+ Timber.i("fill-translateTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillTranslateTransition(options);
+ assertEquals(layer.getFillTranslateTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillTranslateAsConstant() {
+ Timber.i("fill-translate");
+ assertNotNull(layer);
+ assertNull(layer.getFillTranslate().getValue());
+
+ // Set and Get
+ Float[] propertyValue = new Float[] {0f, 0f};
+ layer.setProperties(fillTranslate(propertyValue));
+ assertEquals(layer.getFillTranslate().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillTranslateAnchorAsConstant() {
+ Timber.i("fill-translate-anchor");
+ assertNotNull(layer);
+ assertNull(layer.getFillTranslateAnchor().getValue());
+
+ // Set and Get
+ String propertyValue = FILL_TRANSLATE_ANCHOR_MAP;
+ layer.setProperties(fillTranslateAnchor(propertyValue));
+ assertEquals(layer.getFillTranslateAnchor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillPatternTransition() {
+ Timber.i("fill-patternTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillPatternTransition(options);
+ assertEquals(layer.getFillPatternTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillPatternAsConstant() {
+ Timber.i("fill-pattern");
+ assertNotNull(layer);
+ assertNull(layer.getFillPattern().getValue());
+
+ // Set and Get
+ String propertyValue = "pedestrian-polygon";
+ layer.setProperties(fillPattern(propertyValue));
+ assertEquals(layer.getFillPattern().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFillPatternAsExpression() {
+ Timber.i("fill-pattern-expression");
+ assertNotNull(layer);
+ assertNull(layer.getFillPattern().getExpression());
+
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(fillPattern(expression));
+ assertEquals(layer.getFillPattern().getExpression(), expression);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/GeoJsonSourceTests.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/GeoJsonSourceTests.java
new file mode 100644
index 0000000000..61086e1344
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/GeoJsonSourceTests.java
@@ -0,0 +1,189 @@
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.support.annotation.RawRes;
+import android.support.test.espresso.ViewAction;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+
+import com.mapbox.geojson.Feature;
+import com.mapbox.geojson.FeatureCollection;
+import com.mapbox.geojson.Point;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.style.layers.CircleLayer;
+import com.mapbox.mapboxsdk.style.layers.Layer;
+import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
+import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
+import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
+import com.mapbox.mapboxsdk.testapp.utils.TestingAsyncUtils;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import timber.log.Timber;
+
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for {@link GeoJsonSource}
+ */
+@RunWith(AndroidJUnit4.class)
+public class GeoJsonSourceTests extends EspressoTest {
+
+ @Test
+ public void testFeatureCollection() {
+ validateTestSetup();
+ MapboxMapAction.invoke(mapboxMap, (uiController, mapboxMap) -> {
+ GeoJsonSource source = null;
+ try {
+ source = new GeoJsonSource("source", FeatureCollection
+ .fromJson(ResourceUtils.readRawResource(rule.getActivity(), R.raw.test_feature_collection)));
+ } catch (IOException exception) {
+ Timber.e(exception);
+ }
+ mapboxMap.getStyle().addSource(source);
+ mapboxMap.getStyle().addLayer(new CircleLayer("layer", source.getId()));
+ });
+ }
+
+ @Test
+ public void testPointGeometry() {
+ validateTestSetup();
+ MapboxMapAction.invoke(mapboxMap, (uiController, mapboxMap) -> {
+ GeoJsonSource source = new GeoJsonSource("source", Point.fromLngLat(0d, 0d));
+ mapboxMap.getStyle().addSource(source);
+ mapboxMap.getStyle().addLayer(new CircleLayer("layer", source.getId()));
+ });
+ }
+
+ @Test
+ public void testFeatureProperties() {
+ validateTestSetup();
+ MapboxMapAction.invoke(mapboxMap, (uiController, mapboxMap) -> {
+ GeoJsonSource source = null;
+ try {
+ source = new GeoJsonSource("source",
+ ResourceUtils.readRawResource(rule.getActivity(), R.raw.test_feature_properties));
+ } catch (IOException exception) {
+ Timber.e(exception);
+ }
+ mapboxMap.getStyle().addSource(source);
+ mapboxMap.getStyle().addLayer(new CircleLayer("layer", source.getId()));
+ });
+ }
+
+ @Test
+ public void testUpdateCoalescing() {
+ validateTestSetup();
+ MapboxMapAction.invoke(mapboxMap, (uiController, mapboxMap) -> {
+ GeoJsonSource source = new GeoJsonSource("source");
+ mapboxMap.getStyle().addSource(source);
+ mapboxMap.getStyle().addLayer(new CircleLayer("layer", source.getId()));
+
+ source.setGeoJson(Point.fromLngLat(0, 0));
+ source.setGeoJson(Point.fromLngLat(-25, -25));
+ try {
+ source.setGeoJson(ResourceUtils.readRawResource(rule.getActivity(), R.raw.test_feature_properties));
+ } catch (IOException exception) {
+ Timber.e(exception);
+ }
+
+ source.setGeoJson(Point.fromLngLat(20, 55));
+ TestingAsyncUtils.INSTANCE.waitForLayer(uiController, mapView);
+ assertEquals(1, mapboxMap.queryRenderedFeatures(
+ mapboxMap.getProjection().toScreenLocation(
+ new LatLng(55, 20)), "layer").size());
+ });
+ }
+
+ @Test
+ public void testClearCollectionDuringConversion() {
+ // https://github.com/mapbox/mapbox-gl-native/issues/14565
+ validateTestSetup();
+ MapboxMapAction.invoke(mapboxMap, (uiController, mapboxMap) -> {
+ for (int j = 0; j < 1000; j++) {
+ List<Feature> features = new ArrayList<>();
+ for (int i = 0; i < 100; i++) {
+ features.add(Feature.fromGeometry(Point.fromLngLat(0, 0)));
+ }
+ mapboxMap.getStyle().addSource(new GeoJsonSource("source" + j, FeatureCollection.fromFeatures(features)));
+ features.clear();
+ }
+ });
+ }
+
+ @Test
+ public void testPointFeature() {
+ testFeatureFromResource(R.raw.test_point_feature);
+ }
+
+ @Test
+ public void testLineStringFeature() {
+ testFeatureFromResource(R.raw.test_line_string_feature);
+ }
+
+ @Test
+ public void testPolygonFeature() {
+ testFeatureFromResource(R.raw.test_polygon_feature);
+ }
+
+ @Test
+ public void testPolygonWithHoleFeature() {
+ testFeatureFromResource(R.raw.test_polygon_with_hole_feature);
+ }
+
+ @Test
+ public void testMultiPointFeature() {
+ testFeatureFromResource(R.raw.test_multi_point_feature);
+ }
+
+ @Test
+ public void testMultiLineStringFeature() {
+ testFeatureFromResource(R.raw.test_multi_line_string_feature);
+ }
+
+ @Test
+ public void testMultiPolygonFeature() {
+ testFeatureFromResource(R.raw.test_multi_polygon_feature);
+ }
+
+ protected void testFeatureFromResource(final @RawRes int resource) {
+ validateTestSetup();
+ MapboxMapAction.invoke(mapboxMap, (uiController, mapboxMap) -> {
+ GeoJsonSource source = new GeoJsonSource("source");
+ mapboxMap.getStyle().addSource(source);
+ Layer layer = new CircleLayer("layer", source.getId());
+ mapboxMap.getStyle().addLayer(layer);
+
+ try {
+ source.setGeoJson(Feature.fromJson(ResourceUtils.readRawResource(rule.getActivity(), resource)));
+ } catch (IOException exception) {
+ Timber.e(exception);
+ }
+
+ mapboxMap.getStyle().removeLayer(layer);
+ mapboxMap.getStyle().removeSource(source);
+ });
+ }
+
+ public abstract class BaseViewAction implements ViewAction {
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HeatmapLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HeatmapLayerTest.java
new file mode 100644
index 0000000000..21a17723db
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HeatmapLayerTest.java
@@ -0,0 +1,215 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
+
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.maps.BaseLayerTest;
+import org.junit.Before;
+import timber.log.Timber;
+
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.HeatmapLayer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
+
+/**
+ * Basic smoke tests for HeatmapLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class HeatmapLayerTest extends BaseLayerTest {
+
+ private HeatmapLayer layer;
+
+ @Before
+ @UiThreadTest
+ public void beforeTest(){
+ super.before();
+ layer = new HeatmapLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ setupLayer(layer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSourceId() {
+ Timber.i("SourceId");
+ assertNotNull(layer);
+ assertEquals(layer.getSourceId(), "composite");
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSetVisibility() {
+ Timber.i("Visibility");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSourceLayer() {
+ Timber.i("SourceLayer");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFilter() {
+ Timber.i("Filter");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getFilter(), null);
+
+ // Set
+ Expression filter = eq(get("undefined"), literal(1.0));
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
+
+ // Set constant
+ filter = literal(true);
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
+ }
+
+
+
+ @Test
+ @UiThreadTest
+ public void testHeatmapRadiusTransition() {
+ Timber.i("heatmap-radiusTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setHeatmapRadiusTransition(options);
+ assertEquals(layer.getHeatmapRadiusTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHeatmapRadiusAsConstant() {
+ Timber.i("heatmap-radius");
+ assertNotNull(layer);
+ assertNull(layer.getHeatmapRadius().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(heatmapRadius(propertyValue));
+ assertEquals(layer.getHeatmapRadius().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHeatmapRadiusAsExpression() {
+ Timber.i("heatmap-radius-expression");
+ assertNotNull(layer);
+ assertNull(layer.getHeatmapRadius().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(heatmapRadius(expression));
+ assertEquals(layer.getHeatmapRadius().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHeatmapWeightAsConstant() {
+ Timber.i("heatmap-weight");
+ assertNotNull(layer);
+ assertNull(layer.getHeatmapWeight().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(heatmapWeight(propertyValue));
+ assertEquals(layer.getHeatmapWeight().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHeatmapWeightAsExpression() {
+ Timber.i("heatmap-weight-expression");
+ assertNotNull(layer);
+ assertNull(layer.getHeatmapWeight().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(heatmapWeight(expression));
+ assertEquals(layer.getHeatmapWeight().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHeatmapIntensityTransition() {
+ Timber.i("heatmap-intensityTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setHeatmapIntensityTransition(options);
+ assertEquals(layer.getHeatmapIntensityTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHeatmapIntensityAsConstant() {
+ Timber.i("heatmap-intensity");
+ assertNotNull(layer);
+ assertNull(layer.getHeatmapIntensity().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(heatmapIntensity(propertyValue));
+ assertEquals(layer.getHeatmapIntensity().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHeatmapOpacityTransition() {
+ Timber.i("heatmap-opacityTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setHeatmapOpacityTransition(options);
+ assertEquals(layer.getHeatmapOpacityTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHeatmapOpacityAsConstant() {
+ Timber.i("heatmap-opacity");
+ assertNotNull(layer);
+ assertNull(layer.getHeatmapOpacity().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(heatmapOpacity(propertyValue));
+ assertEquals(layer.getHeatmapOpacity().getValue(), propertyValue);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HillshadeLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HillshadeLayerTest.java
new file mode 100644
index 0000000000..694348b888
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HillshadeLayerTest.java
@@ -0,0 +1,223 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
+
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.maps.BaseLayerTest;
+import org.junit.Before;
+import timber.log.Timber;
+
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.HillshadeLayer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
+
+/**
+ * Basic smoke tests for HillshadeLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class HillshadeLayerTest extends BaseLayerTest {
+
+ private HillshadeLayer layer;
+
+ @Before
+ @UiThreadTest
+ public void beforeTest(){
+ super.before();
+ layer = new HillshadeLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ setupLayer(layer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSourceId() {
+ Timber.i("SourceId");
+ assertNotNull(layer);
+ assertEquals(layer.getSourceId(), "composite");
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSetVisibility() {
+ Timber.i("Visibility");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHillshadeIlluminationDirectionAsConstant() {
+ Timber.i("hillshade-illumination-direction");
+ assertNotNull(layer);
+ assertNull(layer.getHillshadeIlluminationDirection().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(hillshadeIlluminationDirection(propertyValue));
+ assertEquals(layer.getHillshadeIlluminationDirection().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHillshadeIlluminationAnchorAsConstant() {
+ Timber.i("hillshade-illumination-anchor");
+ assertNotNull(layer);
+ assertNull(layer.getHillshadeIlluminationAnchor().getValue());
+
+ // Set and Get
+ String propertyValue = HILLSHADE_ILLUMINATION_ANCHOR_MAP;
+ layer.setProperties(hillshadeIlluminationAnchor(propertyValue));
+ assertEquals(layer.getHillshadeIlluminationAnchor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHillshadeExaggerationTransition() {
+ Timber.i("hillshade-exaggerationTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setHillshadeExaggerationTransition(options);
+ assertEquals(layer.getHillshadeExaggerationTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHillshadeExaggerationAsConstant() {
+ Timber.i("hillshade-exaggeration");
+ assertNotNull(layer);
+ assertNull(layer.getHillshadeExaggeration().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(hillshadeExaggeration(propertyValue));
+ assertEquals(layer.getHillshadeExaggeration().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHillshadeShadowColorTransition() {
+ Timber.i("hillshade-shadow-colorTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setHillshadeShadowColorTransition(options);
+ assertEquals(layer.getHillshadeShadowColorTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHillshadeShadowColorAsConstant() {
+ Timber.i("hillshade-shadow-color");
+ assertNotNull(layer);
+ assertNull(layer.getHillshadeShadowColor().getValue());
+
+ // Set and Get
+ String propertyValue = "rgba(255,128,0,0.7)";
+ layer.setProperties(hillshadeShadowColor(propertyValue));
+ assertEquals(layer.getHillshadeShadowColor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHillshadeShadowColorAsIntConstant() {
+ Timber.i("hillshade-shadow-color");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(hillshadeShadowColor(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.getHillshadeShadowColorAsInt(), Color.argb(127, 255, 127, 0));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHillshadeHighlightColorTransition() {
+ Timber.i("hillshade-highlight-colorTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setHillshadeHighlightColorTransition(options);
+ assertEquals(layer.getHillshadeHighlightColorTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHillshadeHighlightColorAsConstant() {
+ Timber.i("hillshade-highlight-color");
+ assertNotNull(layer);
+ assertNull(layer.getHillshadeHighlightColor().getValue());
+
+ // Set and Get
+ String propertyValue = "rgba(255,128,0,0.7)";
+ layer.setProperties(hillshadeHighlightColor(propertyValue));
+ assertEquals(layer.getHillshadeHighlightColor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHillshadeHighlightColorAsIntConstant() {
+ Timber.i("hillshade-highlight-color");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(hillshadeHighlightColor(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.getHillshadeHighlightColorAsInt(), Color.argb(127, 255, 127, 0));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHillshadeAccentColorTransition() {
+ Timber.i("hillshade-accent-colorTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setHillshadeAccentColorTransition(options);
+ assertEquals(layer.getHillshadeAccentColorTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHillshadeAccentColorAsConstant() {
+ Timber.i("hillshade-accent-color");
+ assertNotNull(layer);
+ assertNull(layer.getHillshadeAccentColor().getValue());
+
+ // Set and Get
+ String propertyValue = "rgba(255,128,0,0.7)";
+ layer.setProperties(hillshadeAccentColor(propertyValue));
+ assertEquals(layer.getHillshadeAccentColor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testHillshadeAccentColorAsIntConstant() {
+ Timber.i("hillshade-accent-color");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(hillshadeAccentColor(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.getHillshadeAccentColorAsInt(), Color.argb(127, 255, 127, 0));
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.kt
new file mode 100644
index 0000000000..eb45ab52c6
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ImageTest.kt
@@ -0,0 +1,75 @@
+package com.mapbox.mapboxsdk.testapp.style
+
+import android.graphics.Bitmap
+import android.graphics.drawable.BitmapDrawable
+import android.support.test.runner.AndroidJUnit4
+import com.mapbox.mapboxsdk.testapp.R
+import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction
+import com.mapbox.mapboxsdk.testapp.activity.EspressoTest
+import java.util.*
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * CRUD tests around Image
+ */
+@RunWith(AndroidJUnit4::class)
+class ImageTest : EspressoTest() {
+
+ companion object {
+ private const val IMAGE_ID = "test.image"
+ }
+
+ @Test
+ fun testAddGetImage() {
+ validateTestSetup()
+ MapboxMapAction.invoke(mapboxMap) { uiController, mapboxMap ->
+ val drawable = rule.activity.resources.getDrawable(R.drawable.ic_launcher_round)
+ assertTrue(drawable is BitmapDrawable)
+
+ val bitmapSet = (drawable as BitmapDrawable).bitmap
+ mapboxMap.style!!.addImage(IMAGE_ID, bitmapSet)
+
+ // adding an image requires converting the image with an asynctask
+ uiController.loopMainThreadForAtLeast(200)
+
+ val bitmapGet = mapboxMap.style!!.getImage(IMAGE_ID)
+ assertTrue(bitmapGet!!.similarTo(bitmapSet))
+
+ mapboxMap.style!!.removeImage(IMAGE_ID)
+ assertNull(mapboxMap.style!!.getImage(IMAGE_ID))
+ }
+ }
+}
+
+/**
+ * Alternative implementation of Bitmap.sameAs #14060
+ */
+fun Bitmap.similarTo(other: Bitmap): Boolean {
+ if (invalidConfig(other)) {
+ return false
+ }
+
+ // Allocate arrays
+ val argb = IntArray(width * height)
+ val argbOther = IntArray(other.width * other.height)
+ getPixels(argb, 0, width, 0, 0, width, height)
+ other.getPixels(argbOther, 0, width, 0, 0, width, height)
+
+ // Alpha channel special check
+ if (config == Bitmap.Config.ALPHA_8) {
+ // in this case we have to manually compare the alpha channel as the rest is garbage.
+ val length = width * height
+ for (i in 0 until length) {
+ if (argb[i] and -0x1000000 != argbOther[i] and -0x1000000) {
+ return false
+ }
+ }
+ return true
+ }
+ return Arrays.equals(argb, argbOther)
+}
+
+fun Bitmap.invalidConfig(other: Bitmap): Boolean = this.config != other.config || this.width != other.width || this.height != other.height \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java
new file mode 100644
index 0000000000..b78a2d26e5
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java
@@ -0,0 +1,172 @@
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.style.light.Light;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer;
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
+import com.mapbox.mapboxsdk.style.light.Position;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.BaseTest;
+import com.mapbox.mapboxsdk.testapp.activity.style.FillExtrusionStyleTestActivity;
+
+import timber.log.Timber;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
+import static com.mapbox.mapboxsdk.style.layers.Property.ANCHOR_MAP;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionBase;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionHeight;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionOpacity;
+
+import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+
+@RunWith(AndroidJUnit4.class)
+public class LightTest extends BaseTest {
+
+ private Light light;
+
+ @Test
+ public void testAnchor() {
+ validateTestSetup();
+ setupLight();
+ Timber.i("anchor");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ light.setAnchor(ANCHOR_MAP);
+ assertEquals("Anchor should match", ANCHOR_MAP, light.getAnchor());
+ });
+ }
+
+ @Test
+ public void testPositionTransition() {
+ validateTestSetup();
+ setupLight();
+ Timber.i("positionTransitionOptions");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ light.setPositionTransition(options);
+ assertEquals("Transition options should match", options, light.getPositionTransition());
+ });
+ }
+
+ @Test
+ public void testPosition() {
+ validateTestSetup();
+ setupLight();
+ Timber.i("position");
+ invoke(mapboxMap,(uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ Position position = new Position(1, 2, 3);
+ light.setPosition(position);
+ assertEquals("Position should match", position, light.getPosition());
+ });
+ }
+
+ @Test
+ public void testColorTransition() {
+ validateTestSetup();
+ setupLight();
+ Timber.i("colorTransitionOptions");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ light.setColorTransition(options);
+ assertEquals("Transition options should match", options, light.getColorTransition());
+ });
+ }
+
+ @Test
+ public void testColor() {
+ validateTestSetup();
+ setupLight();
+ Timber.i("color");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ light.setColor("rgba(255,128,0,0.7)");
+ assertEquals("Color should match", "rgba(255,128,0,0.7)", light.getColor());
+ });
+ }
+
+ @Test
+ public void testIntensityTransition() {
+ validateTestSetup();
+ setupLight();
+ Timber.i("intensityTransitionOptions");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ light.setIntensityTransition(options);
+ assertEquals("Transition options should match", options, light.getIntensityTransition());
+ });
+ }
+
+ @Test
+ public void testIntensity() {
+ validateTestSetup();
+ setupLight();
+ Timber.i("intensity");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ light.setIntensity(0.3f);
+ assertEquals("Intensity should match", 0.3f, light.getIntensity());
+ });
+ }
+
+ private void setupLight() {
+ onView(withId(R.id.mapView)).perform(new ViewAction() {
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ light = mapboxMap.getStyle().getLight();
+ FillExtrusionLayer fillExtrusionLayer = new FillExtrusionLayer("3d-buildings", "composite");
+ fillExtrusionLayer.setSourceLayer("building");
+ fillExtrusionLayer.setFilter(eq(Expression.get("extrude"), "true"));
+ fillExtrusionLayer.setMinZoom(15);
+ fillExtrusionLayer.setProperties(
+ fillExtrusionColor(Color.LTGRAY),
+ fillExtrusionHeight(Expression.get("height")),
+ fillExtrusionBase(Expression.get("min_height")),
+ fillExtrusionOpacity(0.6f)
+ );
+ mapboxMap.getStyle().addLayer(fillExtrusionLayer);
+ }
+ });
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return FillExtrusionStyleTestActivity.class;
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java
new file mode 100644
index 0000000000..5e00890f7f
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java
@@ -0,0 +1,493 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
+
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.maps.BaseLayerTest;
+import org.junit.Before;
+import timber.log.Timber;
+
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.LineLayer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
+
+/**
+ * Basic smoke tests for LineLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class LineLayerTest extends BaseLayerTest {
+
+ private LineLayer layer;
+
+ @Before
+ @UiThreadTest
+ public void beforeTest(){
+ super.before();
+ layer = new LineLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ setupLayer(layer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSourceId() {
+ Timber.i("SourceId");
+ assertNotNull(layer);
+ assertEquals(layer.getSourceId(), "composite");
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSetVisibility() {
+ Timber.i("Visibility");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSourceLayer() {
+ Timber.i("SourceLayer");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFilter() {
+ Timber.i("Filter");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getFilter(), null);
+
+ // Set
+ Expression filter = eq(get("undefined"), literal(1.0));
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
+
+ // Set constant
+ filter = literal(true);
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
+ }
+
+
+
+ @Test
+ @UiThreadTest
+ public void testLineCapAsConstant() {
+ Timber.i("line-cap");
+ assertNotNull(layer);
+ assertNull(layer.getLineCap().getValue());
+
+ // Set and Get
+ String propertyValue = LINE_CAP_BUTT;
+ layer.setProperties(lineCap(propertyValue));
+ assertEquals(layer.getLineCap().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineJoinAsConstant() {
+ Timber.i("line-join");
+ assertNotNull(layer);
+ assertNull(layer.getLineJoin().getValue());
+
+ // Set and Get
+ String propertyValue = LINE_JOIN_BEVEL;
+ layer.setProperties(lineJoin(propertyValue));
+ assertEquals(layer.getLineJoin().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineJoinAsExpression() {
+ Timber.i("line-join-expression");
+ assertNotNull(layer);
+ assertNull(layer.getLineJoin().getExpression());
+
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(lineJoin(expression));
+ assertEquals(layer.getLineJoin().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineMiterLimitAsConstant() {
+ Timber.i("line-miter-limit");
+ assertNotNull(layer);
+ assertNull(layer.getLineMiterLimit().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(lineMiterLimit(propertyValue));
+ assertEquals(layer.getLineMiterLimit().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineRoundLimitAsConstant() {
+ Timber.i("line-round-limit");
+ assertNotNull(layer);
+ assertNull(layer.getLineRoundLimit().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(lineRoundLimit(propertyValue));
+ assertEquals(layer.getLineRoundLimit().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineOpacityTransition() {
+ Timber.i("line-opacityTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineOpacityTransition(options);
+ assertEquals(layer.getLineOpacityTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineOpacityAsConstant() {
+ Timber.i("line-opacity");
+ assertNotNull(layer);
+ assertNull(layer.getLineOpacity().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(lineOpacity(propertyValue));
+ assertEquals(layer.getLineOpacity().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineOpacityAsExpression() {
+ Timber.i("line-opacity-expression");
+ assertNotNull(layer);
+ assertNull(layer.getLineOpacity().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(lineOpacity(expression));
+ assertEquals(layer.getLineOpacity().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineColorTransition() {
+ Timber.i("line-colorTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineColorTransition(options);
+ assertEquals(layer.getLineColorTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineColorAsConstant() {
+ Timber.i("line-color");
+ assertNotNull(layer);
+ assertNull(layer.getLineColor().getValue());
+
+ // Set and Get
+ String propertyValue = "rgba(255,128,0,0.7)";
+ layer.setProperties(lineColor(propertyValue));
+ assertEquals(layer.getLineColor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineColorAsExpression() {
+ Timber.i("line-color-expression");
+ assertNotNull(layer);
+ assertNull(layer.getLineColor().getExpression());
+
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(lineColor(expression));
+ assertEquals(layer.getLineColor().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineColorAsIntConstant() {
+ Timber.i("line-color");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineColor(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.getLineColorAsInt(), Color.argb(127, 255, 127, 0));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineTranslateTransition() {
+ Timber.i("line-translateTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineTranslateTransition(options);
+ assertEquals(layer.getLineTranslateTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineTranslateAsConstant() {
+ Timber.i("line-translate");
+ assertNotNull(layer);
+ assertNull(layer.getLineTranslate().getValue());
+
+ // Set and Get
+ Float[] propertyValue = new Float[] {0f, 0f};
+ layer.setProperties(lineTranslate(propertyValue));
+ assertEquals(layer.getLineTranslate().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineTranslateAnchorAsConstant() {
+ Timber.i("line-translate-anchor");
+ assertNotNull(layer);
+ assertNull(layer.getLineTranslateAnchor().getValue());
+
+ // Set and Get
+ String propertyValue = LINE_TRANSLATE_ANCHOR_MAP;
+ layer.setProperties(lineTranslateAnchor(propertyValue));
+ assertEquals(layer.getLineTranslateAnchor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineWidthTransition() {
+ Timber.i("line-widthTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineWidthTransition(options);
+ assertEquals(layer.getLineWidthTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineWidthAsConstant() {
+ Timber.i("line-width");
+ assertNotNull(layer);
+ assertNull(layer.getLineWidth().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(lineWidth(propertyValue));
+ assertEquals(layer.getLineWidth().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineWidthAsExpression() {
+ Timber.i("line-width-expression");
+ assertNotNull(layer);
+ assertNull(layer.getLineWidth().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(lineWidth(expression));
+ assertEquals(layer.getLineWidth().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineGapWidthTransition() {
+ Timber.i("line-gap-widthTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineGapWidthTransition(options);
+ assertEquals(layer.getLineGapWidthTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineGapWidthAsConstant() {
+ Timber.i("line-gap-width");
+ assertNotNull(layer);
+ assertNull(layer.getLineGapWidth().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(lineGapWidth(propertyValue));
+ assertEquals(layer.getLineGapWidth().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineGapWidthAsExpression() {
+ Timber.i("line-gap-width-expression");
+ assertNotNull(layer);
+ assertNull(layer.getLineGapWidth().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(lineGapWidth(expression));
+ assertEquals(layer.getLineGapWidth().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineOffsetTransition() {
+ Timber.i("line-offsetTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineOffsetTransition(options);
+ assertEquals(layer.getLineOffsetTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineOffsetAsConstant() {
+ Timber.i("line-offset");
+ assertNotNull(layer);
+ assertNull(layer.getLineOffset().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(lineOffset(propertyValue));
+ assertEquals(layer.getLineOffset().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineBlurTransition() {
+ Timber.i("line-blurTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineBlurTransition(options);
+ assertEquals(layer.getLineBlurTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineBlurAsConstant() {
+ Timber.i("line-blur");
+ assertNotNull(layer);
+ assertNull(layer.getLineBlur().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(lineBlur(propertyValue));
+ assertEquals(layer.getLineBlur().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineBlurAsExpression() {
+ Timber.i("line-blur-expression");
+ assertNotNull(layer);
+ assertNull(layer.getLineBlur().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(lineBlur(expression));
+ assertEquals(layer.getLineBlur().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineDasharrayTransition() {
+ Timber.i("line-dasharrayTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineDasharrayTransition(options);
+ assertEquals(layer.getLineDasharrayTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLineDasharrayAsConstant() {
+ Timber.i("line-dasharray");
+ assertNotNull(layer);
+ assertNull(layer.getLineDasharray().getValue());
+
+ // Set and Get
+ Float[] propertyValue = new Float[] {};
+ layer.setProperties(lineDasharray(propertyValue));
+ assertEquals(layer.getLineDasharray().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLinePatternTransition() {
+ Timber.i("line-patternTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLinePatternTransition(options);
+ assertEquals(layer.getLinePatternTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLinePatternAsConstant() {
+ Timber.i("line-pattern");
+ assertNotNull(layer);
+ assertNull(layer.getLinePattern().getValue());
+
+ // Set and Get
+ String propertyValue = "pedestrian-polygon";
+ layer.setProperties(linePattern(propertyValue));
+ assertEquals(layer.getLinePattern().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testLinePatternAsExpression() {
+ Timber.i("line-pattern-expression");
+ assertNotNull(layer);
+ assertNull(layer.getLinePattern().getExpression());
+
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(linePattern(expression));
+ assertEquals(layer.getLinePattern().getExpression(), expression);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java
new file mode 100644
index 0000000000..aa50b1fe52
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java
@@ -0,0 +1,240 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
+
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.maps.BaseLayerTest;
+import org.junit.Before;
+import timber.log.Timber;
+
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.RasterLayer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
+
+/**
+ * Basic smoke tests for RasterLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class RasterLayerTest extends BaseLayerTest {
+
+ private RasterLayer layer;
+
+ @Before
+ @UiThreadTest
+ public void beforeTest(){
+ super.before();
+ layer = new RasterLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ setupLayer(layer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSourceId() {
+ Timber.i("SourceId");
+ assertNotNull(layer);
+ assertEquals(layer.getSourceId(), "composite");
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSetVisibility() {
+ Timber.i("Visibility");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testRasterOpacityTransition() {
+ Timber.i("raster-opacityTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterOpacityTransition(options);
+ assertEquals(layer.getRasterOpacityTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testRasterOpacityAsConstant() {
+ Timber.i("raster-opacity");
+ assertNotNull(layer);
+ assertNull(layer.getRasterOpacity().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(rasterOpacity(propertyValue));
+ assertEquals(layer.getRasterOpacity().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testRasterHueRotateTransition() {
+ Timber.i("raster-hue-rotateTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterHueRotateTransition(options);
+ assertEquals(layer.getRasterHueRotateTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testRasterHueRotateAsConstant() {
+ Timber.i("raster-hue-rotate");
+ assertNotNull(layer);
+ assertNull(layer.getRasterHueRotate().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(rasterHueRotate(propertyValue));
+ assertEquals(layer.getRasterHueRotate().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testRasterBrightnessMinTransition() {
+ Timber.i("raster-brightness-minTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterBrightnessMinTransition(options);
+ assertEquals(layer.getRasterBrightnessMinTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testRasterBrightnessMinAsConstant() {
+ Timber.i("raster-brightness-min");
+ assertNotNull(layer);
+ assertNull(layer.getRasterBrightnessMin().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(rasterBrightnessMin(propertyValue));
+ assertEquals(layer.getRasterBrightnessMin().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testRasterBrightnessMaxTransition() {
+ Timber.i("raster-brightness-maxTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterBrightnessMaxTransition(options);
+ assertEquals(layer.getRasterBrightnessMaxTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testRasterBrightnessMaxAsConstant() {
+ Timber.i("raster-brightness-max");
+ assertNotNull(layer);
+ assertNull(layer.getRasterBrightnessMax().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(rasterBrightnessMax(propertyValue));
+ assertEquals(layer.getRasterBrightnessMax().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testRasterSaturationTransition() {
+ Timber.i("raster-saturationTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterSaturationTransition(options);
+ assertEquals(layer.getRasterSaturationTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testRasterSaturationAsConstant() {
+ Timber.i("raster-saturation");
+ assertNotNull(layer);
+ assertNull(layer.getRasterSaturation().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(rasterSaturation(propertyValue));
+ assertEquals(layer.getRasterSaturation().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testRasterContrastTransition() {
+ Timber.i("raster-contrastTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterContrastTransition(options);
+ assertEquals(layer.getRasterContrastTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testRasterContrastAsConstant() {
+ Timber.i("raster-contrast");
+ assertNotNull(layer);
+ assertNull(layer.getRasterContrast().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(rasterContrast(propertyValue));
+ assertEquals(layer.getRasterContrast().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testRasterResamplingAsConstant() {
+ Timber.i("raster-resampling");
+ assertNotNull(layer);
+ assertNull(layer.getRasterResampling().getValue());
+
+ // Set and Get
+ String propertyValue = RASTER_RESAMPLING_LINEAR;
+ layer.setProperties(rasterResampling(propertyValue));
+ assertEquals(layer.getRasterResampling().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testRasterFadeDurationAsConstant() {
+ Timber.i("raster-fade-duration");
+ assertNotNull(layer);
+ assertNull(layer.getRasterFadeDuration().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(rasterFadeDuration(propertyValue));
+ assertEquals(layer.getRasterFadeDuration().getValue(), propertyValue);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java
new file mode 100644
index 0000000000..2d1fbf5fc4
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTests.java
@@ -0,0 +1,370 @@
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.graphics.PointF;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+import com.mapbox.mapboxsdk.style.layers.CannotAddLayerException;
+import com.mapbox.mapboxsdk.style.layers.CircleLayer;
+import com.mapbox.mapboxsdk.style.layers.FillLayer;
+import com.mapbox.mapboxsdk.style.layers.Layer;
+import com.mapbox.mapboxsdk.style.layers.LineLayer;
+import com.mapbox.mapboxsdk.style.layers.Property;
+import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
+import com.mapbox.mapboxsdk.style.sources.CannotAddSourceException;
+import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
+import com.mapbox.mapboxsdk.style.sources.RasterSource;
+import com.mapbox.mapboxsdk.style.sources.Source;
+import com.mapbox.mapboxsdk.style.sources.VectorSource;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
+import junit.framework.Assert;
+import org.hamcrest.Matcher;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import timber.log.Timber;
+
+import java.util.List;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Basic smoke tests for Layer and Source
+ */
+@RunWith(AndroidJUnit4.class)
+public class RuntimeStyleTests extends EspressoTest {
+
+ @Test
+ public void testListLayers() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new BaseViewAction() {
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ List<Layer> layers = mapboxMap.getStyle().getLayers();
+ assertNotNull(layers);
+ assertTrue(layers.size() > 0);
+ for (Layer layer : layers) {
+ assertNotNull(layer);
+ }
+ }
+
+ });
+ }
+
+ @Test
+ public void testGetAddRemoveLayer() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new AddRemoveLayerAction());
+ }
+
+ @Test
+ public void testAddLayerAbove() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new BaseViewAction() {
+ @Override
+ public void perform(UiController uiController, View view) {
+ List<Layer> layers = mapboxMap.getStyle().getLayers();
+ Source source = mapboxMap.getStyle().getSources().get(0);
+
+ // Test inserting with invalid above-id
+ try {
+ mapboxMap.getStyle().addLayerAbove(
+ new CircleLayer("invalid-id-layer-test", source.getId()), "no-such-layer-here-man"
+ );
+ fail("Should have thrown exception");
+ } catch (CannotAddLayerException ex) {
+ // Yeah
+ assertNotNull(ex.getMessage());
+ }
+
+ // Insert as last
+ CircleLayer last = new CircleLayer("this is the last one", source.getId());
+ mapboxMap.getStyle().addLayerAbove(last, layers.get(layers.size() - 1).getId());
+ layers = mapboxMap.getStyle().getLayers();
+ assertEquals(last.getId(), layers.get(layers.size() - 1).getId());
+
+ // Insert
+ CircleLayer second = new CircleLayer("this is the second one", source.getId());
+ mapboxMap.getStyle().addLayerAbove(second, layers.get(0).getId());
+ layers = mapboxMap.getStyle().getLayers();
+ assertEquals(second.getId(), layers.get(1).getId());
+ }
+ });
+ }
+
+ @Test
+ public void testRemoveLayerAt() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new BaseViewAction() {
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ // Remove by index
+ Layer firstLayer = mapboxMap.getStyle().getLayers().get(0);
+ boolean removed = mapboxMap.getStyle().removeLayerAt(0);
+ assertTrue(removed);
+ assertNotNull(firstLayer);
+
+ // Test remove by index bounds checks
+ Timber.i("Remove layer at index > size");
+ assertFalse(mapboxMap.getStyle().removeLayerAt(Integer.MAX_VALUE));
+ }
+ });
+ }
+
+ public void testAddLayerAt() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new BaseViewAction() {
+ @Override
+ public void perform(UiController uiController, View view) {
+ List<Layer> layers = mapboxMap.getStyle().getLayers();
+ Source source = mapboxMap.getStyle().getSources().get(0);
+
+ // Test inserting out of range
+ try {
+ mapboxMap.getStyle().addLayerAt(new CircleLayer("invalid-id-layer-test", source.getId()), layers.size());
+ fail("Should have thrown exception");
+ } catch (CannotAddLayerException ex) {
+ // Yeah
+ assertNotNull(ex.getMessage());
+ }
+
+ // Insert at current last position
+ CircleLayer last = new CircleLayer("this is the last one", source.getId());
+ mapboxMap.getStyle().addLayerAt(last, layers.size() - 1);
+ layers = mapboxMap.getStyle().getLayers();
+ assertEquals(last.getId(), layers.get(layers.size() - 2).getId());
+
+ // Insert at start
+ CircleLayer second = new CircleLayer("this is the first one", source.getId());
+ mapboxMap.getStyle().addLayerAt(second, 0);
+ layers = mapboxMap.getStyle().getLayers();
+ assertEquals(second.getId(), layers.get(0).getId());
+ }
+ });
+ }
+
+
+ @Test
+ public void testListSources() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new BaseViewAction() {
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ List<Source> sources = mapboxMap.getStyle().getSources();
+ assertNotNull(sources);
+ assertTrue(sources.size() > 0);
+ for (Source source : sources) {
+ assertNotNull(source);
+ }
+ }
+
+ });
+ }
+
+ @Test
+ public void testAddRemoveSource() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ mapboxMap.getStyle().addSource(new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"));
+ mapboxMap.getStyle().removeSource("my-source");
+
+ // Add initial source
+ mapboxMap.getStyle().addSource(new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"));
+
+ // Remove
+ boolean removeOk = mapboxMap.getStyle().removeSource("my-source");
+ assertTrue(removeOk);
+ assertNull(mapboxMap.getStyle().getLayer("my-source"));
+
+ // Add
+ Source source = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
+ mapboxMap.getStyle().addSource(source);
+
+ // Remove, preserving the reference
+ mapboxMap.getStyle().removeSource(source);
+
+ // Re-add the reference...
+ mapboxMap.getStyle().addSource(source);
+
+ // Ensure it's there
+ Assert.assertNotNull(mapboxMap.getStyle().getSource(source.getId()));
+
+ // Test adding a duplicate source
+ try {
+ Source source2 = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
+ mapboxMap.getStyle().addSource(source2);
+ fail("Should not have been allowed to add a source with a duplicate id");
+ } catch (CannotAddSourceException cannotAddSourceException) {
+ // OK
+ }
+ });
+
+ }
+
+ @Test
+ public void testVectorSourceUrlGetter() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ VectorSource source = new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
+ mapboxMap.getStyle().addSource(source);
+ assertEquals("mapbox://mapbox.mapbox-terrain-v2", source.getUri());
+ });
+ }
+
+ @Test
+ public void testRasterSourceUrlGetter() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ RasterSource source = new RasterSource("my-source", "mapbox://mapbox.mapbox-terrain-v2");
+ mapboxMap.getStyle().addSource(source);
+ assertEquals("mapbox://mapbox.mapbox-terrain-v2", source.getUri());
+ });
+ }
+
+ @Test
+ public void testGeoJsonSourceUrlGetter() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ GeoJsonSource source = new GeoJsonSource("my-source");
+ mapboxMap.getStyle().addSource(source);
+ assertNull(source.getUri());
+ source.setUri("http://mapbox.com/my-file.json");
+ assertEquals("http://mapbox.com/my-file.json", source.getUri());
+ });
+ }
+
+ @Test
+ public void testRemoveSourceInUse() {
+ validateTestSetup();
+
+ onView(withId(R.id.mapView)).perform(new BaseViewAction() {
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ mapboxMap.getStyle().addSource(new VectorSource("my-source", "mapbox://mapbox.mapbox-terrain-v2"));
+ mapboxMap.getStyle().addLayer(new LineLayer("my-layer", "my-source"));
+ mapboxMap.getStyle().removeSource("my-source");
+ assertNotNull(mapboxMap.getStyle().getSource("my-source"));
+ }
+
+ });
+ }
+
+ @Test
+ public void testRemoveNonExistingSource() {
+ invoke(mapboxMap, (uiController, mapboxMap) -> mapboxMap.getStyle().removeSource("source"));
+ }
+
+ @Test
+ public void testRemoveNonExistingLayer() {
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertFalse(mapboxMap.getStyle().removeLayer("layer"));
+ assertFalse(mapboxMap.getStyle().removeLayerAt(mapboxMap.getStyle().getLayers().size() + 1));
+ assertFalse(mapboxMap.getStyle().removeLayerAt(-1));
+ });
+ }
+
+ @Test
+ public void testRemoveExistingLayer() {
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ Layer firstLayer = mapboxMap.getStyle().getLayers().get(0);
+ assertTrue(mapboxMap.getStyle().removeLayer(firstLayer));
+
+ firstLayer = mapboxMap.getStyle().getLayers().get(0);
+ assertTrue(mapboxMap.getStyle().removeLayer(firstLayer.getId()));
+
+ assertTrue(mapboxMap.getStyle().removeLayerAt(0));
+ });
+ }
+
+ /**
+ * https://github.com/mapbox/mapbox-gl-native/issues/7973
+ */
+ @Test
+ public void testQueryRenderedFeaturesInputHandling() {
+ validateTestSetup();
+ onView(withId(R.id.mapView)).perform(new BaseViewAction() {
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ String[] layerIds = new String[600];
+ for (int i = 0; i < layerIds.length; i++) {
+ layerIds[i] = "layer-" + i;
+ }
+ mapboxMap.queryRenderedFeatures(new PointF(100, 100), layerIds);
+ }
+
+ });
+ }
+
+ private class AddRemoveLayerAction extends BaseViewAction {
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ // Get initial
+ assertNotNull(mapboxMap.getStyle().getLayer("building"));
+
+ // Remove
+ boolean removed = mapboxMap.getStyle().removeLayer("building");
+ assertTrue(removed);
+ assertNull(mapboxMap.getStyle().getLayer("building"));
+
+ // Add
+ FillLayer layer = new FillLayer("building", "composite");
+ layer.setSourceLayer("building");
+ mapboxMap.getStyle().addLayer(layer);
+ assertNotNull(mapboxMap.getStyle().getLayer("building"));
+
+ // Assure the reference still works
+ layer.setProperties(PropertyFactory.visibility(Property.VISIBLE));
+
+ // Remove, preserving the reference
+ mapboxMap.getStyle().removeLayer(layer);
+
+ // Property setters should still work
+ layer.setProperties(PropertyFactory.fillColor(Color.RED));
+
+ // Re-add the reference...
+ mapboxMap.getStyle().addLayer(layer);
+
+ // Ensure it's there
+ Assert.assertNotNull(mapboxMap.getStyle().getLayer(layer.getId()));
+
+ // Test adding a duplicate layer
+ try {
+ mapboxMap.getStyle().addLayer(new FillLayer("building", "composite"));
+ fail("Should not have been allowed to add a layer with a duplicate id");
+ } catch (CannotAddLayerException cannotAddLayerException) {
+ // OK
+ }
+ }
+ }
+
+ public abstract class BaseViewAction implements ViewAction {
+
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTimingTests.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTimingTests.java
new file mode 100644
index 0000000000..4dd01d06cb
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RuntimeStyleTimingTests.java
@@ -0,0 +1,27 @@
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.testapp.activity.BaseTest;
+import com.mapbox.mapboxsdk.testapp.activity.style.RuntimeStyleTimingTestActivity;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Basic smoke tests for adding Layer and Source as early as possible (in onCreate)
+ */
+@RunWith(AndroidJUnit4.class)
+public class RuntimeStyleTimingTests extends BaseTest {
+
+ @Override
+ protected Class getActivityClass() {
+ return RuntimeStyleTimingTestActivity.class;
+ }
+
+ @Test
+ public void testGetAddRemoveLayer() {
+ validateTestSetup();
+ // We're good if it didn't crash
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/StyleLoaderTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/StyleLoaderTest.java
new file mode 100644
index 0000000000..495b209831
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/StyleLoaderTest.java
@@ -0,0 +1,59 @@
+package com.mapbox.mapboxsdk.testapp.style;
+
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.Style;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.EspressoTest;
+import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests around style loading
+ */
+public class StyleLoaderTest extends EspressoTest {
+
+ @Test
+ public void testSetGetStyleJsonString() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ try {
+ String expected = ResourceUtils.readRawResource(rule.getActivity(), R.raw.local_style);
+ mapboxMap.setStyle(new Style.Builder().fromJson(expected));
+ String actual = mapboxMap.getStyle().getJson();
+ assertEquals("Style json should match", expected, actual);
+ } catch (IOException exception) {
+ exception.printStackTrace();
+ }
+ });
+ }
+
+ @Test
+ public void testDefaultStyleLoadWithActivityLifecycleChange() {
+ validateTestSetup();
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ try {
+ String expected = ResourceUtils.readRawResource(rule.getActivity(), R.raw.local_style);
+ mapboxMap.setStyle(new Style.Builder().fromJson(expected));
+
+ // fake activity stop/start
+ MapView mapView = (MapView) rule.getActivity().findViewById(R.id.mapView);
+ mapView.onPause();
+ mapView.onStop();
+
+ mapView.onStart();
+ mapView.onResume();
+
+ String actual = mapboxMap.getStyle().getJson();
+ assertEquals("Style URL should be empty", "", mapboxMap.getStyle().getUri());
+ assertEquals("Style json should match", expected, actual);
+ } catch (IOException exception) {
+ exception.printStackTrace();
+ }
+ });
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
new file mode 100644
index 0000000000..c65e37019b
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java
@@ -0,0 +1,1313 @@
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
+
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.maps.BaseLayerTest;
+import org.junit.Before;
+import timber.log.Timber;
+
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
+import com.mapbox.mapboxsdk.style.types.Formatted;
+import com.mapbox.mapboxsdk.style.types.FormattedSection;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
+
+/**
+ * Basic smoke tests for SymbolLayer
+ */
+@RunWith(AndroidJUnit4.class)
+public class SymbolLayerTest extends BaseLayerTest {
+
+ private SymbolLayer layer;
+
+ @Before
+ @UiThreadTest
+ public void beforeTest(){
+ super.before();
+ layer = new SymbolLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ setupLayer(layer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSourceId() {
+ Timber.i("SourceId");
+ assertNotNull(layer);
+ assertEquals(layer.getSourceId(), "composite");
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSetVisibility() {
+ Timber.i("Visibility");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSourceLayer() {
+ Timber.i("SourceLayer");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFilter() {
+ Timber.i("Filter");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getFilter(), null);
+
+ // Set
+ Expression filter = eq(get("undefined"), literal(1.0));
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
+
+ // Set constant
+ filter = literal(true);
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
+ }
+
+
+
+ @Test
+ @UiThreadTest
+ public void testSymbolPlacementAsConstant() {
+ Timber.i("symbol-placement");
+ assertNotNull(layer);
+ assertNull(layer.getSymbolPlacement().getValue());
+
+ // Set and Get
+ String propertyValue = SYMBOL_PLACEMENT_POINT;
+ layer.setProperties(symbolPlacement(propertyValue));
+ assertEquals(layer.getSymbolPlacement().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSymbolSpacingAsConstant() {
+ Timber.i("symbol-spacing");
+ assertNotNull(layer);
+ assertNull(layer.getSymbolSpacing().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(symbolSpacing(propertyValue));
+ assertEquals(layer.getSymbolSpacing().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSymbolAvoidEdgesAsConstant() {
+ Timber.i("symbol-avoid-edges");
+ assertNotNull(layer);
+ assertNull(layer.getSymbolAvoidEdges().getValue());
+
+ // Set and Get
+ Boolean propertyValue = true;
+ layer.setProperties(symbolAvoidEdges(propertyValue));
+ assertEquals(layer.getSymbolAvoidEdges().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSymbolSortKeyAsConstant() {
+ Timber.i("symbol-sort-key");
+ assertNotNull(layer);
+ assertNull(layer.getSymbolSortKey().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(symbolSortKey(propertyValue));
+ assertEquals(layer.getSymbolSortKey().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSymbolSortKeyAsExpression() {
+ Timber.i("symbol-sort-key-expression");
+ assertNotNull(layer);
+ assertNull(layer.getSymbolSortKey().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(symbolSortKey(expression));
+ assertEquals(layer.getSymbolSortKey().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testSymbolZOrderAsConstant() {
+ Timber.i("symbol-z-order");
+ assertNotNull(layer);
+ assertNull(layer.getSymbolZOrder().getValue());
+
+ // Set and Get
+ String propertyValue = SYMBOL_Z_ORDER_AUTO;
+ layer.setProperties(symbolZOrder(propertyValue));
+ assertEquals(layer.getSymbolZOrder().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconAllowOverlapAsConstant() {
+ Timber.i("icon-allow-overlap");
+ assertNotNull(layer);
+ assertNull(layer.getIconAllowOverlap().getValue());
+
+ // Set and Get
+ Boolean propertyValue = true;
+ layer.setProperties(iconAllowOverlap(propertyValue));
+ assertEquals(layer.getIconAllowOverlap().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconIgnorePlacementAsConstant() {
+ Timber.i("icon-ignore-placement");
+ assertNotNull(layer);
+ assertNull(layer.getIconIgnorePlacement().getValue());
+
+ // Set and Get
+ Boolean propertyValue = true;
+ layer.setProperties(iconIgnorePlacement(propertyValue));
+ assertEquals(layer.getIconIgnorePlacement().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconOptionalAsConstant() {
+ Timber.i("icon-optional");
+ assertNotNull(layer);
+ assertNull(layer.getIconOptional().getValue());
+
+ // Set and Get
+ Boolean propertyValue = true;
+ layer.setProperties(iconOptional(propertyValue));
+ assertEquals(layer.getIconOptional().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconRotationAlignmentAsConstant() {
+ Timber.i("icon-rotation-alignment");
+ assertNotNull(layer);
+ assertNull(layer.getIconRotationAlignment().getValue());
+
+ // Set and Get
+ String propertyValue = ICON_ROTATION_ALIGNMENT_MAP;
+ layer.setProperties(iconRotationAlignment(propertyValue));
+ assertEquals(layer.getIconRotationAlignment().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconSizeAsConstant() {
+ Timber.i("icon-size");
+ assertNotNull(layer);
+ assertNull(layer.getIconSize().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(iconSize(propertyValue));
+ assertEquals(layer.getIconSize().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconSizeAsExpression() {
+ Timber.i("icon-size-expression");
+ assertNotNull(layer);
+ assertNull(layer.getIconSize().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(iconSize(expression));
+ assertEquals(layer.getIconSize().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconTextFitAsConstant() {
+ Timber.i("icon-text-fit");
+ assertNotNull(layer);
+ assertNull(layer.getIconTextFit().getValue());
+
+ // Set and Get
+ String propertyValue = ICON_TEXT_FIT_NONE;
+ layer.setProperties(iconTextFit(propertyValue));
+ assertEquals(layer.getIconTextFit().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconTextFitPaddingAsConstant() {
+ Timber.i("icon-text-fit-padding");
+ assertNotNull(layer);
+ assertNull(layer.getIconTextFitPadding().getValue());
+
+ // Set and Get
+ Float[] propertyValue = new Float[] {0f, 0f, 0f, 0f};
+ layer.setProperties(iconTextFitPadding(propertyValue));
+ assertEquals(layer.getIconTextFitPadding().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconImageAsConstant() {
+ Timber.i("icon-image");
+ assertNotNull(layer);
+ assertNull(layer.getIconImage().getValue());
+
+ // Set and Get
+ String propertyValue = "undefined";
+ layer.setProperties(iconImage(propertyValue));
+ assertEquals(layer.getIconImage().getValue(), propertyValue);
+
+ layer.setProperties(iconImage("{token}"));
+ assertEquals(layer.getIconImage().getExpression(), Expression.toString(Expression.get("token")));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconImageAsExpression() {
+ Timber.i("icon-image-expression");
+ assertNotNull(layer);
+ assertNull(layer.getIconImage().getExpression());
+
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(iconImage(expression));
+ assertEquals(layer.getIconImage().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconRotateAsConstant() {
+ Timber.i("icon-rotate");
+ assertNotNull(layer);
+ assertNull(layer.getIconRotate().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(iconRotate(propertyValue));
+ assertEquals(layer.getIconRotate().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconRotateAsExpression() {
+ Timber.i("icon-rotate-expression");
+ assertNotNull(layer);
+ assertNull(layer.getIconRotate().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(iconRotate(expression));
+ assertEquals(layer.getIconRotate().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconPaddingAsConstant() {
+ Timber.i("icon-padding");
+ assertNotNull(layer);
+ assertNull(layer.getIconPadding().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(iconPadding(propertyValue));
+ assertEquals(layer.getIconPadding().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconKeepUprightAsConstant() {
+ Timber.i("icon-keep-upright");
+ assertNotNull(layer);
+ assertNull(layer.getIconKeepUpright().getValue());
+
+ // Set and Get
+ Boolean propertyValue = true;
+ layer.setProperties(iconKeepUpright(propertyValue));
+ assertEquals(layer.getIconKeepUpright().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconOffsetAsConstant() {
+ Timber.i("icon-offset");
+ assertNotNull(layer);
+ assertNull(layer.getIconOffset().getValue());
+
+ // Set and Get
+ Float[] propertyValue = new Float[] {0f, 0f};
+ layer.setProperties(iconOffset(propertyValue));
+ assertEquals(layer.getIconOffset().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconAnchorAsConstant() {
+ Timber.i("icon-anchor");
+ assertNotNull(layer);
+ assertNull(layer.getIconAnchor().getValue());
+
+ // Set and Get
+ String propertyValue = ICON_ANCHOR_CENTER;
+ layer.setProperties(iconAnchor(propertyValue));
+ assertEquals(layer.getIconAnchor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconAnchorAsExpression() {
+ Timber.i("icon-anchor-expression");
+ assertNotNull(layer);
+ assertNull(layer.getIconAnchor().getExpression());
+
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(iconAnchor(expression));
+ assertEquals(layer.getIconAnchor().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconPitchAlignmentAsConstant() {
+ Timber.i("icon-pitch-alignment");
+ assertNotNull(layer);
+ assertNull(layer.getIconPitchAlignment().getValue());
+
+ // Set and Get
+ String propertyValue = ICON_PITCH_ALIGNMENT_MAP;
+ layer.setProperties(iconPitchAlignment(propertyValue));
+ assertEquals(layer.getIconPitchAlignment().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextPitchAlignmentAsConstant() {
+ Timber.i("text-pitch-alignment");
+ assertNotNull(layer);
+ assertNull(layer.getTextPitchAlignment().getValue());
+
+ // Set and Get
+ String propertyValue = TEXT_PITCH_ALIGNMENT_MAP;
+ layer.setProperties(textPitchAlignment(propertyValue));
+ assertEquals(layer.getTextPitchAlignment().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextRotationAlignmentAsConstant() {
+ Timber.i("text-rotation-alignment");
+ assertNotNull(layer);
+ assertNull(layer.getTextRotationAlignment().getValue());
+
+ // Set and Get
+ String propertyValue = TEXT_ROTATION_ALIGNMENT_MAP;
+ layer.setProperties(textRotationAlignment(propertyValue));
+ assertEquals(layer.getTextRotationAlignment().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextFieldAsConstant() {
+ Timber.i("text-field");
+ assertNotNull(layer);
+ assertNull(layer.getTextField().getValue());
+
+ // Set and Get
+ Formatted propertyValue = new Formatted(new FormattedSection("default"));
+ layer.setProperties(textField("default"));
+ assertEquals(layer.getTextField().getValue(), propertyValue);
+ layer.setProperties(textField(propertyValue));
+ assertEquals(layer.getTextField().getValue(), propertyValue);
+
+ layer.setProperties(textField("{token}"));
+ assertEquals(layer.getTextField().getExpression(), format(Expression.formatEntry(Expression.toString(Expression.get("token")))));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextFieldAsExpression() {
+ Timber.i("text-field-expression");
+ assertNotNull(layer);
+ assertNull(layer.getTextField().getExpression());
+
+ // Set and Get
+ Expression expression = format(Expression.formatEntry(Expression.get("undefined"), FormatOption.formatFontScale(2.0), FormatOption.formatTextFont(new String[]{"Open Sans Regular", "Arial Unicode MS Regular"})));
+ layer.setProperties(textField(expression));
+ assertEquals(layer.getTextField().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextFontAsConstant() {
+ Timber.i("text-font");
+ assertNotNull(layer);
+ assertNull(layer.getTextFont().getValue());
+
+ // Set and Get
+ String[] propertyValue = new String[]{"Open Sans Regular", "Arial Unicode MS Regular"};
+ layer.setProperties(textFont(propertyValue));
+ assertEquals(layer.getTextFont().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextSizeAsConstant() {
+ Timber.i("text-size");
+ assertNotNull(layer);
+ assertNull(layer.getTextSize().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(textSize(propertyValue));
+ assertEquals(layer.getTextSize().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextSizeAsExpression() {
+ Timber.i("text-size-expression");
+ assertNotNull(layer);
+ assertNull(layer.getTextSize().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(textSize(expression));
+ assertEquals(layer.getTextSize().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextMaxWidthAsConstant() {
+ Timber.i("text-max-width");
+ assertNotNull(layer);
+ assertNull(layer.getTextMaxWidth().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(textMaxWidth(propertyValue));
+ assertEquals(layer.getTextMaxWidth().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextMaxWidthAsExpression() {
+ Timber.i("text-max-width-expression");
+ assertNotNull(layer);
+ assertNull(layer.getTextMaxWidth().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(textMaxWidth(expression));
+ assertEquals(layer.getTextMaxWidth().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextLineHeightAsConstant() {
+ Timber.i("text-line-height");
+ assertNotNull(layer);
+ assertNull(layer.getTextLineHeight().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(textLineHeight(propertyValue));
+ assertEquals(layer.getTextLineHeight().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextLetterSpacingAsConstant() {
+ Timber.i("text-letter-spacing");
+ assertNotNull(layer);
+ assertNull(layer.getTextLetterSpacing().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(textLetterSpacing(propertyValue));
+ assertEquals(layer.getTextLetterSpacing().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextLetterSpacingAsExpression() {
+ Timber.i("text-letter-spacing-expression");
+ assertNotNull(layer);
+ assertNull(layer.getTextLetterSpacing().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(textLetterSpacing(expression));
+ assertEquals(layer.getTextLetterSpacing().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextJustifyAsConstant() {
+ Timber.i("text-justify");
+ assertNotNull(layer);
+ assertNull(layer.getTextJustify().getValue());
+
+ // Set and Get
+ String propertyValue = TEXT_JUSTIFY_AUTO;
+ layer.setProperties(textJustify(propertyValue));
+ assertEquals(layer.getTextJustify().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextJustifyAsExpression() {
+ Timber.i("text-justify-expression");
+ assertNotNull(layer);
+ assertNull(layer.getTextJustify().getExpression());
+
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(textJustify(expression));
+ assertEquals(layer.getTextJustify().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextRadialOffsetAsConstant() {
+ Timber.i("text-radial-offset");
+ assertNotNull(layer);
+ assertNull(layer.getTextRadialOffset().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(textRadialOffset(propertyValue));
+ assertEquals(layer.getTextRadialOffset().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextVariableAnchorAsConstant() {
+ Timber.i("text-variable-anchor");
+ assertNotNull(layer);
+ assertNull(layer.getTextVariableAnchor().getValue());
+
+ // Set and Get
+ String[] propertyValue = new String[0];
+ layer.setProperties(textVariableAnchor(propertyValue));
+ assertEquals(layer.getTextVariableAnchor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextAnchorAsConstant() {
+ Timber.i("text-anchor");
+ assertNotNull(layer);
+ assertNull(layer.getTextAnchor().getValue());
+
+ // Set and Get
+ String propertyValue = TEXT_ANCHOR_CENTER;
+ layer.setProperties(textAnchor(propertyValue));
+ assertEquals(layer.getTextAnchor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextAnchorAsExpression() {
+ Timber.i("text-anchor-expression");
+ assertNotNull(layer);
+ assertNull(layer.getTextAnchor().getExpression());
+
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(textAnchor(expression));
+ assertEquals(layer.getTextAnchor().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextMaxAngleAsConstant() {
+ Timber.i("text-max-angle");
+ assertNotNull(layer);
+ assertNull(layer.getTextMaxAngle().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(textMaxAngle(propertyValue));
+ assertEquals(layer.getTextMaxAngle().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextWritingModeAsConstant() {
+ Timber.i("text-writing-mode");
+ assertNotNull(layer);
+ assertNull(layer.getTextWritingMode().getValue());
+
+ // Set and Get
+ String[] propertyValue = new String[0];
+ layer.setProperties(textWritingMode(propertyValue));
+ assertEquals(layer.getTextWritingMode().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextRotateAsConstant() {
+ Timber.i("text-rotate");
+ assertNotNull(layer);
+ assertNull(layer.getTextRotate().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(textRotate(propertyValue));
+ assertEquals(layer.getTextRotate().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextRotateAsExpression() {
+ Timber.i("text-rotate-expression");
+ assertNotNull(layer);
+ assertNull(layer.getTextRotate().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(textRotate(expression));
+ assertEquals(layer.getTextRotate().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextPaddingAsConstant() {
+ Timber.i("text-padding");
+ assertNotNull(layer);
+ assertNull(layer.getTextPadding().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(textPadding(propertyValue));
+ assertEquals(layer.getTextPadding().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextKeepUprightAsConstant() {
+ Timber.i("text-keep-upright");
+ assertNotNull(layer);
+ assertNull(layer.getTextKeepUpright().getValue());
+
+ // Set and Get
+ Boolean propertyValue = true;
+ layer.setProperties(textKeepUpright(propertyValue));
+ assertEquals(layer.getTextKeepUpright().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextTransformAsConstant() {
+ Timber.i("text-transform");
+ assertNotNull(layer);
+ assertNull(layer.getTextTransform().getValue());
+
+ // Set and Get
+ String propertyValue = TEXT_TRANSFORM_NONE;
+ layer.setProperties(textTransform(propertyValue));
+ assertEquals(layer.getTextTransform().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextTransformAsExpression() {
+ Timber.i("text-transform-expression");
+ assertNotNull(layer);
+ assertNull(layer.getTextTransform().getExpression());
+
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(textTransform(expression));
+ assertEquals(layer.getTextTransform().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextOffsetAsConstant() {
+ Timber.i("text-offset");
+ assertNotNull(layer);
+ assertNull(layer.getTextOffset().getValue());
+
+ // Set and Get
+ Float[] propertyValue = new Float[] {0f, 0f};
+ layer.setProperties(textOffset(propertyValue));
+ assertEquals(layer.getTextOffset().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextAllowOverlapAsConstant() {
+ Timber.i("text-allow-overlap");
+ assertNotNull(layer);
+ assertNull(layer.getTextAllowOverlap().getValue());
+
+ // Set and Get
+ Boolean propertyValue = true;
+ layer.setProperties(textAllowOverlap(propertyValue));
+ assertEquals(layer.getTextAllowOverlap().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextIgnorePlacementAsConstant() {
+ Timber.i("text-ignore-placement");
+ assertNotNull(layer);
+ assertNull(layer.getTextIgnorePlacement().getValue());
+
+ // Set and Get
+ Boolean propertyValue = true;
+ layer.setProperties(textIgnorePlacement(propertyValue));
+ assertEquals(layer.getTextIgnorePlacement().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextOptionalAsConstant() {
+ Timber.i("text-optional");
+ assertNotNull(layer);
+ assertNull(layer.getTextOptional().getValue());
+
+ // Set and Get
+ Boolean propertyValue = true;
+ layer.setProperties(textOptional(propertyValue));
+ assertEquals(layer.getTextOptional().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconOpacityTransition() {
+ Timber.i("icon-opacityTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconOpacityTransition(options);
+ assertEquals(layer.getIconOpacityTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconOpacityAsConstant() {
+ Timber.i("icon-opacity");
+ assertNotNull(layer);
+ assertNull(layer.getIconOpacity().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(iconOpacity(propertyValue));
+ assertEquals(layer.getIconOpacity().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconOpacityAsExpression() {
+ Timber.i("icon-opacity-expression");
+ assertNotNull(layer);
+ assertNull(layer.getIconOpacity().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(iconOpacity(expression));
+ assertEquals(layer.getIconOpacity().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconColorTransition() {
+ Timber.i("icon-colorTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconColorTransition(options);
+ assertEquals(layer.getIconColorTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconColorAsConstant() {
+ Timber.i("icon-color");
+ assertNotNull(layer);
+ assertNull(layer.getIconColor().getValue());
+
+ // Set and Get
+ String propertyValue = "rgba(255,128,0,0.7)";
+ layer.setProperties(iconColor(propertyValue));
+ assertEquals(layer.getIconColor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconColorAsExpression() {
+ Timber.i("icon-color-expression");
+ assertNotNull(layer);
+ assertNull(layer.getIconColor().getExpression());
+
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(iconColor(expression));
+ assertEquals(layer.getIconColor().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconColorAsIntConstant() {
+ Timber.i("icon-color");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconColor(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.getIconColorAsInt(), Color.argb(127, 255, 127, 0));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconHaloColorTransition() {
+ Timber.i("icon-halo-colorTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconHaloColorTransition(options);
+ assertEquals(layer.getIconHaloColorTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconHaloColorAsConstant() {
+ Timber.i("icon-halo-color");
+ assertNotNull(layer);
+ assertNull(layer.getIconHaloColor().getValue());
+
+ // Set and Get
+ String propertyValue = "rgba(255,128,0,0.7)";
+ layer.setProperties(iconHaloColor(propertyValue));
+ assertEquals(layer.getIconHaloColor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconHaloColorAsExpression() {
+ Timber.i("icon-halo-color-expression");
+ assertNotNull(layer);
+ assertNull(layer.getIconHaloColor().getExpression());
+
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(iconHaloColor(expression));
+ assertEquals(layer.getIconHaloColor().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconHaloColorAsIntConstant() {
+ Timber.i("icon-halo-color");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconHaloColor(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.getIconHaloColorAsInt(), Color.argb(127, 255, 127, 0));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconHaloWidthTransition() {
+ Timber.i("icon-halo-widthTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconHaloWidthTransition(options);
+ assertEquals(layer.getIconHaloWidthTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconHaloWidthAsConstant() {
+ Timber.i("icon-halo-width");
+ assertNotNull(layer);
+ assertNull(layer.getIconHaloWidth().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(iconHaloWidth(propertyValue));
+ assertEquals(layer.getIconHaloWidth().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconHaloWidthAsExpression() {
+ Timber.i("icon-halo-width-expression");
+ assertNotNull(layer);
+ assertNull(layer.getIconHaloWidth().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(iconHaloWidth(expression));
+ assertEquals(layer.getIconHaloWidth().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconHaloBlurTransition() {
+ Timber.i("icon-halo-blurTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconHaloBlurTransition(options);
+ assertEquals(layer.getIconHaloBlurTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconHaloBlurAsConstant() {
+ Timber.i("icon-halo-blur");
+ assertNotNull(layer);
+ assertNull(layer.getIconHaloBlur().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(iconHaloBlur(propertyValue));
+ assertEquals(layer.getIconHaloBlur().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconHaloBlurAsExpression() {
+ Timber.i("icon-halo-blur-expression");
+ assertNotNull(layer);
+ assertNull(layer.getIconHaloBlur().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(iconHaloBlur(expression));
+ assertEquals(layer.getIconHaloBlur().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconTranslateTransition() {
+ Timber.i("icon-translateTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconTranslateTransition(options);
+ assertEquals(layer.getIconTranslateTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconTranslateAsConstant() {
+ Timber.i("icon-translate");
+ assertNotNull(layer);
+ assertNull(layer.getIconTranslate().getValue());
+
+ // Set and Get
+ Float[] propertyValue = new Float[] {0f, 0f};
+ layer.setProperties(iconTranslate(propertyValue));
+ assertEquals(layer.getIconTranslate().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testIconTranslateAnchorAsConstant() {
+ Timber.i("icon-translate-anchor");
+ assertNotNull(layer);
+ assertNull(layer.getIconTranslateAnchor().getValue());
+
+ // Set and Get
+ String propertyValue = ICON_TRANSLATE_ANCHOR_MAP;
+ layer.setProperties(iconTranslateAnchor(propertyValue));
+ assertEquals(layer.getIconTranslateAnchor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextOpacityTransition() {
+ Timber.i("text-opacityTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextOpacityTransition(options);
+ assertEquals(layer.getTextOpacityTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextOpacityAsConstant() {
+ Timber.i("text-opacity");
+ assertNotNull(layer);
+ assertNull(layer.getTextOpacity().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(textOpacity(propertyValue));
+ assertEquals(layer.getTextOpacity().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextOpacityAsExpression() {
+ Timber.i("text-opacity-expression");
+ assertNotNull(layer);
+ assertNull(layer.getTextOpacity().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(textOpacity(expression));
+ assertEquals(layer.getTextOpacity().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextColorTransition() {
+ Timber.i("text-colorTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextColorTransition(options);
+ assertEquals(layer.getTextColorTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextColorAsConstant() {
+ Timber.i("text-color");
+ assertNotNull(layer);
+ assertNull(layer.getTextColor().getValue());
+
+ // Set and Get
+ String propertyValue = "rgba(255,128,0,0.7)";
+ layer.setProperties(textColor(propertyValue));
+ assertEquals(layer.getTextColor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextColorAsExpression() {
+ Timber.i("text-color-expression");
+ assertNotNull(layer);
+ assertNull(layer.getTextColor().getExpression());
+
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(textColor(expression));
+ assertEquals(layer.getTextColor().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextColorAsIntConstant() {
+ Timber.i("text-color");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textColor(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.getTextColorAsInt(), Color.argb(127, 255, 127, 0));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextHaloColorTransition() {
+ Timber.i("text-halo-colorTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextHaloColorTransition(options);
+ assertEquals(layer.getTextHaloColorTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextHaloColorAsConstant() {
+ Timber.i("text-halo-color");
+ assertNotNull(layer);
+ assertNull(layer.getTextHaloColor().getValue());
+
+ // Set and Get
+ String propertyValue = "rgba(255,128,0,0.7)";
+ layer.setProperties(textHaloColor(propertyValue));
+ assertEquals(layer.getTextHaloColor().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextHaloColorAsExpression() {
+ Timber.i("text-halo-color-expression");
+ assertNotNull(layer);
+ assertNull(layer.getTextHaloColor().getExpression());
+
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(textHaloColor(expression));
+ assertEquals(layer.getTextHaloColor().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextHaloColorAsIntConstant() {
+ Timber.i("text-halo-color");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textHaloColor(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.getTextHaloColorAsInt(), Color.argb(127, 255, 127, 0));
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextHaloWidthTransition() {
+ Timber.i("text-halo-widthTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextHaloWidthTransition(options);
+ assertEquals(layer.getTextHaloWidthTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextHaloWidthAsConstant() {
+ Timber.i("text-halo-width");
+ assertNotNull(layer);
+ assertNull(layer.getTextHaloWidth().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(textHaloWidth(propertyValue));
+ assertEquals(layer.getTextHaloWidth().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextHaloWidthAsExpression() {
+ Timber.i("text-halo-width-expression");
+ assertNotNull(layer);
+ assertNull(layer.getTextHaloWidth().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(textHaloWidth(expression));
+ assertEquals(layer.getTextHaloWidth().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextHaloBlurTransition() {
+ Timber.i("text-halo-blurTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextHaloBlurTransition(options);
+ assertEquals(layer.getTextHaloBlurTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextHaloBlurAsConstant() {
+ Timber.i("text-halo-blur");
+ assertNotNull(layer);
+ assertNull(layer.getTextHaloBlur().getValue());
+
+ // Set and Get
+ Float propertyValue = 0.3f;
+ layer.setProperties(textHaloBlur(propertyValue));
+ assertEquals(layer.getTextHaloBlur().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextHaloBlurAsExpression() {
+ Timber.i("text-halo-blur-expression");
+ assertNotNull(layer);
+ assertNull(layer.getTextHaloBlur().getExpression());
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(textHaloBlur(expression));
+ assertEquals(layer.getTextHaloBlur().getExpression(), expression);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextTranslateTransition() {
+ Timber.i("text-translateTransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextTranslateTransition(options);
+ assertEquals(layer.getTextTranslateTransition(), options);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextTranslateAsConstant() {
+ Timber.i("text-translate");
+ assertNotNull(layer);
+ assertNull(layer.getTextTranslate().getValue());
+
+ // Set and Get
+ Float[] propertyValue = new Float[] {0f, 0f};
+ layer.setProperties(textTranslate(propertyValue));
+ assertEquals(layer.getTextTranslate().getValue(), propertyValue);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testTextTranslateAnchorAsConstant() {
+ Timber.i("text-translate-anchor");
+ assertNotNull(layer);
+ assertNull(layer.getTextTranslateAnchor().getValue());
+
+ // Set and Get
+ String propertyValue = TEXT_TRANSLATE_ANCHOR_MAP;
+ layer.setProperties(textTranslateAnchor(propertyValue));
+ assertEquals(layer.getTextTranslateAnchor().getValue(), propertyValue);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs
new file mode 100644
index 0000000000..1104cbed9d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs
@@ -0,0 +1,195 @@
+<%
+ const type = locals.type;
+ const properties = locals.properties;
+-%>
+// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
+
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.maps.BaseLayerTest;
+import org.junit.Before;
+import timber.log.Timber;
+
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.<%- camelize(type) %>Layer;
+<% if (type === 'symbol') { -%>
+import com.mapbox.mapboxsdk.style.types.Formatted;
+import com.mapbox.mapboxsdk.style.types.FormattedSection;
+<% } -%>
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
+import static org.junit.Assert.*;
+import static com.mapbox.mapboxsdk.style.layers.Property.*;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
+
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
+
+/**
+ * Basic smoke tests for <%- camelize(type) %>Layer
+ */
+@RunWith(AndroidJUnit4.class)
+public class <%- camelize(type) %>LayerTest extends BaseLayerTest {
+
+ private <%- camelize(type) %>Layer layer;
+
+ @Before
+ @UiThreadTest
+ public void beforeTest(){
+ super.before();
+<% if (type === 'background') { -%>
+ layer = new <%- camelize(type) %>Layer("my-layer");
+<% } else { -%>
+ layer = new <%- camelize(type) %>Layer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+<% } -%>
+ setupLayer(layer);
+ }
+<% if (type !== 'background') { -%>
+
+ @Test
+ @UiThreadTest
+ public void testSourceId() {
+ Timber.i("SourceId");
+ assertNotNull(layer);
+ assertEquals(layer.getSourceId(), "composite");
+ }
+<% } -%>
+
+ @Test
+ @UiThreadTest
+ public void testSetVisibility() {
+ Timber.i("Visibility");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getVisibility().getValue(), VISIBLE);
+
+ // Set
+ layer.setProperties(visibility(NONE));
+ assertEquals(layer.getVisibility().getValue(), NONE);
+ }
+<% if (!(type === 'background' || type === 'raster' || type === 'hillshade')) { -%>
+
+ @Test
+ @UiThreadTest
+ public void testSourceLayer() {
+ Timber.i("SourceLayer");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testFilter() {
+ Timber.i("Filter");
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getFilter(), null);
+
+ // Set
+ Expression filter = eq(get("undefined"), literal(1.0));
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
+
+ // Set constant
+ filter = literal(true);
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
+ }
+
+
+<% } -%>
+<% for (const property of properties) { -%>
+<% if (property['property-type'] !== 'color-ramp') { -%>
+<% if (property.transition) { -%>
+
+ @Test
+ @UiThreadTest
+ public void test<%- camelize(property.name) %>Transition() {
+ Timber.i("<%- property.name %>TransitionOptions");
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.set<%- camelize(property.name) %>Transition(options);
+ assertEquals(layer.get<%- camelize(property.name) %>Transition(), options);
+ }
+<% } -%>
+
+ @Test
+ @UiThreadTest
+ public void test<%- camelize(property.name) %>AsConstant() {
+ Timber.i("<%- property.name %>");
+ assertNotNull(layer);
+ assertNull(layer.get<%- camelize(property.name) %>().getValue());
+
+ // Set and Get
+ <%- propertyType(property) %> propertyValue = <%- defaultValueJava(property) %>;
+<% if (property.type === 'formatted') { -%>
+ layer.setProperties(<%- camelizeWithLeadingLowercase(property.name) %>("default"));
+ assertEquals(layer.get<%- camelize(property.name) %>().getValue(), propertyValue);
+<% } -%>
+ layer.setProperties(<%- camelizeWithLeadingLowercase(property.name) %>(propertyValue));
+ assertEquals(layer.get<%- camelize(property.name) %>().getValue(), propertyValue);
+<% if (property.tokens) { -%>
+
+ layer.setProperties(<%- camelizeWithLeadingLowercase(property.name) %>("{token}"));
+<% if (property.type === 'formatted') { -%>
+ assertEquals(layer.get<%- camelize(property.name) %>().getExpression(), <%- defaultExpressionJava(property) %>(Expression.formatEntry(Expression.toString(Expression.get("token")))));
+<% } else {-%>
+ assertEquals(layer.get<%- camelize(property.name) %>().getExpression(), Expression.toString(Expression.get("token")));
+<% } -%>
+<% } -%>
+ }
+<% if (property['property-type'] === 'data-driven' || property['property-type'] === 'cross-faded-data-driven') { -%>
+<% if (!(property.name.endsWith("-font")||property.name.endsWith("-offset"))) { -%>
+
+ @Test
+ @UiThreadTest
+ public void test<%- camelize(property.name) %>AsExpression() {
+ Timber.i("<%- property.name %>-expression");
+ assertNotNull(layer);
+ assertNull(layer.get<%- camelize(property.name) %>().getExpression());
+
+ // Set and Get
+<% if (property.type === 'formatted') { -%>
+ Expression expression = <%- defaultExpressionJava(property) %>(Expression.formatEntry(Expression.get("undefined"), FormatOption.formatFontScale(2.0), FormatOption.formatTextFont(new String[]{"Open Sans Regular", "Arial Unicode MS Regular"})));
+<% } else { -%>
+ Expression expression = <%- defaultExpressionJava(property) %>(Expression.get("undefined"));
+<% } -%>
+ layer.setProperties(<%- camelizeWithLeadingLowercase(property.name) %>(expression));
+ assertEquals(layer.get<%- camelize(property.name) %>().getExpression(), expression);
+ }
+<% } -%>
+<% } -%>
+<% if (property.type == 'color') { -%>
+
+ @Test
+ @UiThreadTest
+ public void test<%- camelize(property.name) %>AsIntConstant() {
+ Timber.i("<%- property.name %>");
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(<%- camelizeWithLeadingLowercase(property.name) %>(Color.argb(127, 255, 127, 0)));
+ assertEquals(layer.get<%- camelize(property.name) %>AsInt(), Color.argb(127, 255, 127, 0));
+ }
+<% } -%>
+<% } -%>
+<% } -%>
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs
new file mode 100644
index 0000000000..9bc77b202b
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs
@@ -0,0 +1,132 @@
+<%
+ const properties = locals.properties;
+-%>
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.ViewAction;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.style.light.Light;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer;
+import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
+import com.mapbox.mapboxsdk.style.light.Position;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.BaseTest;
+import com.mapbox.mapboxsdk.testapp.activity.style.FillExtrusionStyleTestActivity;
+
+import timber.log.Timber;
+
+import org.hamcrest.Matcher;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
+import static com.mapbox.mapboxsdk.style.layers.Property.ANCHOR_MAP;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionBase;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionHeight;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionOpacity;
+
+import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+
+@RunWith(AndroidJUnit4.class)
+public class LightTest extends BaseTest {
+
+ private Light light;
+<% for (const property of properties) { -%>
+<% if (property.transition) { -%>
+
+ @Test
+ public void test<%- camelize(property.name) %>Transition() {
+ validateTestSetup();
+ setupLight();
+ Timber.i("<%- property.name %>TransitionOptions");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ light.set<%- camelize(property.name) %>Transition(options);
+ assertEquals("Transition options should match", options, light.get<%- camelize(property.name) %>Transition());
+ });
+ }
+<% } -%>
+<% if (property.name == "position") { -%>
+
+ @Test
+ public void test<%- camelize(property.name) %>() {
+ validateTestSetup();
+ setupLight();
+ Timber.i("<%- property.name %>");
+ invoke(mapboxMap,(uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ Position position = new Position(1, 2, 3);
+ light.set<%- camelize(property.name) %>(position);
+ assertEquals("Position should match", position, light.get<%- camelize(property.name) %>());
+ });
+ }
+<% } else { -%>
+
+ @Test
+ public void test<%- camelize(property.name) %>() {
+ validateTestSetup();
+ setupLight();
+ Timber.i("<%- property.name %>");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ light.set<%- camelize(property.name) %>(<%- defaultValueJava(property) %>);
+<% if (property.name == 'color') { -%>
+ assertEquals("<%- camelize(property.name) %> should match", <%- defaultValueJava(property) %>, light.get<%- camelize(property.name) %>());
+<% } else { -%>
+ assertEquals("<%- camelize(property.name) %> should match", <%- defaultValueJava(property) %>, light.get<%- camelize(property.name) %>());
+<% } -%>
+ });
+ }
+<% } -%>
+<% } -%>
+
+ private void setupLight() {
+ onView(withId(R.id.mapView)).perform(new ViewAction() {
+ @Override
+ public Matcher<View> getConstraints() {
+ return isDisplayed();
+ }
+
+ @Override
+ public String getDescription() {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ light = mapboxMap.getStyle().getLight();
+ FillExtrusionLayer fillExtrusionLayer = new FillExtrusionLayer("3d-buildings", "composite");
+ fillExtrusionLayer.setSourceLayer("building");
+ fillExtrusionLayer.setFilter(eq(Expression.get("extrude"), "true"));
+ fillExtrusionLayer.setMinZoom(15);
+ fillExtrusionLayer.setProperties(
+ fillExtrusionColor(Color.LTGRAY),
+ fillExtrusionHeight(Expression.get("height")),
+ fillExtrusionBase(Expression.get("min_height")),
+ fillExtrusionOpacity(0.6f)
+ );
+ mapboxMap.getStyle().addLayer(fillExtrusionLayer);
+ }
+ });
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return FillExtrusionStyleTestActivity.class;
+ }
+} \ No newline at end of file