From ec63e1bf6d77b828be21686a88d5df721d19cbe5 Mon Sep 17 00:00:00 2001 From: Kevin Li Date: Wed, 22 Dec 2021 17:31:12 +0800 Subject: [PATCH] Parse event data without json (#1001) * Parse event data without json * Add missed docs; fix the failed test cases * Add tests for nullable properties * Add map.nonNullStringWithUpperCase function --- .../observable/ObservableExtension.kt | 278 +++++++-- .../observable/model/DataSourceType.kt | 13 +- .../observable/model/MapLoadErrorType.kt | 13 +- .../extension/observable/model/RenderMode.kt | 10 +- .../observable/model/RequestPriority.kt | 7 +- .../extension/observable/model/RequestType.kt | 19 +- .../observable/model/ResponseErrorReason.kt | 17 +- .../observable/model/ResponseSourceType.kt | 11 +- .../observable/model/SourceDataType.kt | 7 +- .../observable/model/StyleDataType.kt | 9 +- .../java/com/mapbox/maps/OfflineTest.kt | 44 +- .../com/mapbox/maps/NativeObserverTest.kt | 54 +- .../extension/observable/MapboxMapTest.kt | 102 ---- .../extension/observable/ObservableTest.kt | 570 ++++++++++++++++++ 14 files changed, 944 insertions(+), 210 deletions(-) delete mode 100644 sdk/src/test/java/com/mapbox/maps/extension/observable/MapboxMapTest.kt create mode 100644 sdk/src/test/java/com/mapbox/maps/extension/observable/ObservableTest.kt diff --git a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/ObservableExtension.kt b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/ObservableExtension.kt index dafe5d5229..451d7ca32f 100644 --- a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/ObservableExtension.kt +++ b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/ObservableExtension.kt @@ -1,16 +1,14 @@ package com.mapbox.maps.extension.observable -import com.google.gson.Gson +import com.mapbox.bindgen.Value import com.mapbox.maps.Event import com.mapbox.maps.MapEvents import com.mapbox.maps.ObservableInterface import com.mapbox.maps.Observer import com.mapbox.maps.extension.observable.eventdata.* import com.mapbox.maps.extension.observable.eventdata.ResourceEventData - -private val gson by lazy { - Gson() -} +import com.mapbox.maps.extension.observable.model.* +import java.util.* /** * Subscribes an Observer for of event type "resource-request". @@ -301,124 +299,336 @@ fun ObservableInterface.unsubscribeSourceRemoved(observer: Observer) = * Get the parsed event data for resource-request event. * @return a parsed ResourceEventData object. */ +@Suppress("UNCHECKED_CAST") fun Event.getResourceEventData(): ResourceEventData { - val json = data.toJson() - return gson.fromJson(json, ResourceEventData::class.java) + val map = data.contents as Map + val requestMap = map.nonNullMap(REQUEST) + val responseMap = map.nullableMap(RESPONSE) + val errorMap = responseMap?.nullableMap(ERROR) + return ResourceEventData( + begin = map.nonNullLong(BEGIN), + end = map.nullableLong(END), + dataSource = DataSourceType.valueOf(map.validEnumValue(DATA_SOURCE)), + request = Request( + loadingMethod = requestMap.nonNullList(LOADING_METHOD), + url = requestMap.nonNullString(URL), + kind = RequestType.valueOf(requestMap.validEnumValue(KIND)), + priority = RequestPriority.valueOf(requestMap.validEnumValue(PRIORITY)) + ), + response = if (responseMap == null) null else Response( + eTag = responseMap.nullableString(E_TAG), + mustRevalidate = responseMap.nonNullBoolean(MUST_REVALIDATE), + noContent = responseMap.nonNullBoolean(NO_CONTENT), + modified = responseMap.nullableString(MODIFIED), + source = ResponseSourceType.valueOf(responseMap.validEnumValue(SOURCE)), + notModified = responseMap.nonNullBoolean(NOT_MODIFIED), + expires = responseMap.nullableString(EXPIRES), + size = responseMap.nonNullInt(SIZE), + error = if (errorMap == null) null else Error( + reason = ResponseErrorReason.valueOf(errorMap.validEnumValue(REASON)), + message = errorMap.nonNullString(MESSAGE) + ) + ), + cancelled = map.nonNullBoolean(CANCELLED) + ) } /** * Get the parsed event data for map loaded event. * @return a parsed MapLoadedEventData object. */ +@Suppress("UNCHECKED_CAST") fun Event.getMapLoadedEventData(): MapLoadedEventData { - val json = data.toJson() - return gson.fromJson(json, MapLoadedEventData::class.java) + val map = data.contents as Map + return MapLoadedEventData( + begin = map.nonNullLong(BEGIN), + end = map.nullableLong(END) + ) } /** * Get the parsed event data for map loading error event. * @return a parsed MapLoadingErrorEventData object. */ +@Suppress("UNCHECKED_CAST") fun Event.getMapLoadingErrorEventData(): MapLoadingErrorEventData { - val json = data.toJson() - return gson.fromJson(json, MapLoadingErrorEventData::class.java) + val map = data.contents as Map + val tileIDMap = map.nullableMap(TILE_ID) + return MapLoadingErrorEventData( + begin = map.nonNullLong(BEGIN), + end = map.nullableLong(END), + type = MapLoadErrorType.valueOf(map.validEnumValue(TYPE)), + message = map.nonNullString(MESSAGE), + sourceId = map.nullableString(SOURCE_ID), + tileId = if (tileIDMap == null) null else TileID( + zoom = tileIDMap.nonNullLong(Z), + x = tileIDMap.nonNullLong(X), + y = tileIDMap.nonNullLong(Y) + ) + ) } /** * Get the parsed event data for map idle event. * @return a parsed MapIdleEventData object. */ +@Suppress("UNCHECKED_CAST") fun Event.getMapIdleEventData(): MapIdleEventData { - val json = data.toJson() - return gson.fromJson(json, MapIdleEventData::class.java) + val map = data.contents as Map + return MapIdleEventData( + begin = map.nonNullLong(BEGIN), + end = map.nullableLong(END) + ) } /** * Get the parsed event data for style data loaded event. * @return a parsed StyleDataLoadedEventData object. */ +@Suppress("UNCHECKED_CAST") fun Event.getStyleDataLoadedEventData(): StyleDataLoadedEventData { - val json = data.toJson() - return gson.fromJson(json, StyleDataLoadedEventData::class.java) + val map = data.contents as Map + return StyleDataLoadedEventData( + begin = map.nonNullLong(BEGIN), + end = map.nullableLong(END), + type = StyleDataType.valueOf(map.validEnumValue(TYPE)) + ) } /** * Get the parsed event data for style loaded event. * @return a parsed StyleLoadedEventData object. */ +@Suppress("UNCHECKED_CAST") fun Event.getStyleLoadedEventData(): StyleLoadedEventData { - val json = data.toJson() - return gson.fromJson(json, StyleLoadedEventData::class.java) + val map = data.contents as Map + return StyleLoadedEventData( + begin = map.nonNullLong(BEGIN), + end = map.nullableLong(END), + ) } /** * Get the parsed event data for source data loaded event. * @return a parsed SourceDataLoadedEventData object. */ +@Suppress("UNCHECKED_CAST") fun Event.getSourceDataLoadedEventData(): SourceDataLoadedEventData { - val json = data.toJson() - return gson.fromJson(json, SourceDataLoadedEventData::class.java) + val map = data.contents as Map + val tileIDMap = map.nullableMap(TILE_ID) + + return SourceDataLoadedEventData( + begin = map.nonNullLong(BEGIN), + end = map.nullableLong(END), + id = map.nonNullString(ID), + type = SourceDataType.valueOf(map.validEnumValue(TYPE)), + loaded = map.nullableBoolean(LOADED), + tileID = if (tileIDMap == null) null else TileID( + zoom = tileIDMap.nonNullLong(Z), + x = tileIDMap.nonNullLong(X), + y = tileIDMap.nonNullLong(Y) + ) + ) } /** * Get the parsed event data for style missing event. * @return a parsed StyleImageMissingEventData. */ +@Suppress("UNCHECKED_CAST") fun Event.getStyleImageMissingEventData(): StyleImageMissingEventData { - val json = data.toJson() - return gson.fromJson(json, StyleImageMissingEventData::class.java) + val map = data.contents as Map + return StyleImageMissingEventData( + begin = map.nonNullLong(BEGIN), + end = map.nullableLong(END), + id = map.nonNullString(ID) + ) } /** * Get the parsed event data for style image unused event. * @return a parsed StyleImageUnusedEventData. */ +@Suppress("UNCHECKED_CAST") fun Event.getStyleImageUnusedEventData(): StyleImageUnusedEventData { - val json = data.toJson() - return gson.fromJson(json, StyleImageUnusedEventData::class.java) + val map = data.contents as Map + return StyleImageUnusedEventData( + begin = map.nonNullLong(BEGIN), + end = map.nullableLong(END), + id = map.nonNullString(ID) + ) } /** * Get the parsed event data for source added event. * @return a parsed IDStringEventData. */ +@Suppress("UNCHECKED_CAST") fun Event.getSourceAddedEventData(): SourceAddedEventData { - val json = data.toJson() - return gson.fromJson(json, SourceAddedEventData::class.java) + val map = data.contents as Map + return SourceAddedEventData( + begin = map.nonNullLong(BEGIN), + end = map.nullableLong(END), + id = map.nonNullString(ID) + ) } /** * Get the parsed event data for source removed event. * @return a parsed SourceRemovedEventData. */ +@Suppress("UNCHECKED_CAST") fun Event.getSourceRemovedEventData(): SourceRemovedEventData { - val json = data.toJson() - return gson.fromJson(json, SourceRemovedEventData::class.java) + val map = data.contents as Map + return SourceRemovedEventData( + begin = map.nonNullLong(BEGIN), + end = map.nullableLong(END), + id = map.nonNullString(ID) + ) } /** * Get the parsed event data for render frame started event. * @return a parsed RenderFrameStartedEventData. */ +@Suppress("UNCHECKED_CAST") fun Event.getRenderFrameStartedEventData(): RenderFrameStartedEventData { - val json = data.toJson() - return gson.fromJson(json, RenderFrameStartedEventData::class.java) + val map = data.contents as Map + return RenderFrameStartedEventData( + begin = map.nonNullLong(BEGIN), + end = map.nullableLong(END) + ) } /** * Get the parsed event data for render frame finished event. * @return a parsed RenderFrameFinishedEventData. */ +@Suppress("UNCHECKED_CAST") fun Event.getRenderFrameFinishedEventData(): RenderFrameFinishedEventData { - val json = data.toJson() - return gson.fromJson(json, RenderFrameFinishedEventData::class.java) + val map = data.contents as Map + return RenderFrameFinishedEventData( + begin = map.nonNullLong(BEGIN), + end = map.nullableLong(END), + renderMode = RenderMode.valueOf(map.validEnumValue(RENDER_MODE)), + needsRepaint = map.nonNullBoolean(NEEDS_REPAINT), + placementChanged = map.nonNullBoolean(PLACEMENT_CHANGED) + ) } /** * Get the parsed event data for camera changed event. * @return a parsed CameraChangedEventData. */ +@Suppress("UNCHECKED_CAST") fun Event.getCameraChangedEventData(): CameraChangedEventData { - val json = data.toJson() - return gson.fromJson(json, CameraChangedEventData::class.java) -} \ No newline at end of file + val map = data.contents as Map + return CameraChangedEventData( + begin = map.nonNullLong(BEGIN), + end = map.nullableLong(END) + ) +} + +internal fun Map.nonNullLong(name: String): Long { + return this[name]!!.contents as Long +} + +internal fun Map.nullableLong(name: String): Long? { + return this[name]?.contents as Long? +} + +internal fun Map.nonNullString(name: String): String { + return this[name]!!.contents as String +} + +internal fun Map.validEnumValue(name: String): String { + return nonNullString(name).toUpperCase(Locale.US).replace(DASH, UNDERLINE) +} + +internal fun Map.nullableString(name: String): String? { + return this[name]?.contents as String? +} + +internal fun Map.nonNullInt(name: String): Int { + return (this[name]!!.contents as Long).toInt() +} + +internal fun Map.nullableInt(name: String): Int? { + return (this[name]?.contents as Int?)?.toInt() +} + +internal fun Map.nonNullBoolean(name: String): Boolean { + return this[name]!!.contents as Boolean +} + +internal fun Map.nullableBoolean(name: String): Boolean? { + return this[name]?.contents as Boolean? +} + +@Suppress("UNCHECKED_CAST") +internal fun Map.nonNullMap(name: String): Map { + return this[name]!!.contents as Map +} + +@Suppress("UNCHECKED_CAST") +internal fun Map.nullableMap(name: String): Map? { + return this[name]?.contents as Map? +} + +@Suppress("UNCHECKED_CAST") +internal fun Map.nonNullList(name: String): List { + return (this[name]!!.contents as List).map { it.toString() } +} + +private const val UNDERLINE = "_" +private const val DASH = "-" + +// Base type +private const val BEGIN = "begin" +private const val END = "end" + +// MapLoadingErrorEventData +private const val TYPE = "type" +private const val MESSAGE = "message" +private const val SOURCE_ID = "source-id" +private const val TILE_ID = "tile-id" + +// TileID +private const val X = "x" +private const val Y = "y" +private const val Z = "z" + +// ResourceEventData +private const val DATA_SOURCE = "data-source" +private const val REQUEST = "request" +private const val RESPONSE = "response" +private const val CANCELLED = "cancelled" + +// Request +private const val LOADING_METHOD = "loading-method" +private const val URL = "url" +private const val KIND = "kind" +private const val PRIORITY = "priority" + +// Response +private const val E_TAG = "etag" +private const val MUST_REVALIDATE = "must-revalidate" +private const val NO_CONTENT = "no-content" +private const val MODIFIED = "modified" +private const val SOURCE = "source" +private const val NOT_MODIFIED = "not-modified" +private const val EXPIRES = "expires" +private const val SIZE = "size" +private const val ERROR = "error" + +// Error +private const val REASON = "reason" + +// SourceDataLoadedEventData +private const val ID = "id" +private const val LOADED = "loaded" + +// RenderFrameFinishedEventData( +private const val RENDER_MODE = "render-mode" +private const val NEEDS_REPAINT = "needs-repaint" +private const val PLACEMENT_CHANGED = "placement-changed" \ No newline at end of file diff --git a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/DataSourceType.kt b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/DataSourceType.kt index 6aba2e6d64..03d6f99cb5 100644 --- a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/DataSourceType.kt +++ b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/DataSourceType.kt @@ -4,35 +4,36 @@ import com.google.gson.annotations.SerializedName /** * Describes data source of request for resource-request event. + * @param value String value of this enum */ -enum class DataSourceType { +enum class DataSourceType(val value: String) { /** * data source as resource-loader. */ @SerializedName("resource-loader") - RESOURCE_LOADER, + RESOURCE_LOADER("resource-loader"), /** * data source as network. */ @SerializedName("network") - NETWORK, + NETWORK("network"), /** * data source as database. */ @SerializedName("database") - DATABASE, + DATABASE("database"), /** * data source as asset. */ @SerializedName("asset") - ASSET, + ASSET("asset"), /** * data source as file-system. */ @SerializedName("file-system") - FILE_SYSTEM, + FILE_SYSTEM("file-system"), } \ No newline at end of file diff --git a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/MapLoadErrorType.kt b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/MapLoadErrorType.kt index f21141be44..f7a01d2d74 100644 --- a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/MapLoadErrorType.kt +++ b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/MapLoadErrorType.kt @@ -5,35 +5,36 @@ import com.google.gson.annotations.SerializedName /** * Describes an error type while loading the map. * Defines what resource could not be loaded. + * @param value String value of this enum */ -enum class MapLoadErrorType { +enum class MapLoadErrorType(val value: String) { /** * An error related to style. */ @SerializedName("style") - STYLE, + STYLE("style"), /** * An error related to sprite. */ @SerializedName("sprite") - SPRITE, + SPRITE("sprite"), /** * An error related to source. */ @SerializedName("source") - SOURCE, + SOURCE("source"), /** * An error related to tile. */ @SerializedName("tile") - TILE, + TILE("tile"), /** * An error related to glyphs. */ @SerializedName("glyphs") - GLYPHS + GLYPHS("glyphs") } \ No newline at end of file diff --git a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/RenderMode.kt b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/RenderMode.kt index a476cc9337..d48989ef42 100644 --- a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/RenderMode.kt +++ b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/RenderMode.kt @@ -2,17 +2,19 @@ package com.mapbox.maps.extension.observable.model import com.google.gson.annotations.SerializedName -/** Describes whether a map or frame has been fully rendered or not. */ -enum class RenderMode { +/** Describes whether a map or frame has been fully rendered or not. + * @param value String value of this enum + */ +enum class RenderMode(val value: String) { /** * The map is partially rendered. Partially rendered map means * that not all data needed to render the map has been arrived * from the network or being parsed. */ @SerializedName("partial") - PARTIAL, + PARTIAL("partial"), /** The map is fully rendered. */ @SerializedName("full") - FULL + FULL("full") } \ No newline at end of file diff --git a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/RequestPriority.kt b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/RequestPriority.kt index 88d694b658..9ebdbe6440 100644 --- a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/RequestPriority.kt +++ b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/RequestPriority.kt @@ -4,13 +4,14 @@ import com.google.gson.annotations.SerializedName /** * Describes priority for request object. + * @param value String value of this enum */ -enum class RequestPriority { +enum class RequestPriority(val value: String) { /** Regular priority. */ @SerializedName("regular") - REGULAR, + REGULAR("regular"), /** low priority. */ @SerializedName("low") - LOW + LOW("low") } \ No newline at end of file diff --git a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/RequestType.kt b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/RequestType.kt index 4bb3bd2b21..bf989e693b 100644 --- a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/RequestType.kt +++ b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/RequestType.kt @@ -4,53 +4,54 @@ import com.google.gson.annotations.SerializedName /** * Describes type for request object. + * @param value String value of this enum */ -enum class RequestType { +enum class RequestType(val value: String) { /** * Request type unknown. */ @SerializedName("unknown") - UNKNOWN, + UNKNOWN("unknown"), /** * Request type style. */ @SerializedName("style") - STYLE, + STYLE("style"), /** * Request type source. */ @SerializedName("source") - SOURCE, + SOURCE("source"), /** * Request type tile. */ @SerializedName("tile") - TILE, + TILE("tile"), /** * Request type glyphs. */ @SerializedName("glyphs") - GLYPHS, + GLYPHS("glyphs"), /** * Request type sprite-image. */ @SerializedName("sprite-image") - SPRITE_IMAGE, + SPRITE_IMAGE("sprite-image"), /** * Request type sprite-json. */ @SerializedName("sprite-json") - SPRITE_JSON, + SPRITE_JSON("sprite-json"), /** * Request type image. */ @SerializedName("image") - IMAGE, + IMAGE("image"), } \ No newline at end of file diff --git a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/ResponseErrorReason.kt b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/ResponseErrorReason.kt index 959449fe70..49984338de 100644 --- a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/ResponseErrorReason.kt +++ b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/ResponseErrorReason.kt @@ -4,47 +4,48 @@ import com.google.gson.annotations.SerializedName /** * Describes the reason of Error for response object. + * @param value String value of this enum */ -enum class ResponseErrorReason { +enum class ResponseErrorReason(val value: String) { /** * Error type success. */ @SerializedName("success") - SUCCESS, + SUCCESS("success"), /** * Error type not-found. */ @SerializedName("not-found") - NOT_FOUND, + NOT_FOUND("not-found"), /** * Error type server. */ @SerializedName("server") - SERVER, + SERVER("server"), /** * Error type connection. */ @SerializedName("connection") - CONNECTION, + CONNECTION("connection"), /** * Error type rate-limit. */ @SerializedName("rate-limit") - RATE_LIMIT, + RATE_LIMIT("rate-limit"), /** * Error type in-offline-mode. */ @SerializedName("in-offline-mode") - IN_OFFLINE_MODE, + IN_OFFLINE_MODE("in-offline-mode"), /** * Error type other. */ @SerializedName("other") - OTHER + OTHER("other") } \ No newline at end of file diff --git a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/ResponseSourceType.kt b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/ResponseSourceType.kt index 9f6ac80f4b..a6493fec2d 100644 --- a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/ResponseSourceType.kt +++ b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/ResponseSourceType.kt @@ -4,29 +4,30 @@ import com.google.gson.annotations.SerializedName /** * Describes source data type for response in resource-request event. + * @param value String value of this enum */ -enum class ResponseSourceType { +enum class ResponseSourceType(val value: String) { /** * source type as network. */ @SerializedName("network") - NETWORK, + NETWORK("network"), /** * source type as cache. */ @SerializedName("cache") - CACHE, + CACHE("cache"), /** * source type as tile-store. */ @SerializedName("tile-store") - TILE_STORE, + TILE_STORE("tile-store"), /** * source type as local-file. */ @SerializedName("local-file") - LOCAL_FILE, + LOCAL_FILE("local-file"), } \ No newline at end of file diff --git a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/SourceDataType.kt b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/SourceDataType.kt index 5ae976e1db..36de34d848 100644 --- a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/SourceDataType.kt +++ b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/SourceDataType.kt @@ -4,17 +4,18 @@ import com.google.gson.annotations.SerializedName /** * Defines what kind of source data has been loaded in a source-data-loaded event. + * @param value String value of this enum */ -enum class SourceDataType { +enum class SourceDataType(val value: String) { /** * The source data loaded event is associated with source metadata. */ @SerializedName("metadata") - METADATA, + METADATA("metadata"), /** * The source data loaded event is associated with source tile. */ @SerializedName("tile") - TILE + TILE("tile") } \ No newline at end of file diff --git a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/StyleDataType.kt b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/StyleDataType.kt index f894e8cc6c..5f498f2bf0 100644 --- a/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/StyleDataType.kt +++ b/sdk-base/src/main/java/com/mapbox/maps/extension/observable/model/StyleDataType.kt @@ -4,23 +4,24 @@ import com.google.gson.annotations.SerializedName /** * Defines what kind of style data has been loaded in a style-data-loaded event. + * @param value String value of this enum */ -enum class StyleDataType { +enum class StyleDataType(val value: String) { /** * The style data loaded event is associated with style. */ @SerializedName("style") - STYLE, + STYLE("style"), /** * The style data loaded event is associated with sprite. */ @SerializedName("sprite") - SPRITE, + SPRITE("sprite"), /** * The style data loaded event is associated with sources. */ @SerializedName("sources") - SOURCES + SOURCES("sources") } \ No newline at end of file diff --git a/sdk/src/androidTest/java/com/mapbox/maps/OfflineTest.kt b/sdk/src/androidTest/java/com/mapbox/maps/OfflineTest.kt index f3a12256af..6ad352391c 100644 --- a/sdk/src/androidTest/java/com/mapbox/maps/OfflineTest.kt +++ b/sdk/src/androidTest/java/com/mapbox/maps/OfflineTest.kt @@ -291,15 +291,19 @@ class OfflineTest { var mapLoadingErrorCount = 0 val observer = Observer { event -> Logger.e(TAG, "type ${event.type}, data ${event.data.toJson()}") - val data = event.getResourceEventData() - if (!data.cancelled && data.dataSource == DataSourceType.DATABASE && data.request.kind == RequestType.TILE) { - resourceRequests++ - } - if (event.type == MapEvents.MAP_LOADING_ERROR) { - mapLoadingErrorCount++ - } - if (event.type == MapEvents.MAP_LOADED || event.type == MapEvents.STYLE_LOADED) { - latch.countDown() + when (event.type) { + MapEvents.RESOURCE_REQUEST -> { + val data = event.getResourceEventData() + if (!data.cancelled && data.dataSource == DataSourceType.DATABASE && data.request.kind == RequestType.SOURCE) { + resourceRequests++ + } + } + MapEvents.MAP_LOADING_ERROR -> { + mapLoadingErrorCount++ + } + else -> { + latch.countDown() + } } } switchAirplaneMode() @@ -334,15 +338,19 @@ class OfflineTest { var mapLoadingErrorCount = 0 val observer = Observer { event -> Logger.e(TAG, "type ${event.type}, data ${event.data.toJson()}") - val data = event.getResourceEventData() - if (!data.cancelled && data.dataSource == DataSourceType.DATABASE && data.request.kind == RequestType.TILE) { - resourceRequests++ - } - if (event.type == MapEvents.MAP_LOADING_ERROR) { - mapLoadingErrorCount++ - } - if (event.type == MapEvents.MAP_LOADED || event.type == MapEvents.STYLE_LOADED) { - latch.countDown() + when (event.type) { + MapEvents.RESOURCE_REQUEST -> { + val data = event.getResourceEventData() + if (!data.cancelled && data.dataSource == DataSourceType.DATABASE && data.request.kind == RequestType.TILE) { + resourceRequests++ + } + } + MapEvents.MAP_LOADING_ERROR -> { + mapLoadingErrorCount++ + } + else -> { + latch.countDown() + } } } OfflineSwitch.getInstance().isMapboxStackConnected = false diff --git a/sdk/src/test/java/com/mapbox/maps/NativeObserverTest.kt b/sdk/src/test/java/com/mapbox/maps/NativeObserverTest.kt index 3ae619fc02..7921181d25 100644 --- a/sdk/src/test/java/com/mapbox/maps/NativeObserverTest.kt +++ b/sdk/src/test/java/com/mapbox/maps/NativeObserverTest.kt @@ -101,11 +101,24 @@ class NativeObserverTest { @Test fun addOnMapLoadErrorListener() { + val tileIDMap = hashMapOf( + "z" to Value(1), + "x" to Value(2), + "y" to Value(3) + ) + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "type" to Value("sprite"), + "message" to Value("error message"), + "source-id" to Value("source"), + "tile-id" to Value(tileIDMap) + ) val listener = mockk(relaxUnitFun = true) nativeObserver.addOnMapLoadErrorListener(listener) verify { observableInterface.subscribe(any(), listOf(MapEvents.MAP_LOADING_ERROR)) } assertTrue(nativeObserver.observedEvents.contains(MapEvents.MAP_LOADING_ERROR)) - notifyEvents(MapEvents.MAP_LOADING_ERROR) + notifyEvents(MapEvents.MAP_LOADING_ERROR, Value(map)) verify { listener.onMapLoadError(any()) } val listener2 = mockk(relaxUnitFun = true) @@ -117,7 +130,7 @@ class NativeObserverTest { listOf(MapEvents.MAP_LOADING_ERROR) ) } - notifyEvents(MapEvents.MAP_LOADING_ERROR) + notifyEvents(MapEvents.MAP_LOADING_ERROR, Value(map)) verify { listener2.onMapLoadError(any()) } } @@ -184,11 +197,18 @@ class NativeObserverTest { // Render frame events @Test fun addOnRenderFrameFinishedListener() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "needs-repaint" to Value(true), + "placement-changed" to Value(false), + "render-mode" to Value("full"), + ) val listener = mockk(relaxUnitFun = true) nativeObserver.addOnRenderFrameFinishedListener(listener) verify { observableInterface.subscribe(any(), listOf(MapEvents.RENDER_FRAME_FINISHED)) } assertTrue(nativeObserver.observedEvents.contains(MapEvents.RENDER_FRAME_FINISHED)) - notifyEvents(MapEvents.RENDER_FRAME_FINISHED) + notifyEvents(MapEvents.RENDER_FRAME_FINISHED, Value(map)) verify { listener.onRenderFrameFinished(any()) } val listener2 = mockk(relaxUnitFun = true) @@ -200,7 +220,7 @@ class NativeObserverTest { listOf(MapEvents.RENDER_FRAME_FINISHED) ) } - notifyEvents(MapEvents.RENDER_FRAME_FINISHED) + notifyEvents(MapEvents.RENDER_FRAME_FINISHED, Value(map)) verify { listener2.onRenderFrameFinished(any()) } } @@ -313,11 +333,24 @@ class NativeObserverTest { @Test fun addOnSourceDataLoadedListener() { + val tileIDMap = hashMapOf( + "z" to Value(1), + "x" to Value(2), + "y" to Value(3) + ) + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "id" to Value("id"), + "loaded" to Value(true), + "type" to Value("metadata"), + "tile-id" to Value(tileIDMap) + ) val listener = mockk(relaxUnitFun = true) nativeObserver.addOnSourceDataLoadedListener(listener) verify { observableInterface.subscribe(any(), listOf(MapEvents.SOURCE_DATA_LOADED)) } assertTrue(nativeObserver.observedEvents.contains(MapEvents.SOURCE_DATA_LOADED)) - notifyEvents(MapEvents.SOURCE_DATA_LOADED) + notifyEvents(MapEvents.SOURCE_DATA_LOADED, Value(map)) verify { listener.onSourceDataLoaded(any()) } val listener2 = mockk(relaxUnitFun = true) @@ -329,7 +362,7 @@ class NativeObserverTest { listOf(MapEvents.SOURCE_DATA_LOADED) ) } - notifyEvents(MapEvents.SOURCE_DATA_LOADED) + notifyEvents(MapEvents.SOURCE_DATA_LOADED, Value(map)) verify { listener2.onSourceDataLoaded(any()) } } @@ -524,11 +557,16 @@ class NativeObserverTest { @Test fun addOnStyleDataLoadedListener() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "type" to Value("sources") + ) val listener = mockk(relaxUnitFun = true) nativeObserver.addOnStyleDataLoadedListener(listener) verify { observableInterface.subscribe(any(), listOf(MapEvents.STYLE_DATA_LOADED)) } assertTrue(nativeObserver.observedEvents.contains(MapEvents.STYLE_DATA_LOADED)) - notifyEvents(MapEvents.STYLE_DATA_LOADED) + notifyEvents(MapEvents.STYLE_DATA_LOADED, Value(map)) verify { listener.onStyleDataLoaded(any()) } val listener2 = mockk(relaxUnitFun = true) @@ -540,7 +578,7 @@ class NativeObserverTest { listOf(MapEvents.STYLE_DATA_LOADED) ) } - notifyEvents(MapEvents.STYLE_DATA_LOADED) + notifyEvents(MapEvents.STYLE_DATA_LOADED, Value(map)) verify { listener2.onStyleDataLoaded(any()) } } diff --git a/sdk/src/test/java/com/mapbox/maps/extension/observable/MapboxMapTest.kt b/sdk/src/test/java/com/mapbox/maps/extension/observable/MapboxMapTest.kt deleted file mode 100644 index 3d09e84a18..0000000000 --- a/sdk/src/test/java/com/mapbox/maps/extension/observable/MapboxMapTest.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.mapbox.maps.extension.observable - -import com.mapbox.bindgen.Value -import com.mapbox.maps.Event -import com.mapbox.maps.ObservableInterface -import com.mapbox.maps.Observer -import com.mapbox.maps.extension.observable.model.* -import io.mockk.mockk -import io.mockk.verify -import org.junit.Assert.assertEquals -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner - -@RunWith(RobolectricTestRunner::class) -class MapboxMapTest { - - private val observableInterface: ObservableInterface = mockk(relaxed = true) - private val observer: Observer = mockk(relaxed = true) - - @Test - fun addResourceObserver() { - observableInterface.subscribeResourceRequest(observer) - verify { observableInterface.subscribe(observer, listOf("resource-request")) } - } - - @Test - fun removeResourceObserver() { - observableInterface.unsubscribeResourceRequest(observer) - verify { observableInterface.unsubscribe(observer, listOf("resource-request")) } - } - - @Test - fun getEventData() { - val request = Request(listOf("network"), "https://api.mapbox.com", RequestType.TILE, RequestPriority.REGULAR) - val response = Response( - eTag = "d8abd8d10bee6b45b4dbf5c05496587a", - mustRevalidate = false, - noContent = false, - modified = "Mon, 05 Oct 2020 14:23:52 GMT", - source = ResponseSourceType.NETWORK, - notModified = false, - expires = "Thu, 15 Oct 2020 14:32:23 GMT", - size = 181576, - error = Error(ResponseErrorReason.NOT_FOUND, "error message") - ) - val requestMap = hashMapOf( - Pair("loading-method", Value(listOf(Value("network")))), - Pair("url", Value("https://api.mapbox.com")), - Pair("kind", Value("tile")), - Pair("priority", Value("regular")) - ) - val responseMap = hashMapOf( - Pair("etag", Value("d8abd8d10bee6b45b4dbf5c05496587a")), - Pair("must-revalidate", Value(false)), - Pair("no-content", Value(false)), - Pair("modified", Value("Mon, 05 Oct 2020 14:23:52 GMT")), - Pair("source", Value("network")), - Pair("not-modified", Value(false)), - Pair("expires", Value("Thu, 15 Oct 2020 14:32:23 GMT")), - Pair("size", Value(181576)), - Pair( - "error", - Value( - hashMapOf( - Pair("reason", Value("not-found")), - Pair("message", Value("error message")) - ) - ) - ) - ) - val map = hashMapOf( - Pair("data-source", Value("network")), - Pair("request", Value(requestMap)), - Pair("response", Value(responseMap)) - ) - val event = Event("resource-request", Value.valueOf(map)) - - val eventData = event.getResourceEventData() - assertEquals(DataSourceType.NETWORK, eventData.dataSource) - assertEquals(false, eventData.cancelled) - assertEquals(request, eventData.request) - assertEquals(response, eventData.response) - - assertEquals(listOf("network"), request.loadingMethod) - assertEquals("https://api.mapbox.com", request.url) - assertEquals(RequestType.TILE, request.kind) - assertEquals(RequestPriority.REGULAR, request.priority) - - assertEquals("d8abd8d10bee6b45b4dbf5c05496587a", response.eTag) - assertEquals(false, response.mustRevalidate) - assertEquals(false, response.noContent) - assertEquals(ResponseSourceType.NETWORK, response.source) - assertEquals(false, response.notModified) - assertEquals("Thu, 15 Oct 2020 14:32:23 GMT", response.expires) - assertEquals(181576, response.size) - assertEquals(Error(ResponseErrorReason.NOT_FOUND, "error message"), response.error) - - assertEquals(ResponseErrorReason.NOT_FOUND, response.error!!.reason) - assertEquals("error message", response.error!!.message) - } -} \ No newline at end of file diff --git a/sdk/src/test/java/com/mapbox/maps/extension/observable/ObservableTest.kt b/sdk/src/test/java/com/mapbox/maps/extension/observable/ObservableTest.kt new file mode 100644 index 0000000000..5144eff13a --- /dev/null +++ b/sdk/src/test/java/com/mapbox/maps/extension/observable/ObservableTest.kt @@ -0,0 +1,570 @@ +package com.mapbox.maps.extension.observable + +import com.mapbox.bindgen.Value +import com.mapbox.maps.Event +import com.mapbox.maps.MapEvents +import com.mapbox.maps.ObservableInterface +import com.mapbox.maps.Observer +import com.mapbox.maps.extension.observable.model.* +import io.mockk.mockk +import io.mockk.verify +import org.junit.Assert.* +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class ObservableTest { + + private val observableInterface: ObservableInterface = mockk(relaxed = true) + private val observer: Observer = mockk(relaxed = true) + private val request = Request( + listOf("network"), + "https://api.mapbox.com", + RequestType.TILE, + RequestPriority.REGULAR + ) + private val response = Response( + eTag = "d8abd8d10bee6b45b4dbf5c05496587a", + mustRevalidate = false, + noContent = false, + modified = "Mon, 05 Oct 2020 14:23:52 GMT", + source = ResponseSourceType.NETWORK, + notModified = false, + expires = "Thu, 15 Oct 2020 14:32:23 GMT", + size = 181576, + error = Error(ResponseErrorReason.NOT_FOUND, "error message") + ) + private val requestMap = hashMapOf( + "loading-method" to Value(listOf(Value("network"))), + "url" to Value("https://api.mapbox.com"), + "kind" to Value("tile"), + "priority" to Value("regular") + ) + private val responseMap = hashMapOf( + "etag" to Value("d8abd8d10bee6b45b4dbf5c05496587a"), + "must-revalidate" to Value(false), + "no-content" to Value(false), + "modified" to Value("Mon, 05 Oct 2020 14:23:52 GMT"), + "source" to Value("network"), + "not-modified" to Value(false), + "expires" to Value("Thu, 15 Oct 2020 14:32:23 GMT"), + "size" to Value(181576), + "error" to + Value( + hashMapOf( + "reason" to Value("not-found"), + "message" to Value("error message") + ) + ) + ) + + @Test + fun addResourceObserver() { + observableInterface.subscribeResourceRequest(observer) + verify { observableInterface.subscribe(observer, listOf("resource-request")) } + } + + @Test + fun removeResourceObserver() { + observableInterface.unsubscribeResourceRequest(observer) + verify { observableInterface.unsubscribe(observer, listOf("resource-request")) } + } + + @Test + fun getEventData() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "data-source" to Value("network"), + "request" to Value(requestMap), + "response" to Value(responseMap), + "cancelled" to Value(false) + ) + val event = Event(MapEvents.RESOURCE_REQUEST, Value.valueOf(map)) + + val eventData = event.getResourceEventData() + assertEquals(1L, eventData.begin) + assertEquals(DataSourceType.NETWORK, eventData.dataSource) + assertEquals(false, eventData.cancelled) + assertEquals(request, eventData.request) + assertEquals(response, eventData.response) + + assertEquals(listOf("network"), eventData.request.loadingMethod) + assertEquals("https://api.mapbox.com", eventData.request.url) + assertEquals(RequestType.TILE, eventData.request.kind) + assertEquals(RequestPriority.REGULAR, eventData.request.priority) + + assertNotNull(eventData.response) + assertEquals("d8abd8d10bee6b45b4dbf5c05496587a", eventData.response!!.eTag) + assertEquals(false, eventData.response!!.mustRevalidate) + assertEquals(false, eventData.response!!.noContent) + assertEquals(ResponseSourceType.NETWORK, eventData.response!!.source) + assertEquals(false, eventData.response!!.notModified) + assertEquals("Thu, 15 Oct 2020 14:32:23 GMT", eventData.response!!.expires) + assertEquals("Mon, 05 Oct 2020 14:23:52 GMT", eventData.response!!.modified) + assertEquals(181576, eventData.response!!.size) + assertNotNull(eventData.response!!.error) + assertEquals(ResponseErrorReason.NOT_FOUND, eventData.response!!.error!!.reason) + assertEquals("error message", eventData.response!!.error!!.message) + } + + @Test + fun getEventDataWithNullPropertiesInResponse() { + val responseMap = hashMapOf( + "must-revalidate" to Value(false), + "no-content" to Value(false), + "source" to Value("network"), + "not-modified" to Value(false), + "expires" to Value("Thu, 15 Oct 2020 14:32:23 GMT"), + "size" to Value(181576), + ) + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "data-source" to Value("network"), + "request" to Value(requestMap), + "response" to Value(responseMap), + "cancelled" to Value(false) + ) + val event = Event(MapEvents.RESOURCE_REQUEST, Value.valueOf(map)) + val eventData = event.getResourceEventData() + + assertNotNull(eventData.response) + assertNull(eventData.response!!.eTag) + assertEquals(false, eventData.response!!.mustRevalidate) + assertEquals(false, eventData.response!!.noContent) + assertEquals(ResponseSourceType.NETWORK, eventData.response!!.source) + assertEquals(false, eventData.response!!.notModified) + assertEquals("Thu, 15 Oct 2020 14:32:23 GMT", eventData.response!!.expires) + assertNull(eventData.response!!.modified) + assertEquals(181576, eventData.response!!.size) + assertNull(eventData.response!!.error) + } + + @Test + fun getEventDataWithNullEnd() { + val map = hashMapOf( + "begin" to Value(1L), + "data-source" to Value("network"), + "request" to Value(requestMap), + "response" to Value(responseMap), + "cancelled" to Value(false) + ) + val event = Event(MapEvents.RESOURCE_REQUEST, Value.valueOf(map)) + + val eventData = event.getResourceEventData() + assertNull(eventData.end) + } + + @Test + fun getEventDataWithNullResponse() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "data-source" to Value("network"), + "request" to Value(requestMap), + "cancelled" to Value(false) + ) + val event = Event(MapEvents.RESOURCE_REQUEST, Value.valueOf(map)) + val eventData = event.getResourceEventData() + assertNull(eventData.response) + } + + @Test + fun getMapLoadEventData() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L) + ) + val event = Event(MapEvents.MAP_LOADED, Value.valueOf(map)) + val eventData = event.getMapLoadedEventData() + + assertEquals(1L, eventData.begin) + assertEquals(2L, eventData.end) + } + + @Test + fun getMapLoadEventDataWithNullEnd() { + val map = hashMapOf( + "begin" to Value(1L) + ) + val event = Event(MapEvents.MAP_LOADED, Value.valueOf(map)) + val eventData = event.getMapLoadedEventData() + + assertEquals(1L, eventData.begin) + assertNull(eventData.end) + } + + @Test + fun getMapLoadingErrorEventData() { + val tileIDMap = hashMapOf( + "z" to Value(1), + "x" to Value(2), + "y" to Value(3) + ) + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "type" to Value("sprite"), + "message" to Value("error message"), + "source-id" to Value("source"), + "tile-id" to Value(tileIDMap) + ) + val event = Event(MapEvents.MAP_LOADING_ERROR, Value.valueOf(map)) + val eventData = event.getMapLoadingErrorEventData() + + assertEquals(1L, eventData.begin) + assertEquals(2L, eventData.end) + assertEquals(MapLoadErrorType.SPRITE, eventData.type) + assertEquals("source", eventData.sourceId) + assertEquals("error message", eventData.message) + assertEquals(1L, eventData.tileId?.zoom) + assertEquals(2L, eventData.tileId?.x) + assertEquals(3L, eventData.tileId?.y) + } + + @Test + fun getMapLoadingErrorEventDataWithNullProperties() { + val map = hashMapOf( + "begin" to Value(1L), + "type" to Value("sprite"), + "message" to Value("error message"), + ) + val event = Event(MapEvents.MAP_LOADING_ERROR, Value.valueOf(map)) + val eventData = event.getMapLoadingErrorEventData() + assertEquals(1L, eventData.begin) + assertNull(eventData.end) + assertNull(eventData.sourceId) + assertEquals("error message", eventData.message) + assertNull(eventData.tileId) + } + + @Test + fun getMapIdleEventData() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L) + ) + val event = Event(MapEvents.MAP_IDLE, Value.valueOf(map)) + val eventData = event.getMapIdleEventData() + + assertEquals(1L, eventData.begin) + assertEquals(2L, eventData.end) + } + + @Test + fun getMapIdleEventDataWithNullEnd() { + val map = hashMapOf( + "begin" to Value(1L), + ) + val event = Event(MapEvents.MAP_IDLE, Value.valueOf(map)) + val eventData = event.getMapIdleEventData() + + assertEquals(1L, eventData.begin) + assertNull(eventData.end) + } + + @Test + fun getStyleDataLoadedEventData() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "type" to Value("sources") + ) + val event = Event(MapEvents.STYLE_DATA_LOADED, Value.valueOf(map)) + val eventData = event.getStyleDataLoadedEventData() + + assertEquals(1L, eventData.begin) + assertEquals(2L, eventData.end) + assertEquals(StyleDataType.SOURCES, eventData.type) + } + + @Test + fun getStyleDataLoadedEventDataWithNullEnd() { + val map = hashMapOf( + "begin" to Value(1L), + "type" to Value("sources") + ) + val event = Event(MapEvents.STYLE_DATA_LOADED, Value.valueOf(map)) + val eventData = event.getStyleDataLoadedEventData() + + assertEquals(1L, eventData.begin) + assertNull(eventData.end) + assertEquals(StyleDataType.SOURCES, eventData.type) + } + + @Test + fun getStyleLoadedEventData() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L) + ) + val event = Event(MapEvents.STYLE_LOADED, Value.valueOf(map)) + val eventData = event.getStyleLoadedEventData() + + assertEquals(1L, eventData.begin) + assertEquals(2L, eventData.end) + } + + @Test + fun getStyleLoadedEventDataWithNullEnd() { + val map = hashMapOf( + "begin" to Value(1L), + ) + val event = Event(MapEvents.STYLE_LOADED, Value.valueOf(map)) + val eventData = event.getStyleLoadedEventData() + + assertEquals(1L, eventData.begin) + assertNull(eventData.end) + } + + @Test + fun getSourceDataLoadedEventData() { + val tileIDMap = hashMapOf( + "z" to Value(1), + "x" to Value(2), + "y" to Value(3) + ) + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "id" to Value("id"), + "loaded" to Value(true), + "type" to Value("metadata"), + "tile-id" to Value(tileIDMap) + ) + val event = Event(MapEvents.SOURCE_DATA_LOADED, Value.valueOf(map)) + val eventData = event.getSourceDataLoadedEventData() + + assertEquals(1L, eventData.begin) + assertEquals(2L, eventData.end) + assertEquals("id", eventData.id) + assertEquals(true, eventData.loaded) + assertEquals(SourceDataType.METADATA, eventData.type) + assertEquals(1L, eventData.tileID?.zoom) + assertEquals(2L, eventData.tileID?.x) + assertEquals(3L, eventData.tileID?.y) + } + + @Test + fun getSourceDataLoadedEventDataWithNullProperties() { + val map = hashMapOf( + "begin" to Value(1L), + "id" to Value("id"), + "type" to Value("metadata"), + ) + val event = Event(MapEvents.SOURCE_DATA_LOADED, Value.valueOf(map)) + val eventData = event.getSourceDataLoadedEventData() + + assertEquals(1L, eventData.begin) + assertNull(eventData.end) + assertEquals("id", eventData.id) + assertNull(eventData.loaded) + assertEquals(SourceDataType.METADATA, eventData.type) + assertNull(eventData.tileID) + } + + @Test + fun getStyleImageMissingEventData() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "id" to Value("id"), + ) + val event = Event(MapEvents.STYLE_IMAGE_MISSING, Value.valueOf(map)) + val eventData = event.getStyleImageMissingEventData() + + assertEquals(1L, eventData.begin) + assertEquals(2L, eventData.end) + assertEquals("id", eventData.id) + } + + @Test + fun getStyleImageMissingEventDataWithNullEnd() { + val map = hashMapOf( + "begin" to Value(1L), + "id" to Value("id"), + ) + val event = Event(MapEvents.STYLE_IMAGE_MISSING, Value.valueOf(map)) + val eventData = event.getStyleImageMissingEventData() + + assertEquals(1L, eventData.begin) + assertNull(eventData.end) + assertEquals("id", eventData.id) + } + + @Test + fun getStyleImageUnusedEventData() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "id" to Value("id"), + ) + val event = Event(MapEvents.STYLE_IMAGE_REMOVE_UNUSED, Value.valueOf(map)) + val eventData = event.getStyleImageUnusedEventData() + + assertEquals(1L, eventData.begin) + assertEquals(2L, eventData.end) + assertEquals("id", eventData.id) + } + + @Test + fun getStyleImageUnusedEventDataWithNullEnd() { + val map = hashMapOf( + "begin" to Value(1L), + "id" to Value("id"), + ) + val event = Event(MapEvents.STYLE_IMAGE_REMOVE_UNUSED, Value.valueOf(map)) + val eventData = event.getStyleImageUnusedEventData() + + assertEquals(1L, eventData.begin) + assertNull(eventData.end) + assertEquals("id", eventData.id) + } + + @Test + fun getSourceAddedEventData() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "id" to Value("id"), + ) + val event = Event(MapEvents.SOURCE_ADDED, Value.valueOf(map)) + val eventData = event.getSourceAddedEventData() + + assertEquals(1L, eventData.begin) + assertEquals(2L, eventData.end) + assertEquals("id", eventData.id) + } + + @Test + fun getSourceAddedEventDataWithNullEnd() { + val map = hashMapOf( + "begin" to Value(1L), + "id" to Value("id"), + ) + val event = Event(MapEvents.SOURCE_ADDED, Value.valueOf(map)) + val eventData = event.getSourceAddedEventData() + + assertEquals(1L, eventData.begin) + assertNull(eventData.end) + assertEquals("id", eventData.id) + } + + @Test + fun getSourceRemovedEventData() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "id" to Value("id"), + ) + val event = Event(MapEvents.SOURCE_REMOVED, Value.valueOf(map)) + val eventData = event.getSourceRemovedEventData() + + assertEquals(1L, eventData.begin) + assertEquals(2L, eventData.end) + assertEquals("id", eventData.id) + } + + @Test + fun getSourceRemovedEventDataWithNullEnd() { + val map = hashMapOf( + "begin" to Value(1L), + "id" to Value("id"), + ) + val event = Event(MapEvents.SOURCE_REMOVED, Value.valueOf(map)) + val eventData = event.getSourceRemovedEventData() + + assertEquals(1L, eventData.begin) + assertNull(eventData.end) + assertEquals("id", eventData.id) + } + + @Test + fun getRenderFrameStartedEventData() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + ) + val event = Event(MapEvents.RENDER_FRAME_STARTED, Value.valueOf(map)) + val eventData = event.getRenderFrameStartedEventData() + + assertEquals(1L, eventData.begin) + assertEquals(2L, eventData.end) + } + + @Test + fun getRenderFrameStartedEventDataWithNullEnd() { + val map = hashMapOf( + "begin" to Value(1L), + ) + val event = Event(MapEvents.RENDER_FRAME_STARTED, Value.valueOf(map)) + val eventData = event.getRenderFrameStartedEventData() + + assertEquals(1L, eventData.begin) + assertNull(eventData.end) + } + + @Test + fun getRenderFrameFinishedEventData() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + "needs-repaint" to Value(true), + "placement-changed" to Value(false), + "render-mode" to Value("full"), + ) + val event = Event(MapEvents.RENDER_FRAME_FINISHED, Value.valueOf(map)) + val eventData = event.getRenderFrameFinishedEventData() + + assertEquals(1L, eventData.begin) + assertEquals(2L, eventData.end) + assertEquals(true, eventData.needsRepaint) + assertEquals(false, eventData.placementChanged) + assertEquals(RenderMode.FULL, eventData.renderMode) + } + + @Test + fun getRenderFrameFinishedEventDataWithNullEnd() { + val map = hashMapOf( + "begin" to Value(1L), + "needs-repaint" to Value(true), + "placement-changed" to Value(false), + "render-mode" to Value("full"), + ) + val event = Event(MapEvents.RENDER_FRAME_FINISHED, Value.valueOf(map)) + val eventData = event.getRenderFrameFinishedEventData() + + assertEquals(1L, eventData.begin) + assertNull(eventData.end) + assertEquals(true, eventData.needsRepaint) + assertEquals(false, eventData.placementChanged) + assertEquals(RenderMode.FULL, eventData.renderMode) + } + + @Test + fun getCameraChangedEventData() { + val map = hashMapOf( + "begin" to Value(1L), + "end" to Value(2L), + ) + val event = Event(MapEvents.CAMERA_CHANGED, Value.valueOf(map)) + val eventData = event.getCameraChangedEventData() + + assertEquals(1L, eventData.begin) + assertEquals(2L, eventData.end) + } + + @Test + fun getCameraChangedEventDataWithNullEnd() { + val map = hashMapOf( + "begin" to Value(1L), + ) + val event = Event(MapEvents.CAMERA_CHANGED, Value.valueOf(map)) + val eventData = event.getCameraChangedEventData() + + assertEquals(1L, eventData.begin) + assertNull(eventData.end) + } +} \ No newline at end of file