Skip to content

Commit ee429bf

Browse files
committed
Add end-to-end test showing no class init through the public CLI API
Signed-off-by: farkhalit rida <farkhlait@sproutxp.com>
1 parent 7c3dec0 commit ee429bf

1 file changed

Lines changed: 29 additions & 0 deletions

File tree

‎src/test/java/org/apache/commons/cli/ConverterTests.java‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,23 @@ public static class PluginImpl implements Plugin {
7070
}
7171
}
7272

73+
// A Plugin used by the end-to-end public-API test; kept separate so it is not initialized by another test first.
74+
public static class ApiPluginImpl implements Plugin {
75+
76+
static {
77+
apiPluginInitializerRan = true;
78+
}
79+
}
80+
7381
// Set by the static initializer of AClassWithAStaticInitializer; readable without initializing that class.
7482
private static boolean classInitializerRan;
7583

7684
// Set by the static initializer of PluginImpl; readable without initializing that class.
7785
private static boolean pluginInitializerRan;
7886

87+
// Set by the static initializer of ApiPluginImpl; readable without initializing that class.
88+
private static boolean apiPluginInitializerRan;
89+
7990
private static Stream<Arguments> numberTestParameters() {
8091
final List<Arguments> lst = new ArrayList<>();
8192
lst.add(Arguments.of("123", Long.valueOf("123")));
@@ -121,6 +132,24 @@ void testClassValidatedBeforeInitialization() throws Exception {
121132
assertTrue(pluginInitializerRan);
122133
}
123134

135+
@Test
136+
void testClassNotInitializedThroughPublicApi() throws Exception {
137+
// What an application using the public API actually does: declare a Class-typed option via a pattern,
138+
// parse argv, query the value, then gate it. Parsing and querying must not run the named class's
139+
// static initializer; only the application deciding to instantiate it should.
140+
final Options options = PatternOptionBuilder.parsePattern("c+");
141+
final CommandLine line = new DefaultParser().parse(options, new String[] {"-c", ApiPluginImpl.class.getName()});
142+
final Class<?> cls = line.getParsedOptionValue("c");
143+
assertEquals(ApiPluginImpl.class, cls);
144+
// The isAssignableFrom gate a caller uses to reject non-plugins runs without initializing the class.
145+
assertTrue(Plugin.class.isAssignableFrom(cls));
146+
assertFalse(apiPluginInitializerRan);
147+
// Only when the application instantiates the class does its static initializer run.
148+
final Object instance = cls.getConstructor().newInstance();
149+
assertTrue(instance instanceof Plugin);
150+
assertTrue(apiPluginInitializerRan);
151+
}
152+
124153
@Test
125154
void testDate() throws Exception {
126155
assertThrows(java.text.ParseException.class, () -> Converter.DATE.apply("whatever"));

0 commit comments

Comments
 (0)