diff --git a/src/main/java/chapter14/Application.java b/src/main/java/chapter14/Application.java new file mode 100644 index 0000000..904f8d9 --- /dev/null +++ b/src/main/java/chapter14/Application.java @@ -0,0 +1,24 @@ +package chapter14; + +import chapter14.args.Args; +import chapter14.args.ArgsException; + +class Application { + + public static void main(String[] args) { + try { + Args arg = new Args("l,p#,d*", args); + boolean logging = arg.getBoolean('l'); + int port = arg.getInt('p'); + String directory = arg.getString('d'); + executeApplication(logging, port, directory); + } catch (ArgsException e) { + System.out.printf("Argument error: %s\n", e.errorMessage()); + } + } + + // stub + private static void executeApplication(boolean logging, int port, String directory) { + System.out.printf("logging: %b, port: %d, directory: %s\n", logging, port, directory); + } +} diff --git a/src/main/java/chapter14/args/Args.java b/src/main/java/chapter14/args/Args.java new file mode 100644 index 0000000..07e4ac8 --- /dev/null +++ b/src/main/java/chapter14/args/Args.java @@ -0,0 +1,107 @@ +package chapter14.args; + +import java.util.*; + +import static chapter14.args.ArgsException.ErrorCode.*; + +public class Args { + private Map marshalers; + private Set argsFound; + private ListIterator currentArgument; + + public Args(String schema, String[] args) throws ArgsException { + marshalers = new HashMap<>(); + argsFound = new HashSet<>(); + + parseSchema(schema); + parseArgumentStrings(Arrays.asList(args)); + } + + private void parseSchema(String schema) throws ArgsException { + for (String element : schema.split(",")) { + if (element.length() > 0) { + parseSchemaElement(element.trim()); + } + } + } + + private void parseSchemaElement(String element) throws ArgsException { + char elementId = element.charAt(0); + String elementTail = element.substring(1); + validateSchemaElementId(elementId); + if (elementTail.length() == 0) + marshalers.put(elementId, new BooleanArgumentMarshaler()); + else if (elementTail.equals("*")) + marshalers.put(elementId, new StringArgumentMarshaler()); + else if (elementTail.equals("#")) + marshalers.put(elementId, new IntegerArgumentMarshaler()); + else if (elementTail.equals("##")) + marshalers.put(elementId, new DoubleArgumentMarshaler()); + else + throw new ArgsException(INVALID_ARGUMENT_FORMAT, elementId, elementTail); + + } + + private void validateSchemaElementId(char elementId) throws ArgsException { + if (!Character.isLetter(elementId)) { + throw new ArgsException(INVALID_ARGUMENT_NAME, elementId, null); + } + } + + private void parseArgumentStrings(List argsList) throws ArgsException { + for (currentArgument = argsList.listIterator(); currentArgument.hasNext(); ) { + String argString = currentArgument.next(); + if (argString.startsWith("-")) { + parseArgumentCharacters(argString.substring(1)); + } else { + currentArgument.previous(); + break; + } + } + } + + private void parseArgumentCharacters(String argChars) throws ArgsException { + for (int i = 0; i < argChars.length(); i++) { + parseArgumentCharacter(argChars.charAt(i)); + } + } + + private void parseArgumentCharacter(char argChar) throws ArgsException { + ArgumentMarshaler m = marshalers.get(argChar); + if (m == null) { + throw new ArgsException(UNEXPECTED_ARGUMENT, argChar, null); + } else { + argsFound.add(argChar); + try { + m.set(currentArgument); + } catch (ArgsException e) { + e.setErrorArgumentId(argChar); + throw e; + } + } + } + + public boolean has(char arg) { + return argsFound.contains(arg); + } + + public int nextArgument() { + return currentArgument.nextIndex(); + } + + public boolean getBoolean(char arg) { + return BooleanArgumentMarshaler.getValue(marshalers.get(arg)); + } + + public String getString(char arg) { + return StringArgumentMarshaler.getValue(marshalers.get(arg)); + } + + public int getInt(char arg) { + return IntegerArgumentMarshaler.getValue(marshalers.get(arg)); + } + + public double getDouble(char arg) { + return DoubleArgumentMarshaler.getValue(marshalers.get(arg)); + } +} diff --git a/src/main/java/chapter14/args/ArgsException.java b/src/main/java/chapter14/args/ArgsException.java new file mode 100644 index 0000000..5f6b985 --- /dev/null +++ b/src/main/java/chapter14/args/ArgsException.java @@ -0,0 +1,92 @@ +package chapter14.args; + +public class ArgsException extends Exception { + private char errorArgumentId = '\0'; + private String errorParameter = "TILT"; + private ErrorCode errorCode = ErrorCode.OK; + + public ArgsException() { + } + + public ArgsException(String message) { + super(message); + } + + public ArgsException(ErrorCode errorCode) { + this.errorCode = errorCode; + } + + public ArgsException(ErrorCode errorCode, String errorParameter) { + this.errorCode = errorCode; + this.errorParameter = errorParameter; + } + + public ArgsException(ErrorCode errorCode, char errorArgumentId, String errorParameter) { + this.errorCode = errorCode; + this.errorArgumentId = errorArgumentId; + this.errorParameter = errorParameter; + } + + public char getErrorArgumentId() { + return errorArgumentId; + } + + public void setErrorArgumentId(char errorArgumentId) { + this.errorArgumentId = errorArgumentId; + } + + public String getErrorParameter() { + return errorParameter; + } + + public void setErrorParameter(String errorParameter) { + this.errorParameter = errorParameter; + } + + public ErrorCode getErrorCode() { + return errorCode; + } + + public void setErrorCode(ErrorCode errorCode) { + this.errorCode = errorCode; + } + + public String errorMessage() { + switch (errorCode) { + case OK: + return "TILT: Should not get here."; + case UNEXPECTED_ARGUMENT: + return String.format("Argument(s) -%c unexpected.", errorArgumentId); + case MISSING_STRING: + return String.format("Could not find string parameter for -%c.", + errorArgumentId); + case INVALID_INTEGER: + return String.format("Argument -%c expects an integer but was '%s'.", + errorArgumentId, errorParameter); + case MISSING_INTEGER: + return String.format("Could not find integer parameter for -%c.", + errorArgumentId); + case INVALID_DOUBLE: + return String.format("Argument -%c expects an double but was '%s'.", + errorArgumentId, errorParameter); + case MISSING_DOUBLE: + return String.format("Could not find double parameter for -%c.", + errorArgumentId); + case INVALID_ARGUMENT_NAME: + return String.format("'%c' is not a valid argument name.", + errorArgumentId); + case INVALID_ARGUMENT_FORMAT: + return String.format("'%s' is not a valid argument format.", + errorParameter); + } + return ""; + } + + public enum ErrorCode { + OK, INVALID_ARGUMENT_FORMAT, UNEXPECTED_ARGUMENT, + INVALID_ARGUMENT_NAME, + MISSING_STRING, + MISSING_INTEGER, INVALID_INTEGER, + MISSING_DOUBLE, INVALID_DOUBLE + } +} diff --git a/src/main/java/chapter14/args/ArgumentMarshaler.java b/src/main/java/chapter14/args/ArgumentMarshaler.java new file mode 100644 index 0000000..ebf4a48 --- /dev/null +++ b/src/main/java/chapter14/args/ArgumentMarshaler.java @@ -0,0 +1,7 @@ +package chapter14.args; + +import java.util.Iterator; + +public interface ArgumentMarshaler { + void set(Iterator currentArgument) throws ArgsException; +} diff --git a/src/main/java/chapter14/args/BooleanArgumentMarshaler.java b/src/main/java/chapter14/args/BooleanArgumentMarshaler.java new file mode 100644 index 0000000..8ec3e0e --- /dev/null +++ b/src/main/java/chapter14/args/BooleanArgumentMarshaler.java @@ -0,0 +1,20 @@ +package chapter14.args; + +import java.util.Iterator; + +public class BooleanArgumentMarshaler implements ArgumentMarshaler { + private boolean booleanValue = false; + + @Override + public void set(Iterator currentArgument) throws ArgsException { + booleanValue = true; + } + + public static boolean getValue(ArgumentMarshaler am) { + if (am != null && am instanceof BooleanArgumentMarshaler) { + return ((BooleanArgumentMarshaler) am).booleanValue; + } else { + return false; + } + } +} \ No newline at end of file diff --git a/src/main/java/chapter14/args/DoubleArgumentMarshaler.java b/src/main/java/chapter14/args/DoubleArgumentMarshaler.java new file mode 100644 index 0000000..e737b01 --- /dev/null +++ b/src/main/java/chapter14/args/DoubleArgumentMarshaler.java @@ -0,0 +1,32 @@ +package chapter14.args; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import static chapter14.args.ArgsException.ErrorCode.INVALID_DOUBLE; +import static chapter14.args.ArgsException.ErrorCode.MISSING_DOUBLE; + +public class DoubleArgumentMarshaler implements ArgumentMarshaler { + private double doubleValue = 0; + + @Override + public void set(Iterator currentArgument) throws ArgsException { + String parameter = null; + try { + parameter = currentArgument.next(); + doubleValue = Double.parseDouble(parameter); + } catch (NoSuchElementException e) { + throw new ArgsException(MISSING_DOUBLE); + } catch (NumberFormatException e) { + throw new ArgsException(INVALID_DOUBLE, parameter); + } + } + + public static double getValue(ArgumentMarshaler am) { + if (am != null && am instanceof DoubleArgumentMarshaler) { + return ((DoubleArgumentMarshaler) am).doubleValue; + } else { + return 0.0; + } + } +} \ No newline at end of file diff --git a/src/main/java/chapter14/args/IntegerArgumentMarshaler.java b/src/main/java/chapter14/args/IntegerArgumentMarshaler.java new file mode 100644 index 0000000..5162230 --- /dev/null +++ b/src/main/java/chapter14/args/IntegerArgumentMarshaler.java @@ -0,0 +1,32 @@ +package chapter14.args; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import static chapter14.args.ArgsException.ErrorCode.INVALID_INTEGER; +import static chapter14.args.ArgsException.ErrorCode.MISSING_INTEGER; + +public class IntegerArgumentMarshaler implements ArgumentMarshaler { + private int intValue = 0; + + @Override + public void set(Iterator currentArgument) throws ArgsException { + String parameter = null; + try { + parameter = currentArgument.next(); + intValue = Integer.parseInt(parameter); + } catch (NoSuchElementException e) { + throw new ArgsException(MISSING_INTEGER); + } catch (NumberFormatException e) { + throw new ArgsException(INVALID_INTEGER, parameter); + } + } + + public static int getValue(ArgumentMarshaler am) { + if (am != null && am instanceof IntegerArgumentMarshaler) { + return ((IntegerArgumentMarshaler) am).intValue; + } else { + return 0; + } + } +} \ No newline at end of file diff --git a/src/main/java/chapter14/args/StringArgumentMarshaler.java b/src/main/java/chapter14/args/StringArgumentMarshaler.java new file mode 100644 index 0000000..b0698e4 --- /dev/null +++ b/src/main/java/chapter14/args/StringArgumentMarshaler.java @@ -0,0 +1,27 @@ +package chapter14.args; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import static chapter14.args.ArgsException.ErrorCode.MISSING_STRING; + +public class StringArgumentMarshaler implements ArgumentMarshaler { + private String stringValue = ""; + + @Override + public void set(Iterator currentArgument) throws ArgsException { + try { + stringValue = currentArgument.next(); + } catch (NoSuchElementException e) { + throw new ArgsException(MISSING_STRING); + } + } + + public static String getValue(ArgumentMarshaler am) { + if (am != null && am instanceof StringArgumentMarshaler) { + return ((StringArgumentMarshaler) am).stringValue; + } else { + return ""; + } + } +} \ No newline at end of file diff --git a/src/test/java/chapter14/ApplicationTest.java b/src/test/java/chapter14/ApplicationTest.java new file mode 100644 index 0000000..c000de9 --- /dev/null +++ b/src/test/java/chapter14/ApplicationTest.java @@ -0,0 +1,73 @@ +package chapter14; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class ApplicationTest extends MainMethodTest { + + @Test + void booleanArguments() { + //given + String[] args = new String[]{"-l"}; + + //when + runMain(args); + + //then + assertThat(output()).contains("true"); + } + + @Test + void stringArguments() { + //given + String[] args = new String[]{"-d", "root"}; + + //when + runMain(args); + + //then + assertThat(output()).contains("root"); + } + + @Test + void integerArguments() { + //given + String[] args = new String[]{"-p", "42"}; + + //when + runMain(args); + + //then + assertThat(output()).contains("42"); + } + + @Test + void allArgumentsPresent() { + //given + String[] args = new String[]{"-l", "-p", "8080", "-d", "user"}; + + //when + runMain(args); + + //then + assertThat(output()).isEqualTo("logging: true, port: 8080, directory: user"); + } + + @Test + void noArguments() { + //given + String[] args = new String[0]; + + //when + runMain(args); + + //then + assertThat(output()).isEqualTo("logging: false, port: 0, directory:"); + } + + @Override + protected void runMain(String... args) { + Application.main(args); + } +} \ No newline at end of file diff --git a/src/test/java/chapter14/MainMethodTest.java b/src/test/java/chapter14/MainMethodTest.java new file mode 100644 index 0000000..e0bf861 --- /dev/null +++ b/src/test/java/chapter14/MainMethodTest.java @@ -0,0 +1,39 @@ +package chapter14; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.io.PrintStream; + +abstract class MainMethodTest { + private final PrintStream standardOut = System.out; + private OutputStream captor; + + @BeforeEach + protected final void init() { + setSystemOutToMyPrintStreamForCaptor(); + } + + private void setSystemOutToMyPrintStreamForCaptor() { + captor = new ByteArrayOutputStream(); + System.setOut(new PrintStream(captor)); + } + + @AfterEach + protected final void printOutput() { + setSystemOutToStandard(); + System.out.println(output()); + } + + private void setSystemOutToStandard() { + System.setOut(standardOut); + } + + protected final String output() { + return captor.toString().trim(); + } + + protected abstract void runMain(String... args); +} diff --git a/src/test/java/chapter14/args/ArgsExceptionTest.java b/src/test/java/chapter14/args/ArgsExceptionTest.java new file mode 100644 index 0000000..a01faaf --- /dev/null +++ b/src/test/java/chapter14/args/ArgsExceptionTest.java @@ -0,0 +1,106 @@ +package chapter14.args; + +import org.junit.jupiter.api.Test; + +import static chapter14.args.ArgsException.ErrorCode; +import static chapter14.args.ArgsException.ErrorCode.*; +import static org.assertj.core.api.Assertions.assertThat; + +class ArgsExceptionTest { + + @Test + void unexpectedMessage() throws Exception { + //given + ErrorCode errorCode = UNEXPECTED_ARGUMENT; + + //when + ArgsException e = new ArgsException(errorCode, 'x', null); + + //then + assertThat(e.errorMessage()).isEqualTo("Argument(s) -x unexpected."); + } + + @Test + void missingStringMessage() throws Exception { + //given + ErrorCode errorCode = MISSING_STRING; + + //when + ArgsException e = new ArgsException(errorCode, 'x', null); + + //then + assertThat(e.errorMessage()).isEqualTo("Could not find string parameter for -x."); + } + + @Test + void invalidIntegerMessage() throws Exception { + //given + ErrorCode errorCode = INVALID_INTEGER; + + //when + ArgsException e = new ArgsException(errorCode, 'x', "Forty two"); + + //then + assertThat(e.errorMessage()).isEqualTo("Argument -x expects an integer but was 'Forty two'."); + } + + @Test + void missingIntegerMessage() throws Exception { + //given + ErrorCode errorCode = MISSING_INTEGER; + + //when + ArgsException e = new ArgsException(errorCode, 'x', null); + + //then + assertThat(e.errorMessage()).isEqualTo("Could not find integer parameter for -x."); + } + + @Test + void invalidDoubleMessage() throws Exception { + //given + ErrorCode errorCode = INVALID_DOUBLE; + + //when + ArgsException e = new ArgsException(errorCode, 'x', "Forty two"); + + //then + assertThat(e.errorMessage()).isEqualTo("Argument -x expects an double but was 'Forty two'."); + } + + @Test + void missingDoubleMessage() throws Exception { + //given + ErrorCode errorCode = MISSING_DOUBLE; + + //when + ArgsException e = new ArgsException(errorCode, 'x', null); + + //then + assertThat(e.errorMessage()).isEqualTo("Could not find double parameter for -x."); + } + + @Test + void invalidArgumentNameMessage() throws Exception { + //given + ErrorCode errorCode = INVALID_ARGUMENT_NAME; + + //when + ArgsException e = new ArgsException(errorCode, 'x', null); + + //then + assertThat(e.errorMessage()).isEqualTo("'x' is not a valid argument name."); + } + + @Test + void invalidArgumentFormatMessage() throws Exception { + //given + ErrorCode errorCode = INVALID_ARGUMENT_FORMAT; + + //when + ArgsException e = new ArgsException(errorCode, 'x', "f~"); + + //then + assertThat(e.errorMessage()).isEqualTo("'f~' is not a valid argument format."); + } +} \ No newline at end of file diff --git a/src/test/java/chapter14/args/ArgsTest.java b/src/test/java/chapter14/args/ArgsTest.java new file mode 100644 index 0000000..0b331a2 --- /dev/null +++ b/src/test/java/chapter14/args/ArgsTest.java @@ -0,0 +1,298 @@ +package chapter14.args; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static chapter14.args.ArgsException.ErrorCode.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchException; + +class ArgsTest { + + @DisplayName("schema와 arguments가 없는 경우") + @Test + void noSchemaAndArguments() throws Exception { + //given + String schema = ""; + String[] arguments = new String[0]; + + //when + Args args = new Args(schema, arguments); + + //then + assertThat(args.nextArgument()).isZero(); + } + + @DisplayName("schema가 없고 argument가 1개 있는 경우") + @Test + void noSchemaButWithOneArgument() { + //given + String schema = ""; + String[] arguments = new String[]{"-x"}; + + //when + Exception exception = catchException(() -> new Args(schema, arguments)); + + //then + assertThat(exception).isInstanceOf(ArgsException.class); + + ArgsException e = (ArgsException) exception; + assertThat(e.getErrorCode()).isEqualTo(UNEXPECTED_ARGUMENT); + assertThat(e.getErrorArgumentId()).isEqualTo('x'); + } + + @DisplayName("Schema가 있고, arugment가 없는 경우") + @Test + void multipleSchemasButNoArguments() throws Exception { + //given + String schema = "x,y#,z*"; + String[] arguments = new String[]{}; + + //when + Args args = new Args(schema, arguments); + + //then + assertThat(args.has('x')).isFalse(); + assertThat(args.has('y')).isFalse(); + assertThat(args.has('z')).isFalse(); + assertThat(args.getBoolean('x')).isFalse(); + assertThat(args.getInt('y')).isZero(); + assertThat(args.getString('z')).isEmpty(); + } + + @DisplayName("schema가 문자가 아닌 경우") + @Test + void nonLetterSchema() { + //given + String nonLetterSchemaElementId = "*"; + String[] arguments = new String[]{}; + + //when + Exception exception = catchException(() -> new Args(nonLetterSchemaElementId, arguments)); + + //then + assertThat(exception).isInstanceOf(ArgsException.class); + + ArgsException e = (ArgsException) exception; + assertThat(e.getErrorCode()).isEqualTo(INVALID_ARGUMENT_NAME); + assertThat(e.getErrorArgumentId()).isEqualTo('*'); + } + + @DisplayName("schema format이 유효하지 않은 경우") + @Test + void invalidArgumentFormat() { + //given + String invalidSchemeFormat = "f~"; + String[] arguments = new String[]{}; + + //when + Exception exception = catchException(() -> new Args(invalidSchemeFormat, arguments)); + + //then + assertThat(exception).isInstanceOf(ArgsException.class); + + ArgsException e = (ArgsException) exception; + assertThat(e.getErrorCode()).isEqualTo(INVALID_ARGUMENT_FORMAT); + assertThat(e.getErrorArgumentId()).isEqualTo('f'); + } + + @DisplayName("Schema format에 스페이스가 있는 경우") + @Test + void spacesInFormat() throws Exception { + //given + String schema = "x, y"; + String[] arguments = new String[]{"-xy"}; + + //when + Args args = new Args(schema, arguments); + + //then + assertThat(args.has('x')).isTrue(); + assertThat(args.has('y')).isTrue(); + } + + @DisplayName("boolean 값이 있는 경우") + @Test + void simpleBooleanPresent() throws Exception { + //given + String schema = "x"; + String[] arguments = new String[]{"-x"}; + + //when + Args args = new Args(schema, arguments); + + //then + assertThat(args.getBoolean('x')).isTrue(); + } + + @DisplayName("boolean 값이 여러 개 있는 경우") + @Test + void simpleBooleanMultiplePresent() throws Exception { + //given + String schema = "x,y,z"; + String[] arguments = new String[]{"-x", "-y"}; + + //when + Args args = new Args(schema, arguments); + + //then + assertThat(args.has('x')).isTrue(); + assertThat(args.has('y')).isTrue(); + assertThat(args.has('z')).isFalse(); + assertThat(args.getBoolean('x')).isTrue(); + assertThat(args.getBoolean('y')).isTrue(); + assertThat(args.getBoolean('z')).isFalse(); + } + + @DisplayName("boolean 값이 없는 경우") + @Test + void simpleBooleanNotPresent() throws Exception { + //given + Args args = new Args("x", new String[]{}); + + //when + boolean actual = args.getBoolean('y'); + + //then + assertThat(actual).isFalse(); + } + + @DisplayName("String 값이 있는 경우") + @Test + void simpleStringPresent() throws Exception { + //given + String schema = "x*"; + String[] arguments = new String[]{"-x", "param"}; + + //when + Args args = new Args(schema, arguments); + + //then + assertThat(args.has('x')).isTrue(); + assertThat(args.getString('x')).isEqualTo("param"); + } + + @DisplayName("String 값이 여러 개 있는 경우") + @Test + void simpleStringMultiplePresent() throws Exception { + //given + String schema = "x*,y*,z*"; + String[] arguments = new String[]{"-x", "param1", "-y", "param2"}; + + //when + Args args = new Args(schema, arguments); + + //then + assertThat(args.has('x')).isTrue(); + assertThat(args.has('y')).isTrue(); + assertThat(args.has('z')).isFalse(); + assertThat(args.getString('x')).isEqualTo("param1"); + assertThat(args.getString('y')).isEqualTo("param2"); + assertThat(args.getString('z')).isEmpty(); + } + + @DisplayName("String 값이 없는 경우") + @Test + void simpleStringNotPresent() throws Exception { + //given + Args args = new Args("x*", new String[]{}); + + //when + String actual = args.getString('y'); + + //then + assertThat(actual).isEmpty(); + } + + @DisplayName("int 값이 있는 경우") + @Test + void simpleIntPresent() throws Exception { + //given + String schema = "x#"; + String[] arguments = new String[]{"-x", "42"}; + + //when + Args args = new Args(schema, arguments); + + //then + assertThat(args.has('x')).isTrue(); + assertThat(args.getInt('x')).isEqualTo(42); + } + + @DisplayName("int 값이 여러 개 있는 경우") + @Test + void simpleIntMultiplePresent() throws Exception { + //given + String schema = "x#,y#,z#"; + String[] arguments = new String[]{"-x", "8001", "-y", "8002"}; + + //when + Args args = new Args(schema, arguments); + + //then + assertThat(args.has('x')).isTrue(); + assertThat(args.has('y')).isTrue(); + assertThat(args.has('z')).isFalse(); + assertThat(args.getInt('x')).isEqualTo(8001); + assertThat(args.getInt('y')).isEqualTo(8002); + assertThat(args.getInt('z')).isZero(); + } + + @DisplayName("int 값이 없는 경우") + @Test + void simpleIntNotPresent() throws Exception { + //given + Args args = new Args("x#", new String[]{}); + + //when + int actual = args.getInt('y'); + + //then + assertThat(actual).isZero(); + } + + @DisplayName("double 값이 있는 경우") + @Test + void simpleDoublePresent() throws Exception { + //given + String schema = "x##"; + String[] arguments = new String[]{"-x", "42.3"}; + + //when + Args args = new Args(schema, arguments); + + //then + assertThat(args.has('x')).isTrue(); + assertThat(args.getDouble('x')).isEqualTo(42.3); + } + + @DisplayName("Double 값이 없는 경우") + @Test + void simpleDoubleNotPresent() throws Exception { + //given + Args args = new Args("x##", new String[]{}); + + //when + double actual = args.getDouble('y'); + + //then + assertThat(actual).isZero(); + } + + @DisplayName("잘못된 타입으로 호출한 경우") + @Test + void invalidType() throws Exception { + //given + String schema = "x#,y*"; + String[] arguments = new String[]{"-x", "42", "-y", "param"}; + + //when + Args args = new Args(schema, arguments); + + //then + assertThat(args.getBoolean('x')).isFalse(); // x is type int + assertThat(args.getString('x')).isEmpty(); // x is type int + assertThat(args.getInt('y')).isZero(); // y is type String + assertThat(args.getDouble('y')).isZero(); // y is type String + } +} \ No newline at end of file diff --git a/src/test/java/chapter14/args/BooleanArgumentMarshalerTest.java b/src/test/java/chapter14/args/BooleanArgumentMarshalerTest.java new file mode 100644 index 0000000..2b7f28d --- /dev/null +++ b/src/test/java/chapter14/args/BooleanArgumentMarshalerTest.java @@ -0,0 +1,52 @@ +package chapter14.args; + +import org.junit.jupiter.api.Test; + +import java.util.Iterator; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + + +class BooleanArgumentMarshalerTest { + + @Test + void getValueNotPresent() { + //given + ArgumentMarshaler am = new BooleanArgumentMarshaler(); + + //when, then + assertThat(BooleanArgumentMarshaler.getValue(am)).isFalse(); + } + + @Test + void getValuePresent() throws ArgsException { + //given + Iterator list = List.of("test").iterator(); + + //when + ArgumentMarshaler am = new BooleanArgumentMarshaler(); + am.set(list); + + //then + assertThat(BooleanArgumentMarshaler.getValue(am)).isTrue(); + } + + @Test + void getValueNotEqualsType() throws ArgsException { + //given + Iterator list = List.of("param").iterator(); + + //when + ArgumentMarshaler otherType = new StringArgumentMarshaler(); + otherType.set(list); + + //then + assertThat(BooleanArgumentMarshaler.getValue(otherType)).isFalse(); + } + + @Test + void getValueNull() { + assertThat(BooleanArgumentMarshaler.getValue(null)).isFalse(); + } +} \ No newline at end of file diff --git a/src/test/java/chapter14/args/DoubleArgumentMarshalerTest.java b/src/test/java/chapter14/args/DoubleArgumentMarshalerTest.java new file mode 100644 index 0000000..354c8c2 --- /dev/null +++ b/src/test/java/chapter14/args/DoubleArgumentMarshalerTest.java @@ -0,0 +1,89 @@ +package chapter14.args; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchException; + +class DoubleArgumentMarshalerTest { + + @DisplayName("값을 파싱할 수 없는 경우") + @Test + void invalidDouble() { + //given + Iterator argument = List.of("Forty two").iterator(); + + //when + ArgumentMarshaler am = new DoubleArgumentMarshaler(); + Exception exception = catchException(() -> am.set(argument)); + + //then + assertThat(exception).isInstanceOf(ArgsException.class); + + ArgsException e = (ArgsException) exception; + assertThat(e.getErrorCode()).isEqualTo(ArgsException.ErrorCode.INVALID_DOUBLE); + assertThat(e.getErrorParameter()).isEqualTo("Forty two"); + } + + @DisplayName("Argument 값이 없는 경우") + @Test + void missingDouble() { + //given + Iterator argument = Collections.emptyIterator(); + + //when + ArgumentMarshaler am = new DoubleArgumentMarshaler(); + Exception exception = catchException(() -> am.set(argument)); + + //then + assertThat(exception).isInstanceOf(ArgsException.class); + + ArgsException e = (ArgsException) exception; + assertThat(e.getErrorCode()).isEqualTo(ArgsException.ErrorCode.MISSING_DOUBLE); + } + + @Test + void getValueNotPresent() { + //given + ArgumentMarshaler am = new DoubleArgumentMarshaler(); + + //when, then + assertThat(DoubleArgumentMarshaler.getValue(am)).isZero(); + } + + @Test + void getValuePresent() throws ArgsException { + //given + Iterator list = List.of("42.3").iterator(); + + //when + ArgumentMarshaler am = new DoubleArgumentMarshaler(); + am.set(list); + + //then + assertThat(DoubleArgumentMarshaler.getValue(am)).isEqualTo(42.3); + } + + @Test + void getValueNotEqualsType() throws ArgsException { + //given + Iterator list = List.of("param").iterator(); + + //when + ArgumentMarshaler otherType = new StringArgumentMarshaler(); + otherType.set(list); + + //then + assertThat(DoubleArgumentMarshaler.getValue(otherType)).isZero(); + } + + @Test + void getValueNull() { + assertThat(DoubleArgumentMarshaler.getValue(null)).isZero(); + } +} \ No newline at end of file diff --git a/src/test/java/chapter14/args/IntegerArgumentMarshalerTest.java b/src/test/java/chapter14/args/IntegerArgumentMarshalerTest.java new file mode 100644 index 0000000..9c94d1e --- /dev/null +++ b/src/test/java/chapter14/args/IntegerArgumentMarshalerTest.java @@ -0,0 +1,89 @@ +package chapter14.args; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchException; + +class IntegerArgumentMarshalerTest { + + @DisplayName("Integer Argument 값을 파싱할 수 없는 경우") + @Test + void invalidInteger() { + //given + Iterator argument = List.of("Forty two").iterator(); + + //when + ArgumentMarshaler am = new IntegerArgumentMarshaler(); + Exception exception = catchException(() -> am.set(argument)); + + //then + assertThat(exception).isInstanceOf(ArgsException.class); + + ArgsException e = (ArgsException) exception; + assertThat(e.getErrorCode()).isEqualTo(ArgsException.ErrorCode.INVALID_INTEGER); + assertThat(e.getErrorParameter()).isEqualTo("Forty two"); + } + + @DisplayName("Argument 값이 없는 경우") + @Test + void missingInteger() { + //given + Iterator argument = Collections.emptyIterator(); + + //when + ArgumentMarshaler am = new IntegerArgumentMarshaler(); + Exception exception = catchException(() -> am.set(argument)); + + //then + assertThat(exception).isInstanceOf(ArgsException.class); + + ArgsException e = (ArgsException) exception; + assertThat(e.getErrorCode()).isEqualTo(ArgsException.ErrorCode.MISSING_INTEGER); + } + + @Test + void getValueNotPresent() { + //given + ArgumentMarshaler am = new IntegerArgumentMarshaler(); + + //when, then + assertThat(IntegerArgumentMarshaler.getValue(am)).isZero(); + } + + @Test + void getValuePresent() throws ArgsException { + //given + Iterator list = List.of("42").iterator(); + + //when + ArgumentMarshaler am = new IntegerArgumentMarshaler(); + am.set(list); + + //then + assertThat(IntegerArgumentMarshaler.getValue(am)).isEqualTo(42); + } + + @Test + void getValueNotEqualsType() throws ArgsException { + //given + Iterator list = List.of("param").iterator(); + + //when + ArgumentMarshaler otherType = new StringArgumentMarshaler(); + otherType.set(list); + + //then + assertThat(IntegerArgumentMarshaler.getValue(otherType)).isZero(); + } + + @Test + void getValueNull() { + assertThat(IntegerArgumentMarshaler.getValue(null)).isZero(); + } +} \ No newline at end of file diff --git a/src/test/java/chapter14/args/StringArgumentMarshalerTest.java b/src/test/java/chapter14/args/StringArgumentMarshalerTest.java new file mode 100644 index 0000000..fed79ca --- /dev/null +++ b/src/test/java/chapter14/args/StringArgumentMarshalerTest.java @@ -0,0 +1,73 @@ +package chapter14.args; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchException; + +class StringArgumentMarshalerTest { + + @DisplayName("Argument 값이 없는 경우") + @Test + void missingString() { + //given + Iterator argument = Collections.emptyIterator(); + + //when + ArgumentMarshaler am = new StringArgumentMarshaler(); + Exception exception = catchException(() -> am.set(argument)); + + //then + assertThat(exception).isInstanceOf(ArgsException.class); + + ArgsException e = (ArgsException) exception; + assertThat(e.getErrorCode()).isEqualTo(ArgsException.ErrorCode.MISSING_STRING); + } + + + @Test + void getValueNotPresent() { + //given + ArgumentMarshaler am = new StringArgumentMarshaler(); + + //when, then + assertThat(StringArgumentMarshaler.getValue(am)).isEmpty(); + } + + @Test + void getValuePresent() throws ArgsException { + //given + Iterator list = List.of("param").iterator(); + + //when + ArgumentMarshaler am = new StringArgumentMarshaler(); + am.set(list); + + //then + assertThat(StringArgumentMarshaler.getValue(am)).isEqualTo("param"); + } + + @Test + void getValueNotEqualsType() throws ArgsException { + //given + Iterator list = List.of("42").iterator(); + + //when + ArgumentMarshaler otherType = new IntegerArgumentMarshaler(); + otherType.set(list); + + //then + assertThat(StringArgumentMarshaler.getValue(otherType)).isEmpty(); + } + + + @Test + void getValueNull() { + assertThat(StringArgumentMarshaler.getValue(null)).isEmpty(); + } +} \ No newline at end of file