Skip to content

Commit

Permalink
Merge pull request #95 from kennethshackleton/patch-0.12.6
Browse files Browse the repository at this point in the history
Patch 0.12.6.
  • Loading branch information
kennethshackleton authored May 3, 2021
2 parents 26f5e42 + 52a901d commit 207a299
Show file tree
Hide file tree
Showing 12 changed files with 133 additions and 33 deletions.
18 changes: 6 additions & 12 deletions AndroidLib/src/main/kotlin/com/bloomberg/selekt/android/Cursors.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,14 @@ import android.database.AbstractCursor
import android.database.Cursor
import com.bloomberg.selekt.ColumnType
import com.bloomberg.selekt.ICursor
import com.bloomberg.selekt.SQL_BLOB
import com.bloomberg.selekt.SQL_FLOAT
import com.bloomberg.selekt.SQL_INTEGER
import com.bloomberg.selekt.SQL_NULL
import com.bloomberg.selekt.SQL_TEXT
import javax.annotation.concurrent.NotThreadSafe

private fun ColumnType.asAndroidCursorFieldType() = when (sqlDataType) {
SQL_TEXT -> Cursor.FIELD_TYPE_STRING
SQL_INTEGER -> Cursor.FIELD_TYPE_INTEGER
SQL_NULL -> Cursor.FIELD_TYPE_NULL
SQL_FLOAT -> Cursor.FIELD_TYPE_FLOAT
SQL_BLOB -> Cursor.FIELD_TYPE_BLOB
else -> error("Unrecognised column type: $sqlDataType")
private fun ColumnType.asAndroidCursorFieldType() = when (this) {
ColumnType.STRING -> Cursor.FIELD_TYPE_STRING
ColumnType.INTEGER -> Cursor.FIELD_TYPE_INTEGER
ColumnType.NULL -> Cursor.FIELD_TYPE_NULL
ColumnType.FLOAT -> Cursor.FIELD_TYPE_FLOAT
ColumnType.BLOB -> Cursor.FIELD_TYPE_BLOB
}

internal fun ICursor.asAndroidCursor(): Cursor = CursorWrapper(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,12 @@ private class SupportSQLiteDatabase constructor(

override fun execSQL(@Language("RoomSql") sql: String, bindArgs: Array<out Any>) = database.exec(sql, bindArgs)

override fun getAttachedDbs() = sequence<Pair<String, String>> {
database.query("PRAGMA database_list", null).use {
while (it.moveToNext()) {
yield(Pair(it.getString(1), it.getString(2)))
}
override fun getAttachedDbs() = database.query("PRAGMA database_list", null).use {
List<Pair<String, String>>(it.count) { _ ->
it.moveToNext()
Pair(it.getString(1), it.getString(2))
}
}.toList()
}

override fun getMaximumSize() = database.maximumSize

Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
Change Log
==========

## Version 0.12.6

### Fixes

* Fix convenience method for deleting database files, and extend its test coverage.
* Use the `ColumnType`-enum directly when converting to an Android Cursor column type. This increases code coverage by removing a branch we cannot test.
* Appeal instead to a Java-cast in Queries when casting an array, Kotlin's `as` results in a generated null-check branch which won't be encountered here and can't be tested. This increases code coverage.
* Reduce the number of logical branches in the pool implementations, simplifying these implementations and increasing their test coverage.

## Version 0.12.5

### Fixes
Expand Down
2 changes: 1 addition & 1 deletion Lib/src/main/kotlin/com/bloomberg/selekt/Queries.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ internal class SQLQuery internal constructor(
@Language("RoomSql") sql: String,
statementType: SQLStatementType,
args: Array<out Any?>
) = SQLQuery(session, sql, statementType, args.copyOf() as Array<Any?>)
) = SQLQuery(session, sql, statementType, Array<Any?>::class.java.cast(args.copyOf()))
}

override fun bindBlob(index: Int, value: ByteArray) = bind(index, value)
Expand Down
10 changes: 7 additions & 3 deletions Lib/src/main/kotlin/com/bloomberg/selekt/commons/Database.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ fun deleteDatabase(file: File) = file.run {
File("$absolutePath-shm").delete() or
File("$absolutePath-wal").delete()
parentFile?.let {
val prefix = "${it.name}-mj"
it.listFiles { f -> f.name.startsWith(prefix) }
}?.forEach { deleted = deleted or it.delete() }
val prefix = "$name-mj"
it.listFiles {
f -> f.name.startsWith(prefix)
}?.forEach {
deleted = deleted or it.delete()
}
}
deleted
}
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,12 @@ class CommonObjectPool<K : Any, T : IPooledObject<K>>(
}
}

