diff --git a/lib/src/main/java/com/uwyn/urlencoder/UrlEncoder.java b/lib/src/main/java/com/uwyn/urlencoder/UrlEncoder.java index 3486188..3bb0a15 100644 --- a/lib/src/main/java/com/uwyn/urlencoder/UrlEncoder.java +++ b/lib/src/main/java/com/uwyn/urlencoder/UrlEncoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2001-2022 Geert Bevin (gbevin[remove] at uwyn dot com) + * Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com) * Licensed under the Apache License, Version 2.0 (the "License") */ package com.uwyn.urlencoder; @@ -167,7 +167,7 @@ public final class UrlEncoder { * @since 1.0 */ public static String encode(String source, String allow) { - if (source == null || source.isBlank()) { + if (source == null || source.isEmpty()) { return source; } @@ -246,7 +246,7 @@ public final class UrlEncoder { } var text = ""; - if (args.size() == 1) { + if (args.size() == 1 && !args.get(0).isEmpty()) { text = args.remove(0); valid_arguments = true; } diff --git a/lib/src/test/java/com/uwyn/urlencoder/UrlEncoderTest.java b/lib/src/test/java/com/uwyn/urlencoder/UrlEncoderTest.java index a095b35..2fec84f 100644 --- a/lib/src/test/java/com/uwyn/urlencoder/UrlEncoderTest.java +++ b/lib/src/test/java/com/uwyn/urlencoder/UrlEncoderTest.java @@ -1,137 +1,150 @@ /* - * Copyright 2001-2022 Geert Bevin (gbevin[remove] at uwyn dot com) + * Copyright 2001-2023 Geert Bevin (gbevin[remove] at uwyn dot com) * Licensed under the Apache License, Version 2.0 (the "License") */ package com.uwyn.urlencoder; 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.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; -import java.util.Map; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.params.provider.Arguments.arguments; class UrlEncoderTest { - private String[] invalid = {"sdkjfh%", "sdkjfh%6", "sdkjfh%xx", "sdfjfh%-1"}; - private String same = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_.~"; - private Map validMap = Map.of( - "a test &", "a%20test%20%26", - "!abcdefghijklmnopqrstuvwxyz%%ABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_.~=", - "%21abcdefghijklmnopqrstuvwxyz%25%25ABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_.~%3D", - "%#okékÉȢ smile!😁", "%25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81" - ); + private final String same = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVQXYZ0123456789-_.~"; + + private static Stream invalid() { + return Stream.of("sdkjfh%", "sdkjfh%6", "sdkjfh%xx", "sdfjfh%-1"); + } + + private static Stream validMap() { + return 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") + void testDecodeUrl(String expected, String source) { + assertEquals(expected, UrlEncoder.decode(source)); + } @Test - void testDecodeURL() { - assertNull(UrlEncoder.decode(null)); - assertSame("", UrlEncoder.decode("")); + void testDecodeNotNeeded() { assertSame(same, UrlEncoder.decode(same)); - validMap.forEach((expected, source) -> assertEquals(expected, UrlEncoder.decode(source))); + assertEquals("", UrlEncoder.decode(""), "decode('')"); + assertEquals(" ", UrlEncoder.decode(" "), "decode(' ')"); + } - for (String i : invalid) { - assertThrows(IllegalArgumentException.class, () -> UrlEncoder.decode(i)); - } + @ParameterizedTest(name = "decode({0})") + @MethodSource("invalid") + void testDecodeWithException(String source) { + assertThrows(IllegalArgumentException.class, () -> UrlEncoder.decode(source), "decode(" + source + ")"); } @Test - void testEncodeURL() { - assertNull(UrlEncoder.encode(null)); - assertTrue(UrlEncoder.encode("").isEmpty()); + void testDecodeWithNull() { + assertNull(UrlEncoder.decode(null), "decode(null)"); + } + + @Test + void testEncodeWhenNoneNeeded() { assertSame(same, UrlEncoder.encode(same)); - assertSame(same, UrlEncoder.encode(same, "")); - validMap.forEach((source, expected) -> assertEquals(expected, UrlEncoder.encode(source))); - - assertEquals("?test=a%20test", UrlEncoder.encode("?test=a test", "?=")); - assertEquals("?test=a%20test", UrlEncoder.encode("?test=a test", '?', '=')); - assertEquals("aaa", UrlEncoder.encode("aaa", 'a')); + assertSame(same, UrlEncoder.encode(same, ""), "with empty allow"); } @Test - void testMainNoArgs() { - var result = UrlEncoder.processMain(new String[0]); - assertEquals(1, result.status); - assertTrue(result.output.contains("Usage :")); + void testEncodeWithAllowArg() { + assertEquals("?test=a%20test", UrlEncoder.encode("?test=a test", '=', '?'), "encode(x, =, ?)"); + assertEquals("?test=a%20test", UrlEncoder.encode("?test=a test", "=?"), "encode(x, =?)"); + assertEquals("aaa", UrlEncoder.encode("aaa", 'a'), "encode(aaa, a)"); + assertEquals(" ", UrlEncoder.encode(" ", ' '), "encode(' ', ' ')"); + } + + @Test + void testEncodeWithEmptyOrBlank() { + assertTrue(UrlEncoder.encode("", "").isEmpty(), "encode('','')"); + assertEquals("", UrlEncoder.encode(""), "encode('')"); + assertEquals("%20", UrlEncoder.encode(" "), "encode('')"); + } + + @ParameterizedTest(name = "encode({0}) should be {1}") + @MethodSource("validMap") + void testEncodeUrl(String source, String expected) { + assertEquals(expected, UrlEncoder.encode(source)); + } + + @Test + void testEncodeWithNulls() { + assertNull(UrlEncoder.encode(null), "encode(null)"); + assertNull(UrlEncoder.encode(null, (String) null), "encode(null, null)"); + assertEquals("foo", UrlEncoder.encode("foo", (String) null), "encode(foo, null"); + } + + @ParameterizedTest(name = "processMain(-d {1}) should be {0}") + @MethodSource("validMap") + void testMainDecode(String expected, String source) { + var result = UrlEncoder.processMain(new String[]{"-d", source}); + assertEquals(expected, result.output); + assertEquals(0, result.status, "processMain(-d " + source + ").status"); + } + + @ParameterizedTest(name = "processMain(-e {0})") + @MethodSource("validMap") + void testMainEncode(String source, String expected) { + var result = UrlEncoder.processMain(new String[]{source}); + assertEquals(expected, result.output); + assertEquals(0, result.status, "processMain(-e " + source + ").status"); + } + + @ParameterizedTest(name = "processMain(-d {0})") + @MethodSource("invalid") + void testMainEncodeWithExceptions(String source) { + assertThrows(IllegalArgumentException.class, () -> UrlEncoder.processMain(new String[]{"-d", source}), source); } @Test void testMainTooManyArgs() { - var result = UrlEncoder.processMain(new String[] {"-x", "-g", "f"}); - assertEquals(1, result.status); - assertTrue(result.output.contains("Usage :")); + assertTrue(UrlEncoder.processMain(new String[]{"foo", "bar", "test"}).output.contains("Usage :"), "too many args"); } @Test - void testMainMissingEncodeText() { - var result = UrlEncoder.processMain(new String[] {"-e"}); - assertEquals(1, result.status); - assertTrue(result.output.contains("Usage :")); + void testMainWithEmptyArgs() { + assertTrue(UrlEncoder.processMain(new String[]{" ", " "}).output.contains("Usage :"), "processMain(' ', ' ')"); + assertTrue(UrlEncoder.processMain(new String[]{"foo", " "}).output.contains("Usage :"), "processMain('foo', ' ')"); + assertTrue(UrlEncoder.processMain(new String[]{" ", "foo"}).output.contains("Usage :"), "processMain(' ', 'foo')"); + assertTrue(UrlEncoder.processMain(new String[]{"-d ", ""}).output.contains("Usage :"), "processMain('-d', '')"); + assertEquals("%20", UrlEncoder.processMain(new String[]{"-e", " "}).output, "processMain('-e', ' ')"); + assertEquals(" ", UrlEncoder.processMain(new String[]{"-d", " "}).output, "processMain('-d', ' ')"); } - @Test - void testMainMissingDecodeText() { - var result = UrlEncoder.processMain(new String[] {"-d"}); - assertEquals(1, result.status); - assertTrue(result.output.contains("Usage :")); + @ParameterizedTest + @ValueSource(strings = {"", "-d", "-e"}) + void testMainWithInvalidArgs(String arg) { + var result = UrlEncoder.processMain(new String[]{arg}); + assertTrue(result.output.contains("Usage :"), "processMain('" + arg + "')"); + assertEquals(1, result.status, "processMain('" + arg + "').status"); } - @Test - void testMainWrongArgs1() { - var result = UrlEncoder.processMain(new String[] {"-p"}); - assertEquals(1, result.status); - assertTrue(result.output.contains("Usage :")); + @ParameterizedTest(name = "processMain(-e {0})") + @MethodSource("validMap") + void testMainWithOption(String source, String expected) { + var result = UrlEncoder.processMain(new String[]{"-e", source}); + assertEquals(expected, result.output); + assertEquals(0, result.status, "processMain(-e " + source + ").status"); } - - @Test - void testMainWrongArgs2() { - var result = UrlEncoder.processMain(new String[] {"-x", "txt"}); - assertEquals(1, result.status); - assertTrue(result.output.contains("Usage :")); - } - - @Test - void testMainWrongArgs3() { - var result = UrlEncoder.processMain(new String[] {"stuff", "txt"}); - assertEquals(1, result.status); - assertTrue(result.output.contains("Usage :")); - } - - @Test - void testMainWrongArgs4() { - var result = UrlEncoder.processMain(new String[] {"-d", "stuff", "txt"}); - assertEquals(1, result.status); - assertTrue(result.output.contains("Usage :")); - } - - @Test - void testMainWrongArgs5() { - var result = UrlEncoder.processMain(new String[] {"-e", "stuff", "txt"}); - assertEquals(1, result.status); - assertTrue(result.output.contains("Usage :")); - } - - @Test - void testDecodeMainOption() { - validMap.forEach((expected, source) -> { - var result = UrlEncoder.processMain(new String[] {"-d", source}); - assertEquals(0, result.status); - assertEquals(expected, result.output); - }); - } - - @Test - void testEncodeMainDefault() { - validMap.forEach((source, expected) -> { - var result = UrlEncoder.processMain(new String[] {source}); - assertEquals(0, result.status); - assertEquals(expected, result.output); - }); - } - - @Test - void testEncodeMainOption() { - validMap.forEach((source, expected) -> { - var result = UrlEncoder.processMain(new String[] {"-e", source}); - assertEquals(0, result.status); - assertEquals(expected, result.output); - }); - } -} +} \ No newline at end of file