Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pivotal ID # 181937926: Avoid restarting ITests containers #560

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.EnumSource
import uk.ac.ebi.biostd.client.cli.dto.DeletionRequest
import uk.ac.ebi.biostd.client.cli.dto.SubmissionRequest
import uk.ac.ebi.biostd.client.cli.dto.ValidateFileListRequest
Expand All @@ -37,9 +35,8 @@ internal class SubmissionServiceTest {
@BeforeEach
fun beforeEach() = mockkObject(SecurityWebClient)

@ParameterizedTest
@EnumSource(FileMode::class)
fun submit(fileMode: FileMode) {
@Test
fun submit() {
val slot = slot<FileMode>()
every { create(SERVER).getAuthenticatedClient(USER, PASSWORD, ON_BEHALF) } returns bioWebClient
every {
Expand All @@ -55,8 +52,7 @@ internal class SubmissionServiceTest {
}
}

@ParameterizedTest
@EnumSource(FileMode::class)
@Test
fun `submit async`() {
val slot = slot<FileMode>()
every { create(SERVER).getAuthenticatedClient(USER, PASSWORD, ON_BEHALF) } returns bioWebClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ internal class SubmissionClient(
template.postForEntity<Void>("$SUBMISSIONS_URL/fileLists/validate", HttpEntity(body, headers))
}


private fun submitSingle(request: HttpEntity<String>, register: RegisterConfig): SubmissionResponse {
return template
.postForEntity<String>(buildUrl(register), request)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
@file:Suppress("TooManyFunctions")

package ebi.ac.uk.io.ext

import ebi.ac.uk.io.FileUtils
import java.io.File
import java.io.FileOutputStream
import java.nio.charset.Charset
import java.nio.file.Files
import java.util.zip.GZIPOutputStream

Expand Down Expand Up @@ -39,3 +42,28 @@ fun File.resolveMany(vararg keys: String): File {
fun File.gZipTo(target: File) {
FileOutputStream(target).use { GZIPOutputStream(it).bufferedWriter().use { writer -> writer.write(readText()) } }
}

/**
* Creates a file with the given content in the temporary folder.
*/
fun File.createFile(fileName: String, content: String, charset: Charset = Charsets.UTF_8): File {
val file = createNewFile(fileName)
file.writeText(content, charset)
return file
}

/**
* Creates a file with the given content in the temporary folder.
*/
fun File.createFile(fileName: String): File {
return createNewFile(fileName)
}

/**
* Creates a file with the given name or replaces it if already exist.
*/
fun File.createOrReplaceFile(fileName: String): File {
val file = resolve(fileName)
if (file.exists()) file.delete()
return createNewFile(fileName)
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
org.gradle.parallel=false
org.gradle.jvmargs=-Xmx2g
org.gradle.jvmargs=-Xmx4g
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ interface UserGroupDataRepository : JpaRepository<DbUserGroup, Long> {
}

interface AccessPermissionRepository : JpaRepository<DbAccessPermission, Long> {
fun findAllByUserEmail(email: String): List<DbAccessPermission>
fun findAllByUserEmailAndAccessType(email: String, accessType: AccessType): List<DbAccessPermission>
fun existsByUserEmailAndAccessTypeAndAccessTagName(user: String, type: AccessType, accessTag: String): Boolean
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import ac.uk.ebi.biostd.itest.factory.assertAllInOneSubmissionXml
import ac.uk.ebi.biostd.persistence.common.service.SubmissionQueryService
import arrow.core.Either
import ebi.ac.uk.extended.mapping.to.ToSubmissionMapper
import ebi.ac.uk.extended.model.FireFile
import ebi.ac.uk.extended.model.NfsFile
import ebi.ac.uk.extended.model.ExtProcessingStatus
import ebi.ac.uk.extended.model.ExtSubmission
import ebi.ac.uk.extended.model.ExtSubmissionMethod
import ebi.ac.uk.extended.model.FireFile
import ebi.ac.uk.extended.model.NfsFile
import ebi.ac.uk.extended.model.createNfsFile
import ebi.ac.uk.io.ext.md5
import ebi.ac.uk.io.ext.size
Expand All @@ -22,7 +22,7 @@ import java.io.File
import java.nio.file.Paths

internal class AllInOneSubmissionHelper(
private val submissionPath: String,
private val submissionPath: File,
private val submissionRepository: SubmissionQueryService,
private val toSubmissionMapper: ToSubmissionMapper
) {
Expand All @@ -40,7 +40,7 @@ internal class AllInOneSubmissionHelper(
}

private fun assertSubmissionFiles(submission: ExtSubmission) {
val submissionFolderPath = "$submissionPath/${submission.relPath}"
val submissionFolderPath = submissionPath.resolve(submission.relPath)
val accNo = submission.accNo

assertAllInOneSubmissionXml(getSubFileContent("$submissionFolderPath/$accNo.xml"), accNo)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ import uk.ac.ebi.fire.client.api.FIRE_OBJECTS_URL
import java.nio.file.Paths
import java.time.Duration.ofSeconds

private const val CHARACTER_SET = "utf8mb4"
private const val COLLATION = "utf8mb4_unicode_ci"
private const val FIRE_USERNAME = "fireUsername"
private const val FIRE_PASSWORD = "firePassword"
const val CHARACTER_SET = "utf8mb4"
const val COLLATION = "utf8mb4_unicode_ci"
const val FIRE_USERNAME = "fireUsername"
const val FIRE_PASSWORD = "firePassword"

internal open class BaseIntegrationTest(private val tempFolder: TemporaryFolder) {
private val mongoContainer: MongoDBContainer = MongoDBContainer(DockerImageName.parse(MONGO_VERSION))
Expand Down Expand Up @@ -126,4 +126,4 @@ internal open class BaseIntegrationTest(private val tempFolder: TemporaryFolder)
}
}

internal class SpecificMySQLContainer(image: String) : MySQLContainer<SpecificMySQLContainer>(image)
class SpecificMySQLContainer(image: String) : MySQLContainer<SpecificMySQLContainer>(image)
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class SecurityTestService(
private val groupService: IGroupService
) {

fun registerUser(testUser: TestUser): SecurityUser {
private fun registerUser(testUser: TestUser): SecurityUser {
val user = securityService.registerUser(testUser.asRegisterRequest())
if (testUser.superUser) {
val dbUser = userDataRepository.getByEmail(user.email)
Expand All @@ -26,6 +26,10 @@ class SecurityTestService(
return user
}

fun ensureRegisterUser(testUser: TestUser) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest ensureUserRegistration

if (userDataRepository.existsByEmail(testUser.email).not()) registerUser(testUser)
}

fun createTestGroup(): DbUserGroup {
return groupService.createGroup(TestGroup.testGroupName, TestGroup.testGroupDescription)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package ac.uk.ebi.biostd.itest.entities

import ebi.ac.uk.api.security.RegisterRequest

/**
* Represents a bio studies super user.
*/
Expand All @@ -10,6 +8,4 @@ object SuperUser : TestUser {
override val email = "biostudies-mgmt@ebi.ac.uk"
override val password = "12345"
override val superUser = true

override fun asRegisterRequest() = RegisterRequest(username, email, password)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ interface TestUser {
val password: String
val superUser: Boolean

fun asRegisterRequest(): RegisterRequest
fun asRegisterRequest(): RegisterRequest = RegisterRequest(username, email, password)
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package ac.uk.ebi.biostd.itest.factory

import ebi.ac.uk.base.EMPTY
import ebi.ac.uk.test.createOrReplaceFile
import io.github.glytching.junit.extension.folder.TemporaryFolder
import ebi.ac.uk.io.ext.createOrReplaceFile
import java.io.File

data class SubmissionSpec(
Expand All @@ -14,7 +13,7 @@ data class SubmissionSpec(

data class SubmissionFile(val file: File, val folder: String = EMPTY)

fun submissionsFiles(tempFolder: TemporaryFolder): List<SubmissionFile> = listOf(
fun submissionsFiles(tempFolder: File): List<SubmissionFile> = listOf(
SubmissionFile(tempFolder.createOrReplaceFile("DataFile1.txt")),
SubmissionFile(tempFolder.createOrReplaceFile("DataFile2.txt")),
SubmissionFile(tempFolder.createOrReplaceFile("DataFile3.txt"), "Folder1"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package ac.uk.ebi.biostd.itest.factory

import ebi.ac.uk.dsl.json.jsonArray
import ebi.ac.uk.dsl.json.jsonObj
import ebi.ac.uk.test.createFile
import io.github.glytching.junit.extension.folder.TemporaryFolder
import ebi.ac.uk.io.ext.createFile
import java.io.File

fun submissionSpecJson(tempFolder: TemporaryFolder, accNo: String): SubmissionSpec = SubmissionSpec(
fun submissionSpecJson(tempFolder: File, accNo: String): SubmissionSpec = SubmissionSpec(
submission = tempFolder.createFile("submission.json", allInOneSubmissionJson(accNo).toString()),
fileList = tempFolder.createFile("file-list.json", fileList().toString()),
files = submissionsFiles(tempFolder),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package ac.uk.ebi.biostd.itest.factory

import ebi.ac.uk.dsl.tsv.line
import ebi.ac.uk.dsl.tsv.tsv
import ebi.ac.uk.test.createFile
import io.github.glytching.junit.extension.folder.TemporaryFolder
import ebi.ac.uk.io.ext.createFile
import java.io.File

fun submissionSpecTsv(tempFolder: TemporaryFolder, accNo: String): SubmissionSpec = SubmissionSpec(
fun submissionSpecTsv(tempFolder: File, accNo: String): SubmissionSpec = SubmissionSpec(
submission = tempFolder.createFile("submission.tsv", allInOneSubmissionTsv(accNo).toString()),
fileList = tempFolder.createFile("file-list.tsv", fileList().toString()),
files = submissionsFiles(tempFolder),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package ac.uk.ebi.biostd.itest.factory

import ebi.ac.uk.test.createFile
import io.github.glytching.junit.extension.folder.TemporaryFolder
import ebi.ac.uk.io.ext.createFile
import org.redundent.kotlin.xml.xml
import java.io.File

fun submissionSpecXml(tempFolder: TemporaryFolder, accNo: String): SubmissionSpec = SubmissionSpec(
fun submissionSpecXml(tempFolder: File, accNo: String): SubmissionSpec = SubmissionSpec(
submission = tempFolder.createFile("submission.xml", allInOneSubmissionXml(accNo).toString()),
fileList = tempFolder.createFile("file-list.xml", fileList().toString()),
files = submissionsFiles(tempFolder),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package ac.uk.ebi.biostd.itest.itest

import ac.uk.ebi.biostd.itest.common.CHARACTER_SET
import ac.uk.ebi.biostd.itest.common.COLLATION
import ac.uk.ebi.biostd.itest.common.FIRE_PASSWORD
import ac.uk.ebi.biostd.itest.common.FIRE_USERNAME
import ac.uk.ebi.biostd.itest.common.SpecificMySQLContainer
import ac.uk.ebi.biostd.itest.wiremock.TestWireMockTransformer
import ac.uk.ebi.biostd.itest.wiremock.TestWireMockTransformer.Companion.newTransformer
import com.github.tomakehurst.wiremock.WireMockServer
import com.github.tomakehurst.wiremock.client.WireMock
import com.github.tomakehurst.wiremock.client.WireMock.post
import com.github.tomakehurst.wiremock.core.WireMockConfiguration
import ebi.ac.uk.db.MINIMUM_RUNNING_TIME
import ebi.ac.uk.db.MONGO_VERSION
import ebi.ac.uk.db.MYSQL_VERSION
import org.junit.platform.launcher.TestExecutionListener
import org.junit.platform.launcher.TestPlan
import org.testcontainers.containers.MongoDBContainer
import org.testcontainers.containers.startupcheck.MinimumDurationRunningStartupCheckStrategy
import org.testcontainers.utility.DockerImageName.parse
import uk.ac.ebi.fire.client.api.FIRE_OBJECTS_URL
import java.io.File
import java.nio.file.Files
import java.time.Duration.ofSeconds

class ITestListener : TestExecutionListener {

override fun testPlanExecutionStarted(testPlan: TestPlan) {
mongoSetup()
mySqlSetup()
fireSetup()
appPropertiesSetup()
}

override fun testPlanExecutionFinished(testPlan: TestPlan) {
mongoContainer.stop()
mysqlContainer.stop()
fireApiMock.stop()
}

private fun mongoSetup() {
mongoContainer.start()
System.setProperty("spring.data.mongodb.uri", mongoContainer.getReplicaSetUrl("biostudies-test"))
System.setProperty("spring.data.mongodb.database", "biostudies-test")
}

private fun mySqlSetup() {
mysqlContainer.start()
System.setProperty("spring.datasource.url", mysqlContainer.jdbcUrl)
System.setProperty("spring.datasource.username", mysqlContainer.username)
System.setProperty("spring.datasource.password", mysqlContainer.password)
}

private fun fireSetup() {
fireApiMock.stubFor(
post(WireMock.urlMatching(FIRE_OBJECTS_URL))
.withBasicAuth(FIRE_USERNAME, FIRE_PASSWORD)
.willReturn(WireMock.aResponse().withTransformers(TestWireMockTransformer.name))
)
fireApiMock.start()

System.setProperty("app.fire.host", fireApiMock.baseUrl())
System.setProperty("app.fire.username", FIRE_USERNAME)
System.setProperty("app.fire.password", FIRE_PASSWORD)
}

private fun appPropertiesSetup() {
System.setProperty("app.submissionPath", submissionPath.absolutePath)
System.setProperty("app.ftpPath", ftpPath.absolutePath)
System.setProperty("app.fireTempDirPath", fireTempFolder.absolutePath)
System.setProperty("app.tempDirPath", tempDirPath.absolutePath)
System.setProperty("app.requestFilesPath", requestFilesPath.absolutePath)
System.setProperty("app.security.filesDirPath", dropboxPath.absolutePath)
System.setProperty("app.security.magicDirPath", magicDirPath.absolutePath)
System.setProperty("app.persistence.enableFire", "${System.getProperty("enableFire").toBoolean()}")
}

companion object {
private val testAppFolder = Files.createTempDirectory("test-app-folder").toFile()

internal val submissionPath = testAppFolder.createDirectory("submission")
internal val firePath = testAppFolder.createDirectory("fire-db")
internal val fireTempFolder = testAppFolder.createDirectory("fire-temp")
internal val ftpPath = testAppFolder.createDirectory("ftpPath")
internal val tempDirPath = testAppFolder.createDirectory("tempDirPath")
internal val tempFolder = testAppFolder.createDirectory("testTempDir")
internal val requestFilesPath = testAppFolder.createDirectory("requestFilesPath")
internal val magicDirPath = testAppFolder.createDirectory("magic")
internal val dropboxPath = testAppFolder.createDirectory("dropbox")

private val mongoContainer = createMongoContainer(MONGO_VERSION)
private val mysqlContainer = createMysqlContainer(MYSQL_VERSION, "Schema.sql")
private val fireApiMock = createFireApiMock(submissionPath, ftpPath, firePath)

val enableFire get() = System.getProperty("enableFire").toBoolean()

private fun createMongoContainer(version: String): MongoDBContainer =
MongoDBContainer(parse(version))
.withStartupCheckStrategy(MinimumDurationRunningStartupCheckStrategy(ofSeconds(MINIMUM_RUNNING_TIME)))

private fun createMysqlContainer(version: String, schema: String): SpecificMySQLContainer =
SpecificMySQLContainer(version)
.withCommand("mysqld --character-set-server=$CHARACTER_SET --collation-server=$COLLATION")
.withInitScript(schema)
.withStartupCheckStrategy(MinimumDurationRunningStartupCheckStrategy(ofSeconds(MINIMUM_RUNNING_TIME)))

private fun createFireApiMock(submissionDir: File, ftpDir: File, fireDir: File): WireMockServer {
val wireMockTransformer = newTransformer(submissionDir.toPath(), ftpDir.toPath(), fireDir.toPath())
return WireMockServer(WireMockConfiguration().dynamicPort().extensions(wireMockTransformer))
}

private fun File.createDirectory(path: String): File {
val file = resolve(path)
file.mkdir()
return file
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ac.uk.ebi.biostd.itest.itest

import ac.uk.ebi.biostd.client.integration.web.BioWebClient
import ac.uk.ebi.biostd.client.integration.web.SecurityWebClient
import ac.uk.ebi.biostd.itest.entities.TestUser

fun getWebClient(serverPort: Int, user: TestUser): BioWebClient {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one-liner

fun getWebClient(serverPort: Int, user: TestUser): BioWebClient =
    SecurityWebClient
        .create("http://localhost:$serverPort")
        .getAuthenticatedClient(user.email, user.password)

val securityClient = SecurityWebClient.create("http://localhost:$serverPort")
return securityClient.getAuthenticatedClient(user.email, user.password)
}
Loading