✨ Render histograms in a filter
[Sone.git] / src / test / kotlin / net / pterodactylus / sone / template / HistogramRendererTest.kt
diff --git a/src/test/kotlin/net/pterodactylus/sone/template/HistogramRendererTest.kt b/src/test/kotlin/net/pterodactylus/sone/template/HistogramRendererTest.kt
new file mode 100644 (file)
index 0000000..592c3ef
--- /dev/null
@@ -0,0 +1,204 @@
+/**
+ * Sone - HistogramRendererTest.kt - Copyright © 2019 David ‘Bombe’ Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.template
+
+import com.codahale.metrics.*
+import net.pterodactylus.sone.freenet.*
+import net.pterodactylus.util.template.*
+import org.hamcrest.MatcherAssert.*
+import org.hamcrest.Matchers.*
+import org.jsoup.*
+import org.jsoup.nodes.*
+import org.junit.*
+import java.util.*
+
+/**
+ * Unit test for [HistogramRenderer].
+ */
+class HistogramRendererTest {
+
+       private val translation = object : Translation {
+               override val currentLocale = Locale.ENGLISH
+               override fun translate(key: String) = "Metric Name".takeIf { key == "Page.Metrics.TestHistogram.Title" } ?: ""
+       }
+       private val metricRenderer = HistogramRenderer()
+       private val templateContext = TemplateContext().apply {
+               addFilter("html", HtmlFilter())
+               addFilter("duration", DurationFormatFilter())
+               addFilter("l10n", L10nFilter(translation))
+       }
+
+       @Test
+       fun `histogram is rendered as table row`() {
+               createAndVerifyTableRow {
+                       assertThat(it.nodeName(), equalTo("tr"))
+               }
+       }
+
+       @Test
+       fun `histogram has eleven columns`() {
+               createAndVerifyTableRow {
+                       assertThat(it.getElementsByTag("td"), hasSize(11))
+               }
+       }
+
+       @Test
+       fun `first column contains translated metric name`() {
+               createAndVerifyTableRow(mapOf("name" to "test.histogram")) {
+                       assertThat(it.getElementsByTag("td")[0].text(), equalTo("Metric Name"))
+               }
+       }
+
+       @Test
+       fun `second column is numeric`() {
+               verifyColumnIsNumeric(1)
+       }
+
+       @Test
+       fun `second column contains count`() {
+               createAndVerifyTableRow {
+                       assertThat(it.getElementsByTag("td")[1].text(), equalTo("1001"))
+               }
+       }
+
+       @Test
+       fun `third column is numeric`() {
+               verifyColumnIsNumeric(2)
+       }
+
+       @Test
+       fun `third column contains min value`() {
+               createAndVerifyTableRow {
+                       assertThat(it.getElementsByTag("td")[2].text(), equalTo("3.4ms"))
+               }
+       }
+
+       @Test
+       fun `fourth column is numeric`() {
+               verifyColumnIsNumeric(3)
+       }
+
+       @Test
+       fun `fourth column contains max value`() {
+               createAndVerifyTableRow {
+                       assertThat(it.getElementsByTag("td")[3].text(), equalTo("998.9ms"))
+               }
+       }
+
+       @Test
+       fun `fifth column is numeric`() {
+               verifyColumnIsNumeric(4)
+       }
+
+       @Test
+       fun `fifth column contains mean value`() {
+               createAndVerifyTableRow {
+                       assertThat(it.getElementsByTag("td")[4].text(), equalTo("503.4ms"))
+               }
+       }
+
+       @Test
+       fun `sixth column is numeric`() {
+               verifyColumnIsNumeric(5)
+       }
+
+       @Test
+       fun `sixth column contains median value`() {
+               createAndVerifyTableRow {
+                       assertThat(it.getElementsByTag("td")[5].text(), equalTo("501.0ms"))
+               }
+       }
+
+       @Test
+       fun `seventh column is numeric`() {
+               verifyColumnIsNumeric(6)
+       }
+
+       @Test
+       fun `seventh column contains 75th percentile`() {
+               createAndVerifyTableRow {
+                       assertThat(it.getElementsByTag("td")[6].text(), equalTo("757.8ms"))
+               }
+       }
+
+       @Test
+       fun `eighth column is numeric`() {
+               verifyColumnIsNumeric(7)
+       }
+
+       @Test
+       fun `eighth column contains 95th percentile`() {
+               createAndVerifyTableRow {
+                       assertThat(it.getElementsByTag("td")[7].text(), equalTo("948.6ms"))
+               }
+       }
+
+       @Test
+       fun `ninth column is numeric`() {
+               verifyColumnIsNumeric(8)
+       }
+
+       @Test
+       fun `ninth column contains 98th percentile`() {
+               createAndVerifyTableRow {
+                       assertThat(it.getElementsByTag("td")[8].text(), equalTo("972.7ms"))
+               }
+       }
+
+       @Test
+       fun `tenth column is numeric`() {
+               verifyColumnIsNumeric(9)
+       }
+
+       @Test
+       fun `tenth column contains 99th percentile`() {
+               createAndVerifyTableRow {
+                       assertThat(it.getElementsByTag("td")[9].text(), equalTo("986.4ms"))
+               }
+       }
+
+       @Test
+       fun `eleventh column is numeric`() {
+               verifyColumnIsNumeric(10)
+       }
+
+       @Test
+       fun `eleventh column contains 99,9th percentile`() {
+               createAndVerifyTableRow {
+                       assertThat(it.getElementsByTag("td")[10].text(), equalTo("998.5ms"))
+               }
+       }
+
+       private fun createAndVerifyTableRow(parameters: Map<String, Any?>? = null, verify: (Element) -> Unit) =
+                       metricRenderer.format(templateContext, histogram, parameters)
+                                       .let { "<table id='t'>$it</table>" }
+                                       .let(Jsoup::parseBodyFragment)
+                                       .getElementById("t").child(0).child(0)
+                                       .let(verify)
+
+       private fun verifyColumnIsNumeric(column: Int) =
+                       createAndVerifyTableRow {
+                               assertThat(it.getElementsByTag("td")[column].classNames(), hasItem("numeric"))
+                       }
+
+}
+
+private val random = Random(1)
+private val histogram = MetricRegistry().histogram("test.histogram").apply {
+       (0..1000).map { random.nextInt(1_000_000) }.forEach(this::update)
+}