Added parameterized tests

This commit is contained in:
Erik C. Thauvin 2023-01-01 23:05:17 -08:00
parent 59d53ebe01
commit 5f84e96b11
4 changed files with 132 additions and 81 deletions

View file

@ -26,7 +26,7 @@ val deployDir = "deploy"
val gitHub = "ethauvin/${rootProject.name}"
val mavenUrl = "https://github.com/$gitHub"
val publicationName = "mavenJava"
val myClassName = "net.thauvin.erik.urlencoder.UrlEncoder"
val myClassName = "$group.${rootProject.name}.$mavenName"
repositories {
mavenCentral()
@ -34,7 +34,8 @@ repositories {
}
dependencies {
testImplementation(kotlin("test"))
// testImplementation("com.willowtreeapps.assertk:assertk-jvm:0.25")
testImplementation("org.junit.jupiter:junit-jupiter:5.9.0")
}
base {
@ -79,6 +80,10 @@ tasks {
kotlinOptions.jvmTarget = java.targetCompatibility.toString()
}
test {
useJUnitPlatform()
}
withType<Test> {
testLogging {
exceptionFormat = TestExceptionFormat.FULL

View file

@ -2,6 +2,7 @@
<SmellBaseline>
<ManuallySuppressedIssues/>
<CurrentIssues>
<ID>ComplexCondition:UrlEncoder.kt$UrlEncoder$hasOption &amp;&amp; args.size == 2 || !hasOption &amp;&amp; args.size == 1</ID>
<ID>MagicNumber:UrlEncoder.kt$UrlEncoder$0x80</ID>
<ID>MagicNumber:UrlEncoder.kt$UrlEncoder$0xFF</ID>
<ID>MagicNumber:UrlEncoder.kt$UrlEncoder$16</ID>

View file

@ -1,6 +1,6 @@
/*
* Copyright 2001-2022 Geert Bevin (gbevin[remove] at uwyn dot com)
* Copyright 2022 Erik C. Thauvin (erik@thauvin.net)
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
* Copyright 2023 Erik C. Thauvin (erik@thauvin.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -134,10 +134,9 @@ object UrlEncoder {
*/
@JvmStatic
fun encode(source: String, allow: String): String {
if (source.isBlank()) {
if (source.isEmpty()) {
return source
}
var out: StringBuilder? = null
var ch: Char
var i = 0
@ -145,6 +144,7 @@ object UrlEncoder {
ch = source[i]
if (ch.isUnreserved() || allow.indexOf(ch) != -1) {
out?.append(ch)
println(out)
i++
} else {
if (out == null) {
@ -205,10 +205,10 @@ object UrlEncoder {
internal fun processMain(args: Array<String>): MainResult {
val result = MainResult()
if (args.isNotEmpty() && args[0].isNotBlank() && args.size <= 2) {
val hasDecode = args[0] == "-d"
val hasOption = hasDecode || args[0] == "-e"
if (!hasOption || args.size == 2) {
if (args.isNotEmpty() && args[0].isNotEmpty()) {
val hasDecode = (args[0] == "-d")
val hasOption = (hasDecode || args[0] == "-e")
if (hasOption && args.size == 2 || !hasOption && args.size == 1) {
val arg = if (hasOption) args[1] else args[0]
if (hasDecode) {
result.output = decode(arg)

View file

@ -1,6 +1,6 @@
/*
* Copyright 2001-2022 Geert Bevin (gbevin[remove] at uwyn dot com)
* Copyright 2022 Erik C. Thauvin (erik@thauvin.net)
* Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com)
* Copyright 2023 Erik C. Thauvin (erik@thauvin.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,91 +21,136 @@ import net.thauvin.erik.urlencoder.UrlEncoder.decode
import net.thauvin.erik.urlencoder.UrlEncoder.encode
import net.thauvin.erik.urlencoder.UrlEncoder.processMain
import net.thauvin.erik.urlencoder.UrlEncoder.usage
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertSame
import kotlin.test.assertTrue
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertSame
import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.Arguments.arguments
import org.junit.jupiter.params.provider.MethodSource
import org.junit.jupiter.params.provider.ValueSource
import java.util.stream.Stream
class UrlEncoderTest {
private val invalid = arrayOf("sdkjfh%", "sdkjfh%6", "sdkjfh%xx", "sdfjfh%-1")
private val same = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_.~"
private val validMap = mapOf(
"a test &" to "a%20test%20%26",
"!abcdefghijklmnopqrstuvwxyz%%ABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_.~=" to
"%21abcdefghijklmnopqrstuvwxyz%25%25ABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_.~%3D",
"%#okékÉȢ smile!😁" to "%25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81"
)
companion object {
@JvmStatic
fun invalid() = arrayOf("sdkjfh%", "sdkjfh%6", "sdkjfh%xx", "sdfjfh%-1")
@JvmStatic
fun validMap(): Stream<Arguments> = Stream.of(
arguments("a test &", "a%20test%20%26"),
arguments(
"!abcdefghijklmnopqrstuvwxyz%%ABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_.~=",
"%21abcdefghijklmnopqrstuvwxyz%25%25ABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_.~%3D"
),
arguments("%#okékÉȢ smile!😁", "%25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81"),
arguments(
"\uD808\uDC00\uD809\uDD00\uD808\uDF00\uD808\uDD00", "%F0%92%80%80%F0%92%94%80%F0%92%8C%80%F0%92%84%80"
)
)
}
@ParameterizedTest(name = "decode({0}) should be {1}")
@MethodSource("validMap")
fun `Decode Multiple URLs`(expected: String, source: String) {
assertEquals(expected, decode(source))
}
@ParameterizedTest(name = "decode({0})")
@MethodSource("invalid")
fun `Decode with Exceptions`(source: String) {
assertThrows(IllegalArgumentException::class.java, { decode(source) }, "decode($source)")
}
@Test
fun testDecode() {
assertEquals("", decode(""))
fun `Decode when none needed`() {
assertSame(same, decode(same))
validMap.forEach {
assertEquals(it.key, decode(it.value))
}
invalid.forEach {
assertFailsWith<IllegalArgumentException>(
message = it,
block = { decode(it) }
)
}
assertEquals("", decode(""), "decode('')")
assertEquals(" ", decode(" "), "decode(' ')")
}
@ParameterizedTest(name = "encode({0}) should be {1}")
@MethodSource("validMap")
fun `Encode Multiple URLs`(source: String, expected: String) {
assertEquals(expected, encode(source))
}
@Test
fun testEncode() {
assertEquals("", encode(""))
fun `Encode Empty or Blank`() {
assertTrue(encode("", "").isEmpty(), "encode('','')")
assertEquals("", encode(""), "encode('')")
assertEquals("%20", encode(" "), "encode('')")
}
@Test
fun `Encode when none needed`() {
assertSame(same, encode(same))
assertSame(same, encode(same, ""))
assertTrue(encode("").isEmpty())
validMap.forEach {
assertEquals(it.value, encode(it.key))
}
assertEquals("?test=a%20test", encode("?test=a test", '=', '?'))
assertEquals("?test=a%20test", encode("?test=a test", "=?"))
assertEquals("aaa", encode("aaa", 'a'))
assertSame(same, encode(same, ""), "with empty allow")
}
@Test
fun testMainDecode() {
var result: UrlEncoder.MainResult
validMap.forEach {
result = processMain(arrayOf("-d", it.value))
assertEquals(result.output, it.key, it.key)
assertEquals(result.status, 0, it.key)
}
fun `Encode with allow arg`() {
assertEquals("?test=a%20test", encode("?test=a test", '=', '?'), "encode(x, =, ?)")
assertEquals("?test=a%20test", encode("?test=a test", "=?"), "encode(x, =?)")
assertEquals("aaa", encode("aaa", 'a'), "encode(aaa, a)")
assertEquals(" ", encode(" ", ' '), "encode(' ', ' ')")
}
@ParameterizedTest(name = "processMain(-d {1}) should be {0}")
@MethodSource("validMap")
fun `Main Decode`(expected: String, source: String) {
val result: UrlEncoder.MainResult = processMain(arrayOf("-d", source))
assertEquals(expected, result.output)
assertEquals(0, result.status, "processMain(-d $source).status")
}
@ParameterizedTest(name = "processMain(-d {0})")
@MethodSource("invalid")
fun `Main Decode with Exceptions`(source: String) {
assertThrows(IllegalArgumentException::class.java, { processMain(arrayOf("-d", source)) }, source)
}
@ParameterizedTest(name = "processMain(-e {0})")
@MethodSource("validMap")
fun `Main Encode`(source: String, expected: String) {
val result = processMain(arrayOf(source))
assertEquals(expected, result.output)
assertEquals(0, result.status, "processMain(-e $source).status")
}
@ParameterizedTest(name = "processMain(-e {0})")
@MethodSource("validMap")
fun `Main Encode with option`(source: String, expected: String) {
val result = processMain(arrayOf("-e", source))
assertEquals(expected, result.output)
assertEquals(0, result.status, "processMain(-e $source).status")
}
@Test
fun `Main Usage with Empty args`() {
assertEquals(usage, processMain(arrayOf(" ", " ")).output, "processMain(' ', ' ')")
assertEquals(usage, processMain(arrayOf("foo", " ")).output, "processMain('foo', ' ')")
assertEquals(usage, processMain(arrayOf(" ", "foo")).output, "processMain(' ', 'foo')")
assertEquals(usage, processMain(arrayOf("-d ", "")).output, "processMain('-d', '')")
assertEquals("%20", processMain(arrayOf("-e", " ")).output, "processMain('-e', ' ')")
assertEquals(" ", processMain(arrayOf("-d", " ")).output, "processMain('-d', ' ')")
}
@ParameterizedTest
@ValueSource(strings = ["", "-d", "-e"])
fun `Main Usage with invalid arg`(arg: String) {
val result = processMain(arrayOf(arg))
assertEquals(usage, result.output, "processMain('$arg')")
assertEquals(1, result.status, "processMain('$arg').status")
}
@Test
fun testMainEncode() {
var result: UrlEncoder.MainResult
validMap.forEach {
result = processMain(arrayOf("-e", it.key))
assertEquals(it.value, result.output, "-e ${it.key}")
assertEquals(0, result.status, "-e ${it.key}")
result = processMain(arrayOf(it.key))
assertEquals(it.value, result.output, it.value)
assertEquals(0, result.status, it.value)
}
invalid.forEach {
assertFailsWith<IllegalArgumentException>(
message = it,
block = { processMain(arrayOf("-d", it)) }
)
}
}
@Test
fun testMainUsage() {
var result: UrlEncoder.MainResult
fun `Main Usage with too many args`() {
assertEquals(usage, processMain(arrayOf("foo", "bar", "test")).output, "too many args")
for (arg in arrayOf("", " ", "-d", "-e")) {
result = processMain(arrayOf(arg))
assertEquals(usage, result.output, "processMain('$arg')")
assertEquals(1, result.status, "processMain('$arg')")
}
}
}