Reorganize top level directory

This commit is contained in:
2021-01-03 14:43:49 -06:00
parent 9fd36d8d53
commit bebb356425
841 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2016-2020 Alinson Santos Xavier <git@axavier.org>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker 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.
*
* Loop Habit Tracker 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 org.isoron.uhabits.sync.app
import io.ktor.application.*
import org.isoron.uhabits.sync.server.*
import org.mockito.Mockito.*
open class BaseApplicationTest {
protected val server: AbstractSyncServer = mock(AbstractSyncServer::class.java)
protected fun app(): Application.() -> Unit = {
SyncApplication(server).apply {
main()
}
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2016-2020 Alinson Santos Xavier <git@axavier.org>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker 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.
*
* Loop Habit Tracker 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 org.isoron.uhabits.sync.app
import io.ktor.http.*
import io.ktor.server.testing.*
import kotlinx.coroutines.*
import org.isoron.uhabits.sync.*
import org.isoron.uhabits.sync.links.*
import org.junit.Test
import org.mockito.Mockito.*
import kotlin.test.*
class LinksModuleTest : BaseApplicationTest() {
private val link = Link(
id = "ABC123",
syncKey = "SECRET",
createdAt = System.currentTimeMillis(),
)
@Test
fun `when POST is successful should return link`(): Unit = runBlocking {
`when`(server.registerLink("SECRET")).thenReturn(link)
withTestApplication(app()) {
handlePost("/links", LinkRegisterRequestData(syncKey = "SECRET")).apply {
assertEquals(HttpStatusCode.OK, response.status())
assertEquals(link.toJson(), response.content)
}
}
}
@Test
fun `when GET is successful should return link`(): Unit = runBlocking {
`when`(server.getLink("ABC123")).thenReturn(link)
withTestApplication(app()) {
handleGet("/links/ABC123").apply {
assertEquals(HttpStatusCode.OK, response.status())
assertEquals(link.toJson(), response.content)
}
}
}
@Test
fun `GET with invalid link id should return 404`(): Unit = runBlocking {
`when`(server.getLink("ABC123")).thenThrow(KeyNotFoundException())
withTestApplication(app()) {
handleGet("/links/ABC123").apply {
assertEquals(HttpStatusCode.NotFound, response.status())
}
}
}
private fun TestApplicationEngine.handlePost(url: String, data: LinkRegisterRequestData): TestApplicationCall {
return handleRequest(HttpMethod.Post, url) {
addHeader(HttpHeaders.ContentType, ContentType.Application.Json.toString())
setBody(data.toJson())
}
}
private fun TestApplicationEngine.handleGet(url: String): TestApplicationCall {
return handleRequest(HttpMethod.Get, url)
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2016-2020 Alinson Santos Xavier <git@axavier.org>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker 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.
*
* Loop Habit Tracker 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 org.isoron.uhabits.sync.app
import io.ktor.http.*
import io.ktor.server.testing.*
import kotlinx.coroutines.*
import org.isoron.uhabits.sync.*
import org.junit.Test
import org.mockito.*
import org.mockito.Mockito.*
import kotlin.test.*
class RegistrationModuleTest : BaseApplicationTest() {
@Test
fun `when register succeeds should return generated key`():Unit = runBlocking {
`when`(server.register()).thenReturn("ABCDEF")
withTestApplication(app()) {
val call = handleRequest(HttpMethod.Post, "/register")
assertEquals(HttpStatusCode.OK, call.response.status())
assertEquals("{\"key\":\"ABCDEF\"}", call.response.content)
}
}
@Test
fun `when registration is unavailable should return 503`():Unit = runBlocking {
`when`(server.register()).thenThrow(ServiceUnavailable())
withTestApplication(app()) {
val call = handleRequest(HttpMethod.Post, "/register")
assertEquals(HttpStatusCode.ServiceUnavailable, call.response.status())
}
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2016-2020 Alinson Santos Xavier <git@axavier.org>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker 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.
*
* Loop Habit Tracker 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 org.isoron.uhabits.sync.app
import io.ktor.http.*
import io.ktor.server.testing.*
import kotlinx.coroutines.*
import org.isoron.uhabits.sync.*
import org.junit.Test
import org.mockito.Mockito.*
import kotlin.test.*
class StorageModuleTest : BaseApplicationTest() {
private val data1 = SyncData(1, "Hello world")
private val data2 = SyncData(2, "Hello new world")
@Test
fun `when get succeeds should return data`(): Unit = runBlocking {
`when`(server.getData("k1")).thenReturn(data1)
withTestApplication(app()) {
handleGet("/db/k1").apply {
assertEquals(HttpStatusCode.OK, response.status())
assertEquals(data1.toJson(), response.content)
}
}
}
@Test
fun `when get version succeeds should return version`(): Unit = runBlocking {
`when`(server.getDataVersion("k1")).thenReturn(30)
withTestApplication(app()) {
handleGet("/db/k1/version").apply {
assertEquals(HttpStatusCode.OK, response.status())
assertEquals(GetDataVersionResponse(30).toJson(), response.content)
}
}
}
@Test
fun `when get with invalid key should return 404`(): Unit = runBlocking {
`when`(server.getData("k1")).thenThrow(KeyNotFoundException())
withTestApplication(app()) {
handleGet("/db/k1").apply {
assertEquals(HttpStatusCode.NotFound, response.status())
}
}
}
@Test
fun `when put succeeds should return OK`(): Unit = runBlocking {
withTestApplication(app()) {
handlePut("/db/k1", data1).apply {
runBlocking {
assertEquals(HttpStatusCode.OK, response.status())
verify(server).put("k1", data1)
}
}
}
}
@Test
fun `when put with invalid key should return 404`(): Unit = runBlocking {
`when`(server.put("k1", data1)).thenThrow(KeyNotFoundException())
withTestApplication(app()) {
handlePut("/db/k1", data1).apply {
assertEquals(HttpStatusCode.NotFound, response.status())
}
}
}
@Test
fun `when put with invalid version should return 409 and current data`(): Unit = runBlocking {
`when`(server.put("k1", data1)).thenThrow(EditConflictException())
`when`(server.getData("k1")).thenReturn(data2)
withTestApplication(app()) {
handlePut("/db/k1", data1).apply {
assertEquals(HttpStatusCode.Conflict, response.status())
}
}
}
private fun TestApplicationEngine.handlePut(url: String, data: SyncData): TestApplicationCall {
return handleRequest(HttpMethod.Put, url) {
addHeader(HttpHeaders.ContentType, ContentType.Application.Json.toString())
setBody(data.toJson())
}
}
private fun TestApplicationEngine.handleGet(url: String): TestApplicationCall {
return handleRequest(HttpMethod.Get, url)
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2016-2020 Alinson Santos Xavier <git@axavier.org>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker 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.
*
* Loop Habit Tracker 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 org.isoron.uhabits.sync.links
import org.isoron.uhabits.sync.*
import org.junit.Test
import kotlin.test.*
class LinkManagerTest {
@Test
fun testUsage() {
val manager = LinkManager(timeoutInMillis = 250)
val originalLink = manager.register(syncKey = "SECRET")
val retrievedLink = manager.get(originalLink.id)
assertEquals(originalLink, retrievedLink)
Thread.sleep(260) // wait until expiration
assertFailsWith<KeyNotFoundException> {
manager.get(originalLink.id)
}
assertFailsWith<KeyNotFoundException> {
manager.get("INVALID")
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2016-2020 Alinson Santos Xavier <git@axavier.org>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker 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.
*
* Loop Habit Tracker 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/>.
*/
@file:Suppress("BlockingMethodInNonBlockingContext")
package org.isoron.uhabits.sync.repository
import kotlinx.coroutines.*
import org.hamcrest.CoreMatchers.*
import org.isoron.uhabits.sync.*
import org.junit.*
import org.junit.Assert.*
import java.nio.file.*
class FileRepositoryTest {
@Test
fun testUsage() = runBlocking {
val tempdir = Files.createTempDirectory("db")!!
val repo = FileRepository(tempdir)
val original = SyncData(10, "Hello world")
repo.put("abcdefg", original)
val metaPath = tempdir.resolve("a/b/c/d/abcdefg/version")
assertTrue("$metaPath should exist", Files.exists(metaPath))
assertEquals("10", metaPath.toFile().readText())
val dataPath = tempdir.resolve("a/b/c/d/abcdefg/content")
assertTrue("$dataPath should exist", Files.exists(dataPath))
assertEquals("Hello world", dataPath.toFile().readText())
val retrieved = repo.get("abcdefg")
assertThat(retrieved, equalTo(original))
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2016-2020 Alinson Santos Xavier <git@axavier.org>
*
* This file is part of Loop Habit Tracker.
*
* Loop Habit Tracker 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.
*
* Loop Habit Tracker 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 org.isoron.uhabits.sync.server
import kotlinx.coroutines.*
import org.isoron.uhabits.sync.*
import org.isoron.uhabits.sync.repository.*
import org.junit.Test
import java.nio.file.*
import kotlin.test.*
class RepositorySyncServerTest {
private val tempdir = Files.createTempDirectory("db")
private val server = RepositorySyncServer(FileRepository(tempdir))
private val key = runBlocking { server.register() }
@Test
fun testUsage(): Unit = runBlocking {
val data0 = SyncData(0, "")
assertEquals(server.getData(key), data0)
val data1 = SyncData(1, "Hello world")
server.put(key, data1)
assertEquals(server.getData(key), data1)
val data2 = SyncData(2, "Hello new world")
server.put(key, data2)
assertEquals(server.getData(key), data2)
assertFailsWith<EditConflictException> {
server.put(key, data2)
}
assertFailsWith<KeyNotFoundException> {
server.getData("INVALID")
}
assertFailsWith<KeyNotFoundException> {
server.put("INVALID", data0)
}
}
}