2 * Sone - PageToadletTest.kt - Copyright © 2020 David Roden
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.
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.
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/>.
18 package net.pterodactylus.sone.web.page
20 import freenet.client.HighLevelSimpleClient
21 import freenet.clients.http.Cookie
22 import freenet.clients.http.FProxyFetchInProgress.REFILTER_POLICY
23 import freenet.clients.http.LinkEnabledCallback
24 import freenet.clients.http.PageMaker
25 import freenet.clients.http.ReceivedCookie
26 import freenet.clients.http.SessionManager
27 import freenet.clients.http.Toadlet
28 import freenet.clients.http.ToadletContainer
29 import freenet.clients.http.ToadletContext
30 import freenet.clients.http.bookmark.BookmarkManager
31 import freenet.node.useralerts.UserAlertManager
32 import freenet.support.HTMLNode
33 import freenet.support.MultiValueTable
34 import freenet.support.api.Bucket
35 import freenet.support.api.BucketFactory
36 import freenet.support.api.HTTPRequest
37 import freenet.support.io.ArrayBucket
38 import net.pterodactylus.sone.test.deepMock
39 import net.pterodactylus.sone.test.mock
40 import net.pterodactylus.sone.test.whenever
41 import net.pterodactylus.util.web.Method
42 import net.pterodactylus.util.web.Page
43 import net.pterodactylus.util.web.Response
44 import org.hamcrest.MatcherAssert.assertThat
45 import org.hamcrest.Matchers.arrayContaining
46 import org.hamcrest.Matchers.equalTo
47 import org.hamcrest.Matchers.sameInstance
49 import org.mockito.ArgumentMatchers.anyLong
52 import kotlin.text.Charsets.UTF_8
55 * Unit test for PageToadletTest.
57 class PageToadletTest {
59 private val highLevelSimpleClient = mock<HighLevelSimpleClient>()
60 private val sessionManager = mock<SessionManager>()
61 private val httpRequest = mock<HTTPRequest>()
62 private val toadletContext = deepMock<ToadletContext>()
65 whenever(toadletContext.bucketFactory.makeBucket(anyLong())).then { ArrayBucket() }
69 fun `get request is forwarded to page correctly`() {
70 var capturedRequest: FreenetRequest? = null
71 val page = object : TestPage() {
72 override fun handleRequest(request: FreenetRequest, response: Response) =
73 super.handleRequest(request, response)
74 .also { capturedRequest = request }
76 val pageToadlet = PageToadlet(highLevelSimpleClient, sessionManager, "MenuName", page, "/path/")
77 pageToadlet.handleMethodGET(URI("/test"), httpRequest, toadletContext)
78 assertThat(capturedRequest!!.uri, equalTo(URI("/test")))
79 assertThat(capturedRequest!!.method, equalTo(Method.GET))
83 fun `post request is forwarded to page correctly`() {
84 var capturedRequest: FreenetRequest? = null
85 val page = object : TestPage() {
86 override fun handleRequest(request: FreenetRequest, response: Response) =
87 super.handleRequest(request, response)
88 .also { capturedRequest = request }
90 val pageToadlet = PageToadlet(highLevelSimpleClient, sessionManager, "MenuName", page, "/path/")
91 pageToadlet.handleMethodPOST(URI("/test"), httpRequest, toadletContext)
92 assertThat(capturedRequest!!.uri, equalTo(URI("/test")))
93 assertThat(capturedRequest!!.method, equalTo(Method.POST))
97 fun `content written to response is written to context`() {
98 val page = object : TestPage() {
99 override fun handleRequest(request: FreenetRequest, response: Response) =
103 contentType = "data/test"
104 addHeader("Test", "Value")
105 addHeader("More", "true")
106 addHeader("Test", "Another")
110 val pageToadlet = PageToadlet(highLevelSimpleClient, sessionManager, "MenuName", page, "/path/")
111 var writtenData: ByteArray? = null
112 var capturedReply: CapturedReply? = null
113 val toadletContext = object : DelegatingToadletContext(this.toadletContext) {
114 override fun sendReplyHeaders(code: Int, desc: String?, mvt: MultiValueTable<String, String>?, mimeType: String?, length: Long) =
115 sendReplyHeaders(code, desc, mvt, mimeType, length, false)
117 override fun sendReplyHeaders(code: Int, desc: String?, mvt: MultiValueTable<String, String>?, mimeType: String?, length: Long, forceDisableJavascript: Boolean) {
118 capturedReply = CapturedReply(code, desc, mvt, mimeType, length)
121 override fun writeData(data: ByteArray?, offset: Int, length: Int) {
122 writtenData = data!!.copyOfRange(offset, offset + length)
125 override fun writeData(data: ByteArray?) = writeData(data, 0, data!!.size)
126 override fun writeData(data: Bucket?) = writeData(data!!.inputStream.readBytes())
128 pageToadlet.handleMethodGET(URI("/test"), httpRequest, toadletContext)
129 assertThat(capturedReply!!.code, equalTo(123))
130 assertThat(capturedReply!!.status, equalTo("Works"))
131 assertThat(capturedReply!!.mimeType, equalTo("data/test"))
132 assertThat(capturedReply!!.length, equalTo(7L))
133 assertThat(capturedReply!!.headers!!.getArray("Test"), arrayContaining<Any>("Value", "Another"))
134 assertThat(capturedReply!!.headers!!.getArray("More"), arrayContaining<Any>("true"))
135 assertThat(writtenData!!.toString(UTF_8), equalTo("Content"))
139 fun `link-enabled is true for non-callback pages`() {
140 val page = TestPage()
141 val pageToadlet = PageToadlet(highLevelSimpleClient, sessionManager, "MenuName", page, "/path/")
142 assertThat(pageToadlet.isEnabled(toadletContext), equalTo(true))
146 fun `link-enabled is passed through for callback pages`() {
147 var capturedToadletContext: ToadletContext? = null
148 val page = object : TestPage(), LinkEnabledCallback {
149 override fun isEnabled(ctx: ToadletContext?) = false.also { capturedToadletContext = toadletContext }
151 val pageToadlet = PageToadlet(highLevelSimpleClient, sessionManager, "MenuName", page, "/path/")
152 assertThat(pageToadlet.isEnabled(toadletContext), equalTo(false))
153 assertThat(capturedToadletContext, sameInstance(toadletContext))
157 fun `link excemption is false for non-freenet pages`() {
158 val page = TestPage()
159 val pageToadlet = PageToadlet(highLevelSimpleClient, sessionManager, "MenuName", page, "/path/")
160 assertThat(pageToadlet.isLinkExcepted(URI("/test")), equalTo(false))
164 fun `link excemption is passed through for freenet pages`() {
165 var capturedUri: URI? = null
166 val page = object : TestPage(), FreenetPage {
167 override fun isLinkExcepted(link: URI) = true.also { capturedUri = link }
169 val pageToadlet = PageToadlet(highLevelSimpleClient, sessionManager, "MenuName", page, "/path/")
170 assertThat(pageToadlet.isLinkExcepted(URI("/test")), equalTo(true))
171 assertThat(capturedUri, equalTo(URI("/test")))
175 fun `path is created correctly from prefix and page path`() {
176 val page = object : TestPage() {
177 override fun getPath() = "test-path"
179 val pageToadlet = PageToadlet(highLevelSimpleClient, sessionManager, "MenuName", page, "/path/")
180 assertThat(pageToadlet.path(), equalTo("/path/test-path"))
184 fun `menu name is returned correctly`() {
185 val pageToadlet = PageToadlet(highLevelSimpleClient, sessionManager, "MenuName", TestPage(), "/path/")
186 assertThat(pageToadlet.menuName, equalTo("MenuName"))
191 private data class CapturedReply(val code: Int, val status: String?, val headers: MultiValueTable<String, String>?, val mimeType: String?, val length: Long?)
193 private open class TestPage : Page<FreenetRequest> {
194 override fun getPath() = ""
195 override fun isPrefixPage() = false
196 override fun handleRequest(request: FreenetRequest, response: Response) = response
199 private open class DelegatingToadletContext(private val toadletContext: ToadletContext) : ToadletContext {
200 override fun activeToadlet(): Toadlet = toadletContext.activeToadlet()
201 override fun forceDisconnect() = toadletContext.forceDisconnect()
202 override fun sendReplyHeaders(code: Int, desc: String?, mvt: MultiValueTable<String, String>?, mimeType: String?, length: Long) = toadletContext.sendReplyHeaders(code, desc, mvt, mimeType, length)
203 override fun sendReplyHeaders(code: Int, desc: String?, mvt: MultiValueTable<String, String>?, mimeType: String?, length: Long, forceDisableJavascript: Boolean) = toadletContext.sendReplyHeaders(code, desc, mvt, mimeType, length, forceDisableJavascript)
204 override fun sendReplyHeaders(code: Int, desc: String?, mvt: MultiValueTable<String, String>?, mimeType: String?, length: Long, mTime: Date?) = toadletContext.sendReplyHeaders(code, desc, mvt, mimeType, length, mTime)
205 override fun getUri(): URI = toadletContext.uri
206 override fun getPageMaker(): PageMaker = toadletContext.pageMaker
207 override fun getBucketFactory(): BucketFactory = toadletContext.bucketFactory
208 override fun getHeaders(): MultiValueTable<String, String> = toadletContext.headers
209 override fun checkFullAccess(toadlet: Toadlet?): Boolean = toadletContext.checkFullAccess(toadlet)
210 override fun doRobots(): Boolean = toadletContext.doRobots()
211 override fun getReFilterPolicy(): REFILTER_POLICY = toadletContext.reFilterPolicy
212 override fun getAlertManager(): UserAlertManager = toadletContext.alertManager
213 override fun checkFormPassword(request: HTTPRequest?, redirectTo: String?): Boolean = toadletContext.checkFormPassword(request, redirectTo)
214 override fun checkFormPassword(request: HTTPRequest?): Boolean = toadletContext.checkFormPassword(request)
215 override fun addFormChild(parentNode: HTMLNode?, target: String?, id: String?): HTMLNode = toadletContext.addFormChild(parentNode, target, id)
216 override fun sendReplyHeadersFProxy(code: Int, desc: String?, mvt: MultiValueTable<String, String>?, mimeType: String?, length: Long) = toadletContext.sendReplyHeadersFProxy(code, desc, mvt, mimeType, length)
217 override fun setCookie(newCookie: Cookie?) = toadletContext.setCookie(newCookie)
218 override fun isAdvancedModeEnabled(): Boolean = toadletContext.isAdvancedModeEnabled
219 override fun disableProgressPage(): Boolean = toadletContext.disableProgressPage()
220 override fun writeData(data: ByteArray?, offset: Int, length: Int) = toadletContext.writeData(data, offset, length)
221 override fun writeData(data: ByteArray?) = toadletContext.writeData(data)
222 override fun writeData(data: Bucket?) = toadletContext.writeData(data)
223 override fun getCookie(domain: URI?, path: URI?, name: String?): ReceivedCookie? = toadletContext.getCookie(domain, path, name)
224 override fun getUniqueId(): String = toadletContext.uniqueId
225 override fun sendReplyHeadersStatic(code: Int, desc: String?, mvt: MultiValueTable<String, String>?, mimeType: String?, length: Long, mTime: Date?) = toadletContext.sendReplyHeadersStatic(code, desc, mvt, mimeType, length, mTime)
226 override fun getBookmarkManager(): BookmarkManager = toadletContext.bookmarkManager
227 override fun isAllowedFullAccess(): Boolean = toadletContext.isAllowedFullAccess
228 override fun hasFormPassword(request: HTTPRequest?): Boolean = toadletContext.hasFormPassword(request)
229 override fun getFormPassword(): String = toadletContext.formPassword
230 override fun getContainer(): ToadletContainer = toadletContext.container