private infix fun T.shouldBeRemovedAt(priority: Priority?): Boolean {
fun T.isIdle() = this@isIdle.tag != this@CommonObjectPool.tag
return priority == null && isIdle() && future?.isCancelled == false ||
!priority.isHigh() && isIdle() ||
private infix fun T.shouldBeRemovedAt(
priority: Priority?
) = (this@shouldBeRemovedAt.tag != this@CommonObjectPool.tag).let {
priority == null && it && future?.isCancelled == false ||
isClosed.get() ||
priority.isHigh()
priority.isHigh() ||
it
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,10 @@ class SingleObjectPool<K : Any, T : IPooledObject<K>>(
}
}

private infix fun T.shouldBeRemovedAt(priority: Priority?) =
priority == null && canEvict && future?.isCancelled == false ||
!priority.isHigh() && canEvict ||
private infix fun T.shouldBeRemovedAt(priority: Priority?) = canEvict.let {
priority == null && it && future?.isCancelled == false ||
isClosed ||
priority.isHigh()
priority.isHigh() ||
it
}
}
8 changes: 8 additions & 0 deletions Lib/src/test/kotlin/com/bloomberg/selekt/SQLConnectionTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,14 @@ internal class SQLConnectionTest {
}
}

@Test
fun releaseMemory() {
SQLConnection("file::memory:", sqlite, databaseConfiguration, 0, CommonThreadLocalRandom, null).use {
it.releaseMemory()
verify(sqlite, times(1)).databaseReleaseMemory(any())
}
}

private companion object {
const val DB = 1L
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,69 @@

package com.bloomberg.selekt.commons

import com.nhaarman.mockitokotlin2.doReturn
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.whenever
import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertDoesNotThrow
import java.io.File
import java.nio.file.Files
import kotlin.test.assertEquals
import kotlin.test.assertTrue

internal class DatabaseKtTest {
private val parent = Files.createTempDirectory("foo").toFile().also { it.deleteOnExit() }

@AfterEach
fun tearDown() {
assertTrue(parent.deleteRecursively())
}

@Test
fun deleteDatabase() {
arrayOf(
"db",
"db-journal",
"db-shm",
"db-wal"
).forEach {
Files.createFile(File("${parent.absolutePath}/$it").toPath())
}
Files.createFile(File("${parent.absolutePath}/db-mj-bar").toPath())
assertEquals(false, parent.listFiles { f -> f.name.startsWith("db") }?.isEmpty())
deleteDatabase(File("${parent.absolutePath}/db"))
assertEquals(true, parent.listFiles { f -> f.name.startsWith("db") }?.isEmpty())
}

@Test
fun deleteDatabaseDirectory() {
assertThatExceptionOfType(IllegalArgumentException::class.java).isThrownBy {
deleteDatabase(Files.createTempDirectory("foo").toFile().also { it.deleteOnExit() })
deleteDatabase(parent)
}
}

@Test
fun deleteDatabaseWithoutParent() {
mock<File>().apply {
whenever(isFile) doReturn true
}.let {
assertDoesNotThrow {
deleteDatabase(it)
}
}
}

@Test
fun deleteDatabaseWithoutParentFile() {
mock<File>().apply {
whenever(isFile) doReturn true
whenever(parentFile) doReturn File("foo")
}.let {
assertDoesNotThrow {
deleteDatabase(it)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,21 @@ internal class CommonObjectPoolTest {
assertSame("Object was evicted.", obj, it.borrowObject())
}

@Test
fun evictionNegativeIntervalFails() = CommonObjectPool(object : IObjectFactory<PooledObject> {
override fun close() = Unit

override fun destroyObject(obj: PooledObject) = Unit

override fun makeObject() = makePrimaryObject()

override fun makePrimaryObject() = PooledObject()
}, executor, configuration.copy(evictionIntervalMillis = -1L, evictionDelayMillis = 100L), other).use {
val obj = it.borrowObject().apply { it.returnObject(this) }
Thread.sleep(500L)
assertSame(obj, it.borrowObject().apply { it.returnObject(this) }, "Pool must return the same object.")
}

@Test
fun throwsOnBorrowAfterClose(): Unit = pool.run {
close()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,21 @@ internal class SingleObjectPoolTest {
assertSame(two, borrowObject().also { returnObject(it) }, "Pool must return the same object.")
}

@Test
fun evictionNegativeIntervalFails() = SingleObjectPool(object : IObjectFactory<PooledObject> {
override fun close() = Unit

override fun destroyObject(obj: PooledObject) = Unit

override fun makeObject() = makePrimaryObject()

override fun makePrimaryObject() = PooledObject()
}, executor, 100L, -1L).use {
val obj = it.borrowObject().apply { it.returnObject(this) }
Thread.sleep(500L)
assertSame(obj, it.borrowObject().apply { it.returnObject(this) }, "Pool must return the same object.")
}

@Test
fun newObjectAfterSuccessfulEviction() = pool.run {
val obj = borrowObject().also { returnObject(it) }
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
selekt.versionName=0.12.5
selekt.versionName=0.12.6

openssl.version=1.1.1
openssl.version.suffix=d
Expand Down

0 comments on commit 207a299

Please sign in to comment.