SimpleNotes/search/test/NoteSearcherImplTest.kt

159 lines
4.4 KiB
Kotlin

package be.simplenotes.search
import be.simplenotes.types.PersistedNote
import be.simplenotes.types.PersistedNoteMetadata
import org.assertj.core.api.Assertions.assertThat
import org.intellij.lang.annotations.Language
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.parallel.ResourceLock
import java.nio.file.Path
import java.time.LocalDateTime
import java.util.*
@ResourceLock("lucene")
internal class NoteSearcherImplTest {
// region setup
private val searcher = NoteSearcherImpl(Path.of("/tmp", "lucene"))
private fun index(
title: String,
tags: List<String> = emptyList(),
content: String = "",
uuid: UUID = UUID.randomUUID(),
): PersistedNote {
val note = PersistedNote(
title = title,
tags = tags,
markdown = content,
html = "",
updatedAt = LocalDateTime.MIN,
uuid = uuid,
public = false
)
searcher.indexNote(1, note)
return note
}
private fun search(
title: String? = null,
tag: String? = null,
content: String? = null,
all: String? = null,
): List<PersistedNoteMetadata> = searcher.search(1, SearchTerms(title, tag, content, all))
@BeforeEach
@AfterAll
fun dropIndexes() {
searcher.dropIndex(1)
}
@Language("markdown")
val markdownSample =
"""
# Apache Lucene Core
Apache Lucene is a high-performance, full-featured text search engine library written entirely in Java.
It is a technology suitable for nearly any application that requires full-text search, especially cross-platform.
Apache Lucene is an open source project available for free download. Please use the links on the right to access Lucene.
# Lucene Features
Lucene offers powerful features through a simple API:
## Scalable, High-Performance Indexing
* over [150GB/hour on modern hardware](http://home.apache.org/~mikemccand/lucenebench/indexing.html)
* small RAM requirements -- only 1MB heap
* incremental indexing as fast as batch indexing
* index size roughly 20-30% the size of text indexed
""".trimIndent()
// endregion
@Test
fun `exact title search`() {
index("first")
index("second")
index("flip")
assertThat(search("first"))
.hasSizeGreaterThanOrEqualTo(1)
.anyMatch { it.title == "first" }
assertThat(search("nothing")).isEmpty()
}
@Test
fun `fuzzy title search`() {
index("first")
index("second")
index("flip")
@Suppress("SpellCheckingInspection")
assertThat(search("firt"))
.hasSizeGreaterThanOrEqualTo(1)
.anyMatch { it.title == "first" }
assertThat(search("nothing")).isEmpty()
}
@Test
fun `exact tags search`() {
index("first", tags = listOf("example", "flamingo"))
index("second", tags = listOf("yes"))
index("second")
assertThat(search(tag = "example"))
.hasSize(1)
.anyMatch { it.title == "first" }
}
@Test
fun `exact content search`() {
index("first", content = markdownSample)
assertThat(search(content = "fast"))
.hasSize(1)
.anyMatch { it.title == "first" }
@Suppress("SpellCheckingInspection")
assertThat(search(content = "preformance")) // <- note the error
.hasSize(1)
.anyMatch { it.title == "first" }
}
@Test
fun `combined search`() {
index("first", content = markdownSample, tags = listOf("abc"))
assertThat(search(title = "fir", tag = "abc", content = "20"))
.hasSize(1)
}
@Test
fun `search all`() {
index("first", content = markdownSample, tags = listOf("abc"))
assertThat(search(all = "abc", title = "first"))
.hasSize(1)
}
@Test
fun `delete index`() {
val uuid = index("first").uuid
searcher.deleteIndex(1, uuid)
assertThat(search("first")).isEmpty()
}
@Test
fun `update index`() {
val note = index("first")
searcher.updateIndex(1, note.copy(title = "new"))
assertThat(search("first")).isEmpty()
assertThat(search("new")).hasSize(1)
}
}