Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@
</properties>
<dependencies>
<dependency>
<groupId>org.cactoos</groupId>
<artifactId>cactoos</artifactId>
<version>0.57.0</version>
<groupId>info.picocli</groupId>
<artifactId>picocli</artifactId>
<version>4.7.7</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
Expand Down
101 changes: 45 additions & 56 deletions src/main/java/org/eolang/aoi/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,75 +4,64 @@
*/
package org.eolang.aoi;

import java.io.PrintStream;
import java.util.Arrays;
import java.util.List;
import org.cactoos.io.ResourceOf;
import org.cactoos.text.TextOf;
import java.nio.file.Path;
import java.util.concurrent.Callable;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;

/**
* Command-line interface for the AOI (Abstract Object Inference) tool.
*
* <p>This class handles command-line argument parsing and coordinates the execution
* of the AOI tool.</p>
* Command-line interface for the AOI tool.
* <p>
* Implementing {@link Callable} allows Picocli to treat this class as a command that returns an
* exit code.
* </p>
*
* @since 0.0.4
*/
public final class Application {

@Command(
name = "aoi",
description = {
"AOI analyzes EO programs to infer object types. It finds .xmir files in the",
"input directory and generates .xml files with type information."
},
descriptionHeading = "%nDescription:%n",
parameterListHeading = "%nArguments:%n",
optionListHeading = "%nOptions:%n"
)
public final class Application implements Callable<Integer> {
/**
* Command-line arguments passed to the application.
* A standard help option that triggers Picocli's built-in help display.
*/
private final String[] args;
@Option(
names = "--help",
usageHelp = true,
description = "Print this message and exit."
)
private boolean help;

/**
* Output stream for printing messages and help text.
* The first positional argument, representing the input directory.
*/
private final PrintStream out;
@Parameters(
index = "0",
paramLabel = "<input dir>",
description = "Directory with .xmir files (searches recursively)"
)
private Path input;

/**
* Creates a new application instance.
*
* <p>The arguments array is defensively copied to prevent external modification.</p>
*
* @param args Command-line arguments
* @param out Output stream for messages
* The second positional argument, representing the output directory.
*/
public Application(final String[] args, final PrintStream out) {
this.args = Arrays.copyOf(args, args.length);
this.out = out;
}
@Parameters(
index = "1",
paramLabel = "<output dir>",
description = "Directory for .xml files with inferred types"
)
private Path output;

/**
* Executes the main application logic.
*
* <p>Note: {@code --help} and {@code --version} flags take precedence over other arguments and
* will be processed even if other arguments are invalid.</p>
*
* @throws IllegalArgumentException if the number of arguments is not exactly 2 (when neither
* {@code --help} nor {@code --version} is specified)
*/
public void run() {
final List<String> arguments = Arrays.asList(this.args);
if (arguments.contains("--help")) {
this.out.print(new TextOf(new ResourceOf("org/eolang/aoi/help.txt")));
} else if (arguments.contains("--version")) {
this.out.printf(
"aoi version %s",
new TextOf(new ResourceOf("org/eolang/aoi/version.txt"))
);
} else {
if (arguments.size() != 2) {
throw new IllegalArgumentException(
"Expected 2 arguments (input dir and output dir), but got %d: %s".formatted(
arguments.size(),
String.join(", ", arguments)
)
);
}
this.out.printf(
"Input directory: %s, Output directory: %s%n", this.args[0], this.args[1]
);
}
@Override
public Integer call() throws Exception {
return 0;
}
}
8 changes: 5 additions & 3 deletions src/main/java/org/eolang/aoi/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
*/
package org.eolang.aoi;

import picocli.CommandLine;

/**
* Main entry point for the AOI (Abstract Object Inference) application.
*
Expand All @@ -18,11 +20,11 @@ private Main() {
}

/**
* Runs the application.
* Executes the CLI and terminates the JVM with the resulting exit code.
*
* @param args Command-line arguments
* @param args Command-line arguments passed to the application.
*/
public static void main(final String[] args) {
new Application(args, System.out).run();
System.exit(new CommandLine(new Application()).execute(args));
}
}
14 changes: 0 additions & 14 deletions src/main/resources/org/eolang/aoi/help.txt

This file was deleted.

110 changes: 110 additions & 0 deletions src/test/java/org/eolang/aoi/ApplicationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 Objectionary.com
* SPDX-License-Identifier: MIT
*/
package org.eolang.aoi;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.Path;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import picocli.CommandLine;

/**
* Tests for {@link Application}.
*
* @since 0.0.5
* @todo #152:15min Enable help flag tests after adding support for the short `-h` flag.
* Once implemented, remove @Disabled from the following tests:
* {@link ApplicationTest#applicationPrintsHelpMessageWhenHelpFlagIsPassed},
* {@link ApplicationTest#applicationExitsWithZeroCodeWhenHelpFlagIsPassed}
*/
final class ApplicationTest {
@Test
void applicationExitsWithZeroCodeOnSuccessfulExecution(
@TempDir final Path input,
@TempDir final Path output
) {
final CommandLine cmd = new CommandLine(new Application());
final int exit = cmd.execute(input.toString(), output.toString());
MatcherAssert.assertThat(
"Application did not exit with a zero code on successful execution",
exit,
Matchers.is(0)
);
}

@Test
void applicationPrintsNothingToStderrOnSuccessfulExecution(
@TempDir final Path input,
@TempDir final Path output
) {
final CommandLine cmd = new CommandLine(new Application());
final StringWriter stderr = new StringWriter();
cmd.setErr(new PrintWriter(stderr));
cmd.execute(input.toString(), output.toString());
MatcherAssert.assertThat(
"Application printed to stderr during a successful execution",
stderr.toString(),
Matchers.emptyString()
);
}

@Disabled
@ParameterizedTest
@ValueSource(strings = {"--help", "-h"})
void applicationPrintsHelpMessageWhenHelpFlagIsPassed(final String flag) {
final CommandLine cmd = new CommandLine(new Application());
final StringWriter stdout = new StringWriter();
cmd.setOut(new PrintWriter(stdout));
cmd.execute(flag);
MatcherAssert.assertThat(
"Application did not print the help message to stdout for the %s flag".formatted(flag),
stdout.toString(),
Matchers.containsString("Usage:")
);
}

@Disabled
@ParameterizedTest
@ValueSource(strings = {"--help", "-h"})
void applicationExitsWithZeroCodeWhenHelpFlagIsPassed(final String flag) {
final CommandLine cmd = new CommandLine(new Application());
final int exit = cmd.execute(flag);
MatcherAssert.assertThat(
"Application did not exit with a zero code when the %s flag was used".formatted(flag),
exit,
Matchers.is(0)
);
}

@Test
void applicationExitsWithNonZeroCodeWhenNoArgumentsAreProvided() {
final CommandLine cmd = new CommandLine(new Application());
cmd.setErr(new PrintWriter(new StringWriter()));
final int exit = cmd.execute();
MatcherAssert.assertThat(
"Application did not exit with a non-zero code when required arguments were missing",
exit,
Matchers.not(0)
);
}

@Test
void applicationExitsWithNonZeroCodeWhenOneArgumentIsMissing() {
final CommandLine cmd = new CommandLine(new Application());
cmd.setErr(new PrintWriter(new StringWriter()));
final int exit = cmd.execute("input/dir");
MatcherAssert.assertThat(
"Application did not exit with a non-zero code when one argument was missing",
exit,
Matchers.not(0)
);
}
}
28 changes: 0 additions & 28 deletions src/test/java/org/eolang/aoi/DummyTest.java

This file was deleted.

6 changes: 6 additions & 0 deletions src/test/java/org/eolang/aoi/package-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,10 @@
* SPDX-FileCopyrightText: Copyright (c) 2025 Objectionary.com
* SPDX-License-Identifier: MIT
*/

/**
* Tests for {@link org.eolang.aoi}.
*
* @since 0.0.5
*/
package org.eolang.aoi;