Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ class BomPublishingConventionPlugin : Plugin<Project> {

extensions.configure<MavenPublishBaseExtension> {
publishToMavenCentral()
signAllPublications()
if (findProperty("signing.keyId")?.toString()?.isNotBlank() == true ||
findProperty("signing.secretKeyRingFile")?.toString()?.isNotBlank() == true ||
findProperty("signingInMemoryKey")?.toString()?.isNotBlank() == true
) {
signAllPublications()
}

coordinates(
artifactId = "maps-utils-bom",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,12 @@ class PublishingConventionPlugin : Plugin<Project> {
)

publishToMavenCentral()
signAllPublications()
if (findProperty("signing.keyId")?.toString()?.isNotBlank() == true ||
findProperty("signing.secretKeyRingFile")?.toString()?.isNotBlank() == true ||
findProperty("signingInMemoryKey")?.toString()?.isNotBlank() == true
) {
signAllPublications()
}

val artifactIdName = when (project.name) {
"maps-utils" -> "android-maps-utils"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ open class ClusterManager<T : ClusterItem>
/**
* Might re-cluster.
*/
open override fun onCameraIdle() {
override fun onCameraIdle() {
if (mRenderer is OnCameraIdleListener) {
(mRenderer as OnCameraIdleListener).onCameraIdle()
}
Expand All @@ -317,9 +317,9 @@ open class ClusterManager<T : ClusterItem>
}
}

open override fun onMarkerClick(marker: Marker): Boolean = markerManager.onMarkerClick(marker)
override fun onMarkerClick(marker: Marker): Boolean = markerManager.onMarkerClick(marker)

open override fun onInfoWindowClick(marker: Marker) {
override fun onInfoWindowClick(marker: Marker) {
markerManager.onInfoWindowClick(marker)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.maps.android.clustering

import android.content.Context
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.Marker
import com.google.common.truth.Truth.assertThat
import com.google.maps.android.clustering.algo.GridBasedAlgorithm
import com.google.maps.android.clustering.algo.ScreenBasedAlgorithmAdapter
import com.google.maps.android.clustering.view.ClusterRenderer
import com.google.maps.android.collections.MarkerManager
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment

/**
* Unit tests for [ClusterManager].
*/
@RunWith(RobolectricTestRunner::class)
class ClusterManagerTest {

private class TestItem(lat: Double, lng: Double) : ClusterItem {
override val position: LatLng = LatLng(lat, lng)
override val title: String? = null
override val snippet: String? = null
override val zIndex: Float? = null
}

private lateinit var context: Context
private lateinit var map: GoogleMap
private lateinit var markerManager: MarkerManager
private lateinit var clusterManager: ClusterManager<TestItem>

@Before
fun setUp() {
context = RuntimeEnvironment.getApplication()
map = mockk(relaxed = true)
markerManager = MarkerManager(map)
clusterManager = ClusterManager(context, map, markerManager)
}

@Test
fun testItemLifecycle() {
val item1 = TestItem(10.0, 10.0)
val item2 = TestItem(20.0, 20.0)

assertThat(clusterManager.addItem(item1)).isTrue()
assertThat(clusterManager.addItems(listOf(item2))).isTrue()

assertThat(clusterManager.updateItem(item1)).isTrue()

assertThat(clusterManager.removeItem(item1)).isTrue()
assertThat(clusterManager.removeItems(listOf(item2))).isTrue()

clusterManager.addItem(item1)
clusterManager.clearItems()
}

@Test
fun testAlgorithmAndRendererCustomization() {
val customScreenAlgo = ScreenBasedAlgorithmAdapter(GridBasedAlgorithm<TestItem>())
clusterManager.setAlgorithm(customScreenAlgo)
assertThat(clusterManager.algorithm).isEqualTo(customScreenAlgo)

val customBaseAlgo = GridBasedAlgorithm<TestItem>()
clusterManager.algorithm = customBaseAlgo
assertThat(clusterManager.algorithm).isInstanceOf(ScreenBasedAlgorithmAdapter::class.java)

val customRenderer = mockk<ClusterRenderer<TestItem>>(relaxed = true)
clusterManager.renderer = customRenderer
assertThat(clusterManager.renderer).isEqualTo(customRenderer)
verify { customRenderer.onAdd() }

clusterManager.setAnimation(true)
}

@Test
fun testDelegatedMapEvents() {
val mockMarker = mockk<Marker>(relaxed = true)

clusterManager.onCameraIdle()
clusterManager.onMarkerClick(mockMarker)
clusterManager.onInfoWindowClick(mockMarker)
}

@Test
fun testListenerSetters() {
val clusterClickListener = ClusterManager.OnClusterClickListener<TestItem> { true }
val itemClickListener = ClusterManager.OnClusterItemClickListener<TestItem> { true }
val clusterInfoClickListener = ClusterManager.OnClusterInfoWindowClickListener<TestItem> {}
val itemInfoClickListener = ClusterManager.OnClusterItemInfoWindowClickListener<TestItem> {}

clusterManager.setOnClusterClickListener(clusterClickListener)
clusterManager.setOnClusterItemClickListener(itemClickListener)
clusterManager.setOnClusterInfoWindowClickListener(clusterInfoClickListener)
clusterManager.setOnClusterItemInfoWindowClickListener(itemInfoClickListener)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.maps.android.clustering

import com.google.android.gms.maps.model.LatLng
import com.google.common.truth.Truth.assertThat
import com.google.maps.android.clustering.algo.StaticCluster
import org.junit.Test

/**
* Unit tests for [StaticCluster].
*/
class StaticClusterTest {

private class TestItem(lat: Double, lng: Double) : ClusterItem {
override val position: LatLng = LatLng(lat, lng)
override val title: String? = null
override val snippet: String? = null
override val zIndex: Float? = null
}

@Test
fun testEquality() {
val cluster1 = StaticCluster<ClusterItem>(LatLng(0.1, 0.5))
val cluster2 = StaticCluster<ClusterItem>(LatLng(0.1, 0.5))

assertThat(cluster1).isEqualTo(cluster2)
assertThat(cluster1).isNotSameInstanceAs(cluster2)
assertThat(cluster1.hashCode()).isEqualTo(cluster2.hashCode())
}

@Test
fun testUnequality() {
val cluster1 = StaticCluster<ClusterItem>(LatLng(0.1, 0.5))
val cluster2 = StaticCluster<ClusterItem>(LatLng(0.2, 0.3))

assertThat(cluster1).isNotEqualTo(cluster2)
assertThat(cluster1.hashCode()).isNotEqualTo(cluster2.hashCode())
assertThat(cluster1).isNotEqualTo(null)
assertThat(cluster1).isNotEqualTo("not a cluster")
}

@Test
fun testItemOperationsAndProperties() {
val center = LatLng(10.0, 20.0)
val cluster = StaticCluster<ClusterItem>(center)

assertThat(cluster.position).isEqualTo(center)
assertThat(cluster.size).isEqualTo(0)
assertThat(cluster.items).isEmpty()

val item = TestItem(10.0, 20.0)
cluster.add(item)
assertThat(cluster.size).isEqualTo(1)
assertThat(cluster.items).containsExactly(item)
assertThat(cluster.toString()).contains("StaticCluster")

cluster.remove(item)
assertThat(cluster.size).isEqualTo(0)
assertThat(cluster.items).isEmpty()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.maps.android.clustering.algo

import com.google.android.gms.maps.model.LatLng
import com.google.common.truth.Truth.assertThat
import com.google.maps.android.clustering.Cluster
import com.google.maps.android.clustering.ClusterItem
import org.junit.Test

/**
* Unit tests for [AbstractAlgorithm].
*/
class AbstractAlgorithmTest {

private class TestItem : ClusterItem {
override val position: LatLng = LatLng(0.0, 0.0)
override val title: String? = null
override val snippet: String? = null
override val zIndex: Float? = null
}

private class ConcreteAlgorithm : AbstractAlgorithm<TestItem>() {
override fun addItem(item: TestItem): Boolean = true
override fun addItems(items: Collection<TestItem>): Boolean = true
override fun clearItems() {}
override fun removeItem(item: TestItem): Boolean = true
override fun removeItems(items: Collection<TestItem>): Boolean = true
override fun updateItem(item: TestItem): Boolean = true
override fun getClusters(zoom: Float): Set<Cluster<TestItem>> = emptySet()
override val items: Collection<TestItem> get() = emptyList()
override var maxDistanceBetweenClusteredItems: Int = 100
}

@Test
fun testLockOperations() {
val algorithm = ConcreteAlgorithm()
var lockExecuted = false
algorithm.lock()
try {
lockExecuted = true
} finally {
algorithm.unlock()
}
assertThat(lockExecuted).isTrue()
}
}
Loading