package social.grain import androidx.test.ext.junit.runners.AndroidJUnit4 import kotlinx.serialization.json.Json import okhttp3.OkHttpClient import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Test import org.junit.runner.RunWith import social.grain.data.location.LocationServices /** * The H3 cell is the grouping key for a location feed, so it has to agree with * every other Grain client exactly. These pin the resolution and the known * reference values rather than trusting that the binding loaded. */ @RunWith(AndroidJUnit4::class) class H3Test { private val services = LocationServices(OkHttpClient(), Json { ignoreUnknownKeys = true }) @Test fun theNativeBindingLoadsOnThisDevice() { assertTrue( "h3 ships arm and arm64 only — an x86 emulator has no binary", services.isAvailable, ) } @Test fun theDocumentedReferenceCoordinateProducesItsKnownCell() { // The H3 project's own worked example: the Statue of Liberty at // resolution 10. An independent expected value is the only thing that // proves the binding agrees with other clients — asserting the // library's output against itself would prove nothing. assertEquals("8a2a1072b59ffff", services.cellFor(40.689247, -74.044502)) } @Test fun aCellCentresBackOnThePointItCameFrom() { // The location feed's map has only the cell to work from, so the // reverse conversion has to land inside the ~65m cell it names. val center = services.coordinateFor("8a2a1072b59ffff") assertNotNull(center) assertEquals(40.689247, center!!.latitude, 0.001) assertEquals(-74.044502, center.longitude, 0.001) assertEquals("8a2a1072b59ffff", services.cellFor(center.latitude, center.longitude)) } @Test fun aCellAddressThatIsNotOneYieldsNoCoordinate() { assertNull(services.coordinateFor("not-a-cell")) } @Test fun aCellAddressIsFifteenHexCharacters() { val cell = services.cellFor(51.5074, -0.1278) assertNotNull(cell) assertEquals(15, cell!!.length) assertTrue("not hex: $cell", cell.all { it.isDigit() || it in 'a'..'f' }) } @Test fun nearbyPointsShareACellAndDistantOnesDoNot() { // Resolution 10 cells are roughly 65m across, so a few metres apart is // the same cell and a kilometre away is not. val base = services.cellFor(37.775938, -122.41795) assertEquals(base, services.cellFor(37.775940, -122.417952)) assertTrue(base != services.cellFor(37.785938, -122.41795)) } }