blob: c48e619d87bfe95d741c65057cc273f26436eb07 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jmeter.services
import org.apache.jmeter.junit.JMeterTestCase
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertArrayEquals
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.fail
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource
import java.io.EOFException
import java.io.File
import java.io.IOException
class FileServerTest : JMeterTestCase() {
val sut = FileServer()
val testFile = getResourceFilePath("testfiles/unit/FileServerSpec.csv")
val emptyFile = getResourceFilePath("testfiles/empty.csv")
val bomFile = getResourceFilePath("testfiles/bomData.csv")
data class SetBaseForScriptCase(val file: File, val expectedBaseDirRelative: String)
companion object {
@JvmStatic
fun setBaseForScript(): List<SetBaseForScriptCase> {
val baseFile = File(FileServer.getDefaultBase())
return listOf(
SetBaseForScriptCase(baseFile, "."),
SetBaseForScriptCase(baseFile.getParentFile(), "."),
SetBaseForScriptCase(File(baseFile.getParentFile(), "abcd/defg.jmx"), "."),
SetBaseForScriptCase(File(baseFile, "abcd/defg.jmx"), "abcd"),
)
}
}
@BeforeEach
fun setup() {
sut.resetBase()
}
@AfterEach
fun tearDown() {
sut.closeFiles()
}
@Test
fun `reading a non-existent file throws an exception`() {
assertThrows<IOException> {
sut.readLine("test")
}
}
@Test
fun `writing to a non-exisent file throws an exception`() {
assertThrows<IOException> {
sut.write("test", "")
}
}
@Test
fun `no files should be open following resetBase`() {
assertNoFilesOpen()
}
@Test
fun `closing unrecognised files are ignored`() {
sut.closeFile("xxx")
assertNoFilesOpen()
}
@Test
fun `file is not opened until read from`() {
sut.reserveFile(testFile) // Does not open file
assertNoFilesOpen()
assertEquals("a1,b1,c1,d1", sut.readLine(testFile)) {
"readLine($testFile)"
}
assertFilesOpen()
}
private fun assertNoFilesOpen() {
assertFalse(sut.filesOpen(), "filesOpen")
}
private fun assertFilesOpen() {
assertTrue(sut.filesOpen(), "filesOpen")
}
@Test
fun `reading lines loops to start once last line is read`() {
sut.reserveFile(testFile)
val firstPass = Array(4) { sut.readLine(testFile) }
val secondPass = Array(4) { sut.readLine(testFile) }
assertArrayEquals(firstPass, secondPass)
}
@Test
fun `cannot write to reserved file after reading`() {
sut.reserveFile(testFile)
sut.readLine(testFile)
assertThrows<IOException> {
sut.write(testFile, "")
}
}
@Test
fun `closing reserved file after reading resets`() {
sut.reserveFile(testFile)
sut.readLine(testFile)
sut.closeFile(testFile) // does not remove the entry
assertNoFilesOpen()
assertEquals("a1,b1,c1,d1", sut.readLine(testFile), "re-read first line")
assertFilesOpen()
}
@Test
fun `closeFiles() prevents reading of reserved file`() {
sut.reserveFile(testFile)
sut.readLine(testFile)
sut.closeFiles() // removes all entries
assertThrows<IOException> {
sut.readLine(testFile)
}
assertNoFilesOpen()
}
@Test
fun `baseDir is the defaultBasedir`() {
assertEquals(FileServer.getDefaultBase(), sut.getBaseDir()) {
"getBaseDir should be FileServer.getDefaultBase()"
}
}
@Test
fun `setBaseDir doesn't error when no files are open`() {
sut.setBasedir("testfiles/unit/FileServerSpec.csv")
val result = sut.baseDir.replace("\\", "/")
if (!result.endsWith("testfiles/unit")) {
fail("baseDir should start with testfiles/unit, but was $result")
}
}
// TODO: what about throwing an exception in setBaseDir?
@Test
fun `setBaseDir doesn't set base when passed a directory`() {
val dir = "does-not-exist"
sut.setBasedir(dir)
assertThrows<NullPointerException> {
sut.baseDir.endsWith(dir)
}
}
@Test
fun `cannot set baseDir when files are open`() {
sut.reserveFile(testFile)
assertEquals("a1,b1,c1,d1", sut.readLine(testFile), "sut.readLine($testFile)")
assertThrows<IllegalStateException> {
sut.setBasedir("testfiles")
}
}
@ParameterizedTest
@MethodSource("setBaseForScript")
fun `setting base to #file gives getBaseDirRelative == #expectedBaseDirRelative`(case: SetBaseForScriptCase) {
sut.setBaseForScript(case.file)
assertEquals(case.expectedBaseDirRelative, sut.getBaseDirRelative().toString())
}
@Test
fun `non-existent filename to reserveFile will throw exception`() {
val missing = "no-such-file"
val alias = "missing"
val charsetName = "UTF-8"
val hasHeader = true
val ex = assertThrows<IllegalArgumentException> {
sut.reserveFile(missing, charsetName, alias, hasHeader)
}
assertEquals("Could not read file header line for file $missing", ex.message) {
"ex.message"
}
assertEquals("File $missing must exist and be readable", ex.cause?.message) {
"ex.cause?.message"
}
}
@Test
fun `reserving a file with no header will throw an exception if the header is expected`() {
val alias = "empty"
val charsetName = "UTF-8"
val e = assertThrows<IllegalArgumentException> {
sut.reserveFile(emptyFile, charsetName, alias, true)
}
if (e.cause !is EOFException) {
fail("reserveFile(emptyFile) should throw IllegalArgumentException(cause=EOFException), got cause=${e.cause}")
}
}
@Test
fun `resolvedFile returns absolute and relative files`() {
val testFile = File(emptyFile)
assertEquals(
testFile.getCanonicalFile(),
sut.getResolvedFile(testFile.absolutePath).getCanonicalFile(),
"sut.getResolvedFile(testFile.absolutePath)"
)
// relative
assertEquals(
testFile.getCanonicalFile(),
sut.getResolvedFile(testFile.getParentFile().path + "/../testfiles/empty.csv")
.getCanonicalFile(),
"sut.getResolvedFile(testFile.getParentFile().path + \"/../testfiles/empty.csv\")"
)
}
@Test
fun `resolvedFile returns relative files with BaseForScript set`() {
val testFile = File(emptyFile)
sut.setBaseForScript(testFile)
assertEquals(
testFile.getCanonicalFile(),
sut.getResolvedFile(testFile.getName()).getCanonicalFile()
) {
".getResolvedFile(${testFile.name}).getCanonicalFile()"
}
}
@Test
fun `skip bom at start of file and set correct encoding`() {
sut.reserveFile(bomFile)
val header = sut.readLine(bomFile)
assertEquals("\"äöü\"", header)
}
@Test
fun `fail to read a line from a directory`() {
val directory = File(bomFile).parent
sut.reserveFile(directory)
assertThrows<IllegalArgumentException> {
sut.readLine(directory)
}
}
}