From fd473d1368efe9e04764e4547cb9e76193db88c3 Mon Sep 17 00:00:00 2001 From: Sourabh Bhat Date: Mon, 21 Aug 2023 17:59:12 +0200 Subject: [PATCH] New Options class for reading commandline options. --- src/main/util/Options.java | 71 +++++++++++++++++++ test/main/util/OptionsTest.java | 120 ++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 src/main/util/Options.java create mode 100644 test/main/util/OptionsTest.java diff --git a/src/main/util/Options.java b/src/main/util/Options.java new file mode 100644 index 0000000..6ef2ee9 --- /dev/null +++ b/src/main/util/Options.java @@ -0,0 +1,71 @@ +package main.util; + +import java.util.Arrays; +import java.util.List; +import java.util.NoSuchElementException; + +import static java.lang.String.valueOf; + +/** + * A simple utility for reading command line arguments. + */ +public class Options { + private final String[] args; + + public Options(String[] args) { + this.args = args; + } + + public String get(String arg) { + String argName = (arg.startsWith("--") ? arg : ("--" + arg)).trim(); + List option = Arrays.stream(args) + .dropWhile(a -> !a.equals(argName)) + .limit(2) + .toList(); + if (option.size() != 2) { + throw new NoSuchElementException("Cannot find argument named: " + argName); + } + + return option.get(1); + } + + public String getOrDefault(String argName, String defaultValue) { + try { + return get(argName); + } catch (NoSuchElementException ex) { + return defaultValue; + } + } + + private int parseInt(String argName, String argValue) { + try { + return Integer.parseInt(argValue); + } catch (NumberFormatException ex) { + throw new IllegalArgumentException("Unable to parse value '" + argValue + "' as integer for the argument named '" + argName + "'"); + } + } + + public int getInt(String argName) { + return parseInt(argName, get(argName)); + } + + public int getIntOrDefault(String argName, int defaultValue) { + return parseInt(argName, getOrDefault(argName, valueOf(defaultValue))); + } + + private double parseDouble(String argName, String argValue) { + try { + return Double.parseDouble(argValue); + } catch (NumberFormatException ex) { + throw new IllegalArgumentException("Unable to parse value '" + argValue + "' as double for the argument named '" + argName + "'"); + } + } + + public double getDouble(String argName) { + return parseDouble(argName, get(argName)); + } + + public double getDoubleOrDefault(String argName, double defaultValue) { + return parseDouble(argName, getOrDefault(argName, valueOf(defaultValue))); + } +} diff --git a/test/main/util/OptionsTest.java b/test/main/util/OptionsTest.java new file mode 100644 index 0000000..78cd4c2 --- /dev/null +++ b/test/main/util/OptionsTest.java @@ -0,0 +1,120 @@ +package main.util; + +import org.junit.Test; + +import java.util.NoSuchElementException; + +import static org.junit.Assert.*; + +public class OptionsTest { + @Test + public void test_throws_when_argument_is_not_present() { + String[] args = new String[]{ + "--Mach", "3", + "--AoA", "2.5", + "--name", "String argument", + "--incomplete", + }; + Options options = new Options(args); + + NoSuchElementException exception = assertThrows(NoSuchElementException.class, () -> options.get("not-arg")); + assertEquals("Cannot find argument named: --not-arg", exception.getMessage()); + exception = assertThrows(NoSuchElementException.class, () -> options.get("incomplete")); + assertEquals("Cannot find argument named: --incomplete", exception.getMessage()); + } + + @Test + public void test_string_option() { + String[] args = new String[]{ + "--Mach", "3", + "--AoA", "2.5", + "--name", "String argument" + }; + Options options = new Options(args); + + assertEquals("String argument", options.get("name")); + assertEquals("String argument", options.get("--name")); + } + + @Test + public void test_default_value() { + String[] args = new String[]{ + "--Mach", "3", + "--AoA", "2.5", + "--name", "String argument" + }; + Options options = new Options(args); + + assertEquals("String argument", options.getOrDefault("--name", "Default argument")); + assertEquals("Default argument", options.getOrDefault("unknown", "Default argument")); + } + + @Test + public void test_int_argument() { + String[] args = new String[]{ + "--Mach", "3", + "--AoA", "2.5", + "--name", "String argument" + }; + Options options = new Options(args); + + assertEquals(3, options.getInt("Mach")); + } + + @Test + public void test_int_argument_with_default_value() { + String[] args = new String[]{ + "--Mach", "3", + "--AoA", "2.5", + "--name", "String argument" + }; + Options options = new Options(args); + + assertEquals(3, options.getIntOrDefault("Mach", 4)); + assertEquals(6, options.getIntOrDefault("Count", 6)); + } + + @Test + public void test_int_parsing_exception() { + String[] args = new String[]{ + "--Mach", "3.5", + "--AoA", "2.5", + "--name", "String argument" + }; + Options options = new Options(args); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> options.getInt("Mach")); + assertEquals("Unable to parse value '3.5' as integer for the argument named 'Mach'", exception.getMessage()); + exception = assertThrows(IllegalArgumentException.class, () -> options.getIntOrDefault("Mach", 5)); + assertEquals("Unable to parse value '3.5' as integer for the argument named 'Mach'", exception.getMessage()); + } + + @Test + public void test_double_argument() { + String[] args = new String[]{ + "--Mach", "3", + "--AoA", "2.5", + "--name", "String argument" + }; + Options options = new Options(args); + + assertEquals(2.5, options.getDouble("AoA"), 1e-15); + assertEquals(3, options.getDouble("Mach"), 1e-15); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> options.getDouble("name")); + assertEquals("Unable to parse value 'String argument' as double for the argument named 'name'", exception.getMessage()); + } + + @Test + public void test_double_argument_with_default_value() { + String[] args = new String[]{ + "--Mach", "3", + "--AoA", "2.5", + "--name", "String argument" + }; + Options options = new Options(args); + assertEquals(2.5, options.getDoubleOrDefault("AoA", 2.5), 1e-15); + assertEquals(3, options.getDoubleOrDefault("undefined", 3), 1e-15); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> options.getDoubleOrDefault("name", 2.5)); + assertEquals("Unable to parse value 'String argument' as double for the argument named 'name'", exception.getMessage()); + } +} \ No newline at end of file