🔀 Merge “release/v81” into “master”
[Sone.git] / src / test / kotlin / net / pterodactylus / sone / template / HistogramRendererTest.kt
1 /**
2  * Sone - HistogramRendererTest.kt - Copyright © 2019–2020 David ‘Bombe’ Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sone.template
19
20 import com.codahale.metrics.*
21 import net.pterodactylus.sone.freenet.*
22 import net.pterodactylus.util.template.*
23 import org.hamcrest.MatcherAssert.*
24 import org.hamcrest.Matchers.*
25 import org.jsoup.*
26 import org.jsoup.nodes.*
27 import org.junit.*
28 import java.util.*
29
30 /**
31  * Unit test for [HistogramRenderer].
32  */
33 class HistogramRendererTest {
34
35         private val translation = object : Translation {
36                 override val currentLocale = Locale.ENGLISH
37                 override fun translate(key: String) = "Metric Name".takeIf { key == "Page.Metrics.TestHistogram.Title" } ?: ""
38         }
39         private val metricRenderer = HistogramRenderer()
40         private val templateContext = TemplateContext().apply {
41                 addFilter("html", HtmlFilter())
42                 addFilter("duration", DurationFormatFilter())
43                 addFilter("l10n", L10nFilter(translation))
44         }
45
46         @Test
47         fun `histogram is rendered as table row`() {
48                 createAndVerifyTableRow {
49                         assertThat(it.nodeName(), equalTo("tr"))
50                 }
51         }
52
53         @Test
54         fun `histogram has eleven columns`() {
55                 createAndVerifyTableRow {
56                         assertThat(it.getElementsByTag("td"), hasSize(11))
57                 }
58         }
59
60         @Test
61         fun `first column contains translated metric name`() {
62                 createAndVerifyTableRow(mapOf("name" to "test.histogram")) {
63                         assertThat(it.getElementsByTag("td")[0].text(), equalTo("Metric Name"))
64                 }
65         }
66
67         @Test
68         fun `second column is numeric`() {
69                 verifyColumnIsNumeric(1)
70         }
71
72         @Test
73         fun `second column contains count`() {
74                 createAndVerifyTableRow {
75                         assertThat(it.getElementsByTag("td")[1].text(), equalTo("2001"))
76                 }
77         }
78
79         @Test
80         fun `third column is numeric`() {
81                 verifyColumnIsNumeric(2)
82         }
83
84         @Test
85         fun `third column contains min value`() {
86                 createAndVerifyTableRow {
87                         assertThat(it.getElementsByTag("td")[2].text(), equalTo("2.0ms"))
88                 }
89         }
90
91         @Test
92         fun `fourth column is numeric`() {
93                 verifyColumnIsNumeric(3)
94         }
95
96         @Test
97         fun `fourth column contains max value`() {
98                 createAndVerifyTableRow {
99                         assertThat(it.getElementsByTag("td")[3].text(), equalTo("998.0ms"))
100                 }
101         }
102
103         @Test
104         fun `fifth column is numeric`() {
105                 verifyColumnIsNumeric(4)
106         }
107
108         @Test
109         fun `fifth column contains mean value`() {
110                 createAndVerifyTableRow {
111                         assertThat(it.getElementsByTag("td")[4].text(), equalTo("492.7ms"))
112                 }
113         }
114
115         @Test
116         fun `sixth column is numeric`() {
117                 verifyColumnIsNumeric(5)
118         }
119
120         @Test
121         fun `sixth column contains median value`() {
122                 createAndVerifyTableRow {
123                         assertThat(it.getElementsByTag("td")[5].text(), equalTo("483.6ms"))
124                 }
125         }
126
127         @Test
128         fun `seventh column is numeric`() {
129                 verifyColumnIsNumeric(6)
130         }
131
132         @Test
133         fun `seventh column contains 75th percentile`() {
134                 createAndVerifyTableRow {
135                         assertThat(it.getElementsByTag("td")[6].text(), equalTo("740.9ms"))
136                 }
137         }
138
139         @Test
140         fun `eighth column is numeric`() {
141                 verifyColumnIsNumeric(7)
142         }
143
144         @Test
145         fun `eighth column contains 95th percentile`() {
146                 createAndVerifyTableRow {
147                         assertThat(it.getElementsByTag("td")[7].text(), equalTo("940.9ms"))
148                 }
149         }
150
151         @Test
152         fun `ninth column is numeric`() {
153                 verifyColumnIsNumeric(8)
154         }
155
156         @Test
157         fun `ninth column contains 98th percentile`() {
158                 createAndVerifyTableRow {
159                         assertThat(it.getElementsByTag("td")[8].text(), equalTo("975.6ms"))
160                 }
161         }
162
163         @Test
164         fun `tenth column is numeric`() {
165                 verifyColumnIsNumeric(9)
166         }
167
168         @Test
169         fun `tenth column contains 99th percentile`() {
170                 createAndVerifyTableRow {
171                         assertThat(it.getElementsByTag("td")[9].text(), equalTo("991.6ms"))
172                 }
173         }
174
175         @Test
176         fun `eleventh column is numeric`() {
177                 verifyColumnIsNumeric(10)
178         }
179
180         @Test
181         fun `eleventh column contains 99,9th percentile`() {
182                 createAndVerifyTableRow {
183                         assertThat(it.getElementsByTag("td")[10].text(), equalTo("998.0ms"))
184                 }
185         }
186
187         private fun createAndVerifyTableRow(parameters: Map<String, Any?>? = null, verify: (Element) -> Unit) =
188                         metricRenderer.format(templateContext, histogram, parameters)
189                                         .let { "<table id='t'>$it</table>" }
190                                         .let(Jsoup::parseBodyFragment)
191                                         .getElementById("t").child(0).child(0)
192                                         .let(verify)
193
194         private fun verifyColumnIsNumeric(column: Int) =
195                         createAndVerifyTableRow {
196                                 assertThat(it.getElementsByTag("td")[column].classNames(), hasItem("numeric"))
197                         }
198
199 }
200
201 private val random = Random(1)
202 private val histogram = MetricRegistry().histogram("test.histogram") { Histogram(SlidingWindowReservoir(1028)) }.apply {
203         (0..2000).map { random.nextInt(1_000_000) }.forEach(this::update)
204 }