From ac52f38867ecdbecce564e324f89cdf88069ef17 Mon Sep 17 00:00:00 2001 From: 51-code <146736881+51-code@users.noreply.github.com> Date: Mon, 18 Nov 2024 14:10:19 +0200 Subject: [PATCH] Support command line arguments as a configuration (#22) Remove unnecessary code in test Support command line arguments as a configuration source --- .../teragrep/cnf_01/ArgsConfiguration.java | 116 ++++++++++++ .../cnf_01/ConfigurationException.java | 4 + .../cnf_01/ArgsConfigurationTest.java | 167 ++++++++++++++++++ 3 files changed, 287 insertions(+) create mode 100644 src/main/java/com/teragrep/cnf_01/ArgsConfiguration.java create mode 100644 src/test/java/com/teragrep/cnf_01/ArgsConfigurationTest.java diff --git a/src/main/java/com/teragrep/cnf_01/ArgsConfiguration.java b/src/main/java/com/teragrep/cnf_01/ArgsConfiguration.java new file mode 100644 index 0000000..050523d --- /dev/null +++ b/src/main/java/com/teragrep/cnf_01/ArgsConfiguration.java @@ -0,0 +1,116 @@ +/* + * Teragrep Configuration Library for Java (cnf_01) + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.cnf_01; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public final class ArgsConfiguration implements Configuration { + + private static final Logger LOGGER = LoggerFactory.getLogger(ArgsConfiguration.class); + + private final String[] args; + + public ArgsConfiguration(final String[] args) { + this.args = Arrays.copyOf(args, args.length); + } + + /** + * Produces a Map of configurations from the args. + * + * @return immutable map of the args + * @throws ConfigurationException If the args are not given in the format of this regex: ([a-z]+)(=.+) + */ + @Override + public Map asMap() throws ConfigurationException { + final Map map = new HashMap<>(); + + if (args.length != 0) { + final Pattern ptn = Pattern.compile("([a-z]+)(=.+)"); + for (final String arg : args) { + final Matcher matcher = ptn.matcher(arg); + if (!matcher.matches()) { + throw new ConfigurationException( + String + .format( + "Can't parse argument '%s'. Args have to be given in \"key=value\" format.", + arg + ) + ); + } + map.put(matcher.group(1), matcher.group(2).substring(1)); + } + } + LOGGER.debug("Returning configuration map generated from command-line arguments."); + LOGGER.trace("Returning configuration map <[{}]>", map); + + return Collections.unmodifiableMap(map); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + else if (o == null || getClass() != o.getClass()) { + return false; + } + final ArgsConfiguration config = (ArgsConfiguration) o; + return Arrays.equals(args, config.args); + } + + @Override + public int hashCode() { + return Arrays.hashCode(args); + } +} diff --git a/src/main/java/com/teragrep/cnf_01/ConfigurationException.java b/src/main/java/com/teragrep/cnf_01/ConfigurationException.java index 023f333..0dd82c4 100644 --- a/src/main/java/com/teragrep/cnf_01/ConfigurationException.java +++ b/src/main/java/com/teragrep/cnf_01/ConfigurationException.java @@ -50,4 +50,8 @@ public final class ConfigurationException extends Exception { public ConfigurationException(final String message, final Throwable cause) { super(message, cause); } + + public ConfigurationException(final String message) { + super(message); + } } diff --git a/src/test/java/com/teragrep/cnf_01/ArgsConfigurationTest.java b/src/test/java/com/teragrep/cnf_01/ArgsConfigurationTest.java new file mode 100644 index 0000000..f3b8556 --- /dev/null +++ b/src/test/java/com/teragrep/cnf_01/ArgsConfigurationTest.java @@ -0,0 +1,167 @@ +/* + * Teragrep Configuration Library for Java (cnf_01) + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.cnf_01; + +import nl.jqno.equalsverifier.EqualsVerifier; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +public class ArgsConfigurationTest { + + @Test + public void testValidArgs() { + String param = "bar=foo"; + String[] args = { + "foo=bar", param + }; + + ArgsConfiguration config = new ArgsConfiguration(args); + // modifying the original doesn't have effect on the result + args[1] = "biz=buz"; + + Map map = Assertions.assertDoesNotThrow(config::asMap); + + Assertions.assertEquals(2, map.size()); + Assertions.assertTrue(map.containsKey("foo")); + Assertions.assertTrue(map.containsKey("bar")); + Assertions.assertEquals("bar", map.get("foo")); + Assertions.assertEquals("foo", map.get("bar")); + } + + @Test + public void testInvalidArgs() { + String[] args = { + "foo", "bar" + }; + + ArgsConfiguration config = new ArgsConfiguration(args); + + ConfigurationException exception = Assertions.assertThrows(ConfigurationException.class, config::asMap); + + Assertions + .assertEquals( + "Can't parse argument 'foo'. Args have to be given in \"key=value\" format.", + exception.getMessage() + ); + } + + @Test + public void testEmptyArgs() { + String[] args = new String[0]; + ArgsConfiguration config = new ArgsConfiguration(args); + + Map map = Assertions.assertDoesNotThrow(config::asMap); + Assertions.assertTrue(map.isEmpty()); + } + + @Test + public void testImmutability() { + String[] args = new String[0]; + ArgsConfiguration config = new ArgsConfiguration(args); + + Map map = Assertions.assertDoesNotThrow(config::asMap); + Assertions.assertThrows(UnsupportedOperationException.class, () -> map.put("foo", "bar")); // The map is immutable + } + + @Test + public void testEquals() { + String[] args = { + "foo=bar", "bar=foo" + }; + ArgsConfiguration config = new ArgsConfiguration(args); + + String[] args2 = { + "foo=bar", "bar=foo" + }; + ArgsConfiguration config2 = new ArgsConfiguration(args2); + + Assertions.assertDoesNotThrow(config::asMap); + + Assertions.assertEquals(config, config2); + } + + @Test + public void testNotEquals() { + String[] args = { + "foo=bar", "bar=foo" + }; + String[] args2 = { + "" + }; + + ArgsConfiguration config = new ArgsConfiguration(args); + ArgsConfiguration config2 = new ArgsConfiguration(args2); + + Assertions.assertNotEquals(config, config2); + } + + @Test + public void testHashCode() { + String[] args = { + "foo=bar", "bar=foo" + }; + String[] args2 = { + "foo=bar", "bar=foo" + }; + String[] args3 = { + "" + }; + + ArgsConfiguration config = new ArgsConfiguration(args); + ArgsConfiguration config2 = new ArgsConfiguration(args2); + ArgsConfiguration config3 = new ArgsConfiguration(args3); + + Assertions.assertEquals(config.hashCode(), config2.hashCode()); + Assertions.assertNotEquals(config.hashCode(), config3.hashCode()); + } + + @Test + public void testEqualsVerifier() { + EqualsVerifier.forClass(ArgsConfiguration.class).withNonnullFields("args").verify(); + } +}