Skip to content

Commit

Permalink
#571 add CommandReflection tests
Browse files Browse the repository at this point in the history
  • Loading branch information
remkop committed Dec 21, 2018
1 parent 5f3995a commit 0b4b488
Showing 1 changed file with 118 additions and 0 deletions.
118 changes: 118 additions & 0 deletions src/test/java/picocli/CommandLineModelTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Types;
import java.util.*;

Expand Down Expand Up @@ -2421,4 +2423,120 @@ public void testMessagesGetStringArrayNullKey() {

assertNotEquals(def, new Messages(CommandSpec.create(), rb).getStringArray("usage.description", def));
}

@Test
public void testCommandReflection() throws Exception {
Class<?> reflection = Class.forName("picocli.CommandLine$Model$CommandReflection");
Method extractCommandSpec = reflection.getDeclaredMethod("extractCommandSpec", Object.class, IFactory.class, boolean.class);

IFactory myFactory = new IFactory() {
public <K> K create(Class<K> cls) throws Exception {
throw new InitializationException("boom");
}
};

try {
extractCommandSpec.invoke(null, Object.class, myFactory, false);
fail("expected Exception");
} catch (InvocationTargetException ite) {
InitializationException ex = (InitializationException) ite.getCause();
assertEquals("Could not instantiate class java.lang.Object: picocli.CommandLine$InitializationException: boom", ex.getMessage());
}
}

@Command(subcommands = InvalidSub.class)
static class InvalidTop {}

@Command(name = "invalidsub")
static class InvalidSub {
public InvalidSub(int x) {}
}

@Test
public void testCommandReflection_initSubcommands() throws Exception {
try {
CommandSpec.forAnnotatedObject(InvalidTop.class);
} catch (InitializationException ex) {
assertEquals("Cannot instantiate subcommand picocli.CommandLineModelTest$InvalidSub: the class has no constructor", ex.getMessage());
}
}

@Command(subcommands = InvalidSub2.class)
static class InvalidTop2 {}

@Command(name = "<main class>")
static class InvalidSub2 {
}

@Test
public void testCommandReflection_subcommandName() throws Exception {
try {
CommandSpec.forAnnotatedObject(InvalidTop2.class);
} catch (InitializationException ex) {
assertEquals("Subcommand picocli.CommandLineModelTest$InvalidSub2 is missing the mandatory @Command annotation with a 'name' attribute", ex.getMessage());
}
}

static class TypedMemberObj {
int x;
}
@Test
public void testCommandReflection_validateMixin() throws Exception {
Class<?> reflection = Class.forName("picocli.CommandLine$Model$CommandReflection");
Method validateMixin = reflection.getDeclaredMethod("validateMixin", TypedMember.class);
validateMixin.setAccessible(true);

TypedMember typedMember = new TypedMember(TypedMemberObj.class.getDeclaredField("x"));
try {
validateMixin.invoke(null, typedMember);
fail("expected Exception");
} catch (InvocationTargetException ite) {
IllegalStateException ex = (IllegalStateException) ite.getCause();
assertEquals("Bug: validateMixin() should only be called with mixins", ex.getMessage());
}
}
@Test
public void testCommandReflection_validateUnmatched() throws Exception {
Class<?> reflection = Class.forName("picocli.CommandLine$Model$CommandReflection");
Method validateUnmatched = reflection.getDeclaredMethod("validateUnmatched", TypedMember.class);
validateUnmatched.setAccessible(true);

TypedMember typedMember = new TypedMember(TypedMemberObj.class.getDeclaredField("x"));
validateUnmatched.invoke(null, typedMember); // no error
}

static class ValidateArgSpecField {
@Mixin
@Option(names = "-x")
int x;

@Option(names = "-final")
final Object f = new Object();
}

@Test
public void testCommandReflection_validateArgSpecField() throws Exception {
Class<?> reflection = Class.forName("picocli.CommandLine$Model$CommandReflection");
Method validateArgSpecField = reflection.getDeclaredMethod("validateArgSpecField", TypedMember.class);
validateArgSpecField.setAccessible(true);

TypedMember typedMember = new TypedMember(ValidateArgSpecField.class.getDeclaredField("x"));
try {
validateArgSpecField.invoke(null, typedMember);
fail("expected Exception");
} catch (InvocationTargetException ite) {
DuplicateOptionAnnotationsException ex = (DuplicateOptionAnnotationsException) ite.getCause();
assertEquals("A member cannot be both a @Mixin command and an @Option or @Parameters, but 'int picocli.CommandLineModelTest$ValidateArgSpecField.x' is both.", ex.getMessage());
}
}

@Test
public void testCommandReflection_validateArgSpecField_final() throws Exception {
Class<?> reflection = Class.forName("picocli.CommandLine$Model$CommandReflection");
Method validateArgSpecField = reflection.getDeclaredMethod("validateArgSpecField", TypedMember.class);
validateArgSpecField.setAccessible(true);

TypedMember typedMember = new TypedMember(ValidateArgSpecField.class.getDeclaredField("f"));
validateArgSpecField.invoke(null, typedMember); // no error
}
}

0 comments on commit 0b4b488

Please sign in to comment.