158 lines
4.4 KiB
Kotlin
158 lines
4.4 KiB
Kotlin
package be.simplenotes.search
|
|
|
|
import be.simplenotes.types.NoteMetadata
|
|
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.time.LocalDateTime
|
|
import java.util.*
|
|
|
|
@ResourceLock("lucene")
|
|
internal class NoteSearcherImplTest {
|
|
|
|
// region setup
|
|
private val searcher = NoteSearcherImpl()
|
|
|
|
private fun index(
|
|
title: String,
|
|
tags: List<String> = emptyList(),
|
|
content: String = "",
|
|
uuid: UUID = UUID.randomUUID(),
|
|
): PersistedNote {
|
|
val note = PersistedNote(
|
|
NoteMetadata(title, tags),
|
|
markdown = content,
|
|
html = "",
|
|
LocalDateTime.MIN,
|
|
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(meta = note.meta.copy(title = "new")))
|
|
assertThat(search("first")).isEmpty()
|
|
assertThat(search("new")).hasSize(1)
|
|
}
|
|
}
|