package link.roadio.riff.indexer.android.cuetree import android.os.ParcelFileDescriptor import androidx.test.platform.app.InstrumentationRegistry import link.roadio.cuetree.Cancellation import link.roadio.cuetree.Snapshot import link.roadio.riff.indexer.core.ipc.IndexerArtifactKind import link.roadio.riff.storage.hash.nativeXxh3 import org.junit.Assert.assertEquals import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Test import java.nio.file.Files import java.util.concurrent.CountDownLatch import java.util.concurrent.Executors import java.util.concurrent.TimeUnit class CuetreeArtifactLifetimeInstrumentedTest { @Test fun acceptedDescriptorBypassesStoreWorkAndSurvivesPruningAndClose() { val context = InstrumentationRegistry.getInstrumentation().context check(context.packageName == "link.roadio.riff.indexer.module.test") val directory = Files.createTempDirectory(context.cacheDir.toPath(), "cohort-lifetime-").toFile() val store = AndroidCuetreeStore(directory, context) val workers = Executors.newFixedThreadPool(2) val entered = CountDownLatch(1) val release = CountDownLatch(1) try { fun publish(generation: Long) = store.publish( Snapshot( generation, AndroidCuetreeIdentity(context).scheme, emptyList(), metadataRevision = AndroidCuetreeMetadataRevision.current, ), Cancellation(), ) publish(1) val held = workers.submit { synchronized(store) { entered.countDown() check(release.await(10, TimeUnit.SECONDS)) } } assertTrue(entered.await(2, TimeUnit.SECONDS)) val artifact = try { workers .submit { store.currentArtifact(IndexerArtifactKind.CUMD) }.get(2, TimeUnit.SECONDS) } finally { release.countDown() held.get(2, TimeUnit.SECONDS) } checkNotNull(artifact) try { publish(2) publish(3) store.close() assertNull(store.currentArtifact(IndexerArtifactKind.CUMD)) val bytes = ParcelFileDescriptor.AutoCloseInputStream(artifact.descriptor).use { it.readBytes() } assertEquals(artifact.metadata.length, bytes.size.toLong()) assertEquals(artifact.metadata.xxh3, nativeXxh3(bytes)) } finally { artifact.descriptor.close() } } finally { release.countDown() workers.shutdownNow() store.close() directory.deleteRecursively() } } }