Fix test, license, minor code cmpliance

Signed-off-by: Emmanuel Bigeon <emmanuel@bigeon.fr>
This commit is contained in:
Emmanuel Bigeon 2017-11-13 22:38:32 -05:00
parent 83c02f82ec
commit 283090d361
14 changed files with 321 additions and 54 deletions

View File

@ -75,7 +75,8 @@ public class ExitCommand implements ICommand {
} }
@Override @Override
public void execute(final ConsoleOutput output, final ConsoleInput input, final String... args) { public final void execute(final ConsoleOutput output,
final ConsoleInput input, final String... args) {
beforeExit(); beforeExit();
app.exit(); app.exit();
} }
@ -83,18 +84,18 @@ public class ExitCommand implements ICommand {
/* (non-Javadoc) /* (non-Javadoc)
* @see fr.bigeon.gclc.command.ICommand#getCommandName() */ * @see fr.bigeon.gclc.command.ICommand#getCommandName() */
@Override @Override
public String getCommandName() { public final String getCommandName() {
return name; return name;
} }
@Override @Override
public void help(final ConsoleOutput manager, public final void help(final ConsoleOutput manager,
final String... args) throws IOException { final String... args) throws IOException {
manager.println( manager.println(
CLIPrompterMessages.getString(EXIT_MAN, (Object[]) args)); CLIPrompterMessages.getString(EXIT_MAN, (Object[]) args));
} }
@Override @Override
public String tip() { public final String tip() {
return CLIPrompterMessages.getString(EXIT); return CLIPrompterMessages.getString(EXIT);
} }
} }

View File

@ -60,7 +60,9 @@ public interface ICommand {
void execute(ConsoleOutput out, ConsoleInput in, void execute(ConsoleOutput out, ConsoleInput in,
String... args) throws CommandRunException; String... args) throws CommandRunException;
/** @return the command's name */ /** Get teh command name.
*
* @return the command's name */
String getCommandName(); String getCommandName();
/** This prints the help associated to this command. /** This prints the help associated to this command.

View File

@ -61,7 +61,7 @@ public final class SubedCommand extends CommandProvider implements ICommand {
private final ICommand noArgCommand; private final ICommand noArgCommand;
/** A tip on this command. */ /** A tip on this command. */
private final String tip; private final String tip;
/** The name of the command */ /** The name of the command. */
private final String name; private final String name;
/** Create the command that defines sub commands. /** Create the command that defines sub commands.

View File

@ -51,7 +51,7 @@ public final class CommandRunException extends Exception {
/** The type of run exception. */ /** The type of run exception. */
private final CommandRunExceptionType type; private final CommandRunExceptionType type;
/** The command that caused the error. */ /** The command that caused the error. */
private final ICommand source; private transient ICommand source;
/** Create the exception. /** Create the exception.
* *

View File

@ -1,3 +1,37 @@
/*
* Copyright Bigeon Emmanuel (2014)
*
* emmanuel@bigeon.fr
*
* This software is a computer program whose purpose is to
* provide a generic framework for console applications.
*
* This software is governed by the CeCILL license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/or redistribute the software under the terms of the CeCILL
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited
* liability.
*
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
*/
/** /**
* gclc:fr.bigeon.gclc.exception.package-info.java * gclc:fr.bigeon.gclc.exception.package-info.java
* Created on: Nov 13, 2017 * Created on: Nov 13, 2017

View File

@ -1,3 +1,37 @@
/*
* Copyright Bigeon Emmanuel (2014)
*
* emmanuel@bigeon.fr
*
* This software is a computer program whose purpose is to
* provide a generic framework for console applications.
*
* This software is governed by the CeCILL license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/or redistribute the software under the terms of the CeCILL
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited
* liability.
*
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
*/
/** /**
* gclc:fr.bigeon.gclc.i18n.package-info.java * gclc:fr.bigeon.gclc.i18n.package-info.java
* Created on: Nov 13, 2017 * Created on: Nov 13, 2017

View File

@ -128,14 +128,13 @@ public final class ReadingRunnable implements Runnable {
private final BufferedReader reader; private final BufferedReader reader;
/** the state of this runnable. */ /** the state of this runnable. */
private boolean running = true; private boolean running = true;
/** Synchro object. */ /** Synchro object. */
private final Object lock = new Object(); private final Object lock = new Object();
/** The waiting status for a message. */ /** The waiting status for a message. */
private boolean waiting; private boolean waiting;
/** The blocker for a given message. */ /** The blocker for a given message. */
private final Map<String, Object> messageBlocker = new HashMap<>(); private final Map<String, Object> messageBlocker = new HashMap<>();
/** The lock */ /** The lock. */
private final Object messageBlockerLock = new Object(); private final Object messageBlockerLock = new Object();
/** The message being delivered. */ /** The message being delivered. */
private String delivering; private String delivering;
@ -162,6 +161,23 @@ public final class ReadingRunnable implements Runnable {
return res; return res;
} }
/** do wait for a message.
* <p>This method should only be called inside a loop.
* @param timeout the timeout of the wait.
* @throws IOException if the runnable was stopped and no essage was found.
*/
private void doWaitMessage(final long timeout) throws IOException {
try {
lock.wait(timeout);
} catch (final InterruptedException e) {
LOGGER.log(Level.SEVERE, THREAD_INTERRUPTION_EXCEPTION, e);
Thread.currentThread().interrupt();
}
if (messages.isEmpty() && !running) {
throw new IOException(CLOSED_PIPE);
}
}
/** Get the next message. /** Get the next message.
* *
* @return the next read message * @return the next read message
@ -172,17 +188,7 @@ public final class ReadingRunnable implements Runnable {
throw new IOException(CLOSED_PIPE); throw new IOException(CLOSED_PIPE);
} }
waiting = true; waiting = true;
while (messages.isEmpty()) { waitMessage(TIMEOUT);
try {
lock.wait(TIMEOUT);
} catch (final InterruptedException e) {
LOGGER.log(Level.SEVERE, THREAD_INTERRUPTION_EXCEPTION, e);
Thread.currentThread().interrupt();
}
if (messages.isEmpty() && !running) {
throw new IOException(CLOSED_PIPE);
}
}
LOGGER.finest("Polled: " + messages.peek()); //$NON-NLS-1$ LOGGER.finest("Polled: " + messages.peek()); //$NON-NLS-1$
waiting = false; waiting = false;
notifyMessage(messages.peek()); notifyMessage(messages.peek());
@ -201,15 +207,7 @@ public final class ReadingRunnable implements Runnable {
throw new IOException(CLOSED_PIPE); throw new IOException(CLOSED_PIPE);
} }
waiting = true; waiting = true;
try { doWaitMessage(timeout);
lock.wait(timeout);
} catch (final InterruptedException e) {
LOGGER.log(Level.SEVERE, THREAD_INTERRUPTION_EXCEPTION, e);
Thread.currentThread().interrupt();
}
if (messages.isEmpty() && !running) {
throw new IOException(CLOSED_PIPE);
}
waiting = false; waiting = false;
if (messages.isEmpty()) { if (messages.isEmpty()) {
return null; return null;
@ -342,4 +340,15 @@ public final class ReadingRunnable implements Runnable {
this.running = running; this.running = running;
} }
} }
/** Wait for the next message to be integratted.
*
* @param timeout the timeout to wait
* @throws IOException if the next message was not delivered and the
* runnable stopped. */
private void waitMessage(final long timeout) throws IOException {
while (messages.isEmpty()) {
doWaitMessage(timeout);
}
}
} }

View File

@ -38,8 +38,6 @@
*/ */
package fr.bigeon.gclc.manager; package fr.bigeon.gclc.manager;
import java.io.IOException;
/** A console output that absorbs every message. /** A console output that absorbs every message.
* *
* @author Emmanuel Bigeon */ * @author Emmanuel Bigeon */
@ -55,7 +53,7 @@ public final class SinkOutput implements ConsoleOutput {
/* (non-Javadoc) /* (non-Javadoc)
* @see fr.bigeon.gclc.manager.ConsoleOutput#close() */ * @see fr.bigeon.gclc.manager.ConsoleOutput#close() */
@Override @Override
public void close() throws IOException { public void close() {
// //
} }
@ -69,14 +67,14 @@ public final class SinkOutput implements ConsoleOutput {
/* (non-Javadoc) /* (non-Javadoc)
* @see fr.bigeon.gclc.manager.ConsoleOutput#print(java.lang.String) */ * @see fr.bigeon.gclc.manager.ConsoleOutput#print(java.lang.String) */
@Override @Override
public void print(final String text) throws IOException { public void print(final String text) {
// //
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see fr.bigeon.gclc.manager.ConsoleOutput#println() */ * @see fr.bigeon.gclc.manager.ConsoleOutput#println() */
@Override @Override
public void println() throws IOException { public void println() {
// //
} }
@ -84,7 +82,7 @@ public final class SinkOutput implements ConsoleOutput {
* @see fr.bigeon.gclc.manager.ConsoleOutput#println(java.lang.String) * @see fr.bigeon.gclc.manager.ConsoleOutput#println(java.lang.String)
*/ */
@Override @Override
public void println(final String message) throws IOException { public void println(final String message) {
// //
} }

View File

@ -85,7 +85,7 @@ public final class WritingRunnable implements Runnable {
* *
* @param message the message * @param message the message
* @throws IOException if the pipe is closed */ * @throws IOException if the pipe is closed */
public synchronized void addMessage(final String message) throws IOException { public void addMessage(final String message) throws IOException {
synchronized (lock) { synchronized (lock) {
if (!running) { if (!running) {
throw new IOException("Closed pipe"); //$NON-NLS-1$ throw new IOException("Closed pipe"); //$NON-NLS-1$
@ -124,7 +124,7 @@ public final class WritingRunnable implements Runnable {
/** Set the running status. /** Set the running status.
* *
* @param running the running to set */ * @param running the running to set */
public synchronized void setRunning(final boolean running) { public void setRunning(final boolean running) {
synchronized (lock) { synchronized (lock) {
this.running = running; this.running = running;
} }

View File

@ -1,3 +1,37 @@
/*
* Copyright Bigeon Emmanuel (2014)
*
* emmanuel@bigeon.fr
*
* This software is a computer program whose purpose is to
* provide a generic framework for console applications.
*
* This software is governed by the CeCILL license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/or redistribute the software under the terms of the CeCILL
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited
* liability.
*
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
*/
/** /**
* gclc:fr.bigeon.gclc.manager.package-info.java * gclc:fr.bigeon.gclc.manager.package-info.java
* Created on: Nov 13, 2017 * Created on: Nov 13, 2017

View File

@ -1,3 +1,37 @@
/*
* Copyright Bigeon Emmanuel (2014)
*
* emmanuel@bigeon.fr
*
* This software is a computer program whose purpose is to
* provide a generic framework for console applications.
*
* This software is governed by the CeCILL license under French law and
* abiding by the rules of distribution of free software. You can use,
* modify and/or redistribute the software under the terms of the CeCILL
* license as circulated by CEA, CNRS and INRIA at the following URL
* "http://www.cecill.info".
*
* As a counterpart to the access to the source code and rights to copy,
* modify and redistribute granted by the license, users are provided only
* with a limited warranty and the software's author, the holder of the
* economic rights, and the successive licensors have only limited
* liability.
*
* In this respect, the user's attention is drawn to the risks associated
* with loading, using, modifying and/or developing or reproducing the
* software by the user in light of its specific status of free software,
* that may mean that it is complicated to manipulate, and that also
* therefore means that it is reserved for developers and experienced
* professionals having in-depth computer knowledge. Users are therefore
* encouraged to load and test the software's suitability as regards their
* requirements in conditions enabling the security of their systems and/or
* data to be ensured and, more generally, to use and operate it in the
* same conditions as regards security.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL license and that you accept its terms.
*/
/** /**
* gclc:fr.bigeon.gclc.tools.package-info.java * gclc:fr.bigeon.gclc.tools.package-info.java
* Created on: Nov 13, 2017 * Created on: Nov 13, 2017

View File

@ -38,6 +38,10 @@
*/ */
package fr.bigeon.gclc.command; package fr.bigeon.gclc.command;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException; import java.io.IOException;
import org.junit.Test; import org.junit.Test;
@ -78,6 +82,21 @@ public class CommandTest {
}; };
cmd.help(test); cmd.help(test);
// name
assertEquals("First line should be command name", "name",
test.readNextLine());
// tip
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
// Usage
test.readNextLine();
// details
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
assertFalse("Only 6 line should be printed", test.available());
cmd = new Command("name") { cmd = new Command("name") {
@Override @Override
@ -98,6 +117,20 @@ public class CommandTest {
} }
}; };
cmd.help(test); cmd.help(test);
// name
assertEquals("First line should be command name", "name",
test.readNextLine());
// tip
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
// Usage
test.readNextLine();
// details
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
assertFalse("Only 6 line should be printed", test.available());
cmd = new Command("name") { cmd = new Command("name") {
@ -126,6 +159,20 @@ public class CommandTest {
} }
}; };
cmd.help(test); cmd.help(test);
// name
assertEquals("First line should be command name", "name",
test.readNextLine());
// tip
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
// Usage
test.readNextLine();
// details
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
assertFalse("Only 6 line should be printed", test.available());
cmd = new Command("name") { cmd = new Command("name") {
@ -154,6 +201,20 @@ public class CommandTest {
} }
}; };
cmd.help(test); cmd.help(test);
// name
assertEquals("First line should be command name", "name",
test.readNextLine());
// tip
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
// Usage
test.readNextLine();
// details
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
assertFalse("Only 6 line should be printed", test.available());
cmd = new Command("name") { cmd = new Command("name") {
@ -177,6 +238,20 @@ public class CommandTest {
} }
}; };
cmd.help(test); cmd.help(test);
// name
assertEquals("First line should be command name", "name",
test.readNextLine());
// tip
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
// Usage
test.readNextLine();
// details
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
assertFalse("Only 6 line should be printed", test.available());
cmd = new Command("name") { cmd = new Command("name") {
@ -200,6 +275,24 @@ public class CommandTest {
} }
}; };
cmd.help(test); cmd.help(test);
// name
assertEquals("First line should be command name", "name",
test.readNextLine());
// tip
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
// Usage
test.readNextLine();
// pattern
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
// details
assertEquals("Unexpected detail", "details", test.readNextLine());
assertFalse("Only 6 line should be printed", test.available());
cmd = new Command("name") { cmd = new Command("name") {
@Override @Override
@ -222,6 +315,22 @@ public class CommandTest {
} }
}; };
cmd.help(test); cmd.help(test);
// name
assertEquals("First line should be command name", "name",
test.readNextLine());
// tip
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
// Usage
test.readNextLine();
// pattern
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
// details
assertEquals("Unexpected detail", "details", test.readNextLine());
assertFalse("Only 6 line should be printed", test.available());
cmd = new Command("name") { cmd = new Command("name") {
@ -245,6 +354,22 @@ public class CommandTest {
} }
}; };
cmd.help(test); cmd.help(test);
// name
assertEquals("First line should be command name", "name",
test.readNextLine());
// tip
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
// Usage
test.readNextLine();
// pattern
test.readNextLine();
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
//
assertTrue("Section line is empty", test.readNextLine().isEmpty());
assertFalse("Only 6 line should be printed", test.available());
} }
} }

View File

@ -38,6 +38,7 @@
*/ */
package fr.bigeon.gclc.command; package fr.bigeon.gclc.command;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import java.io.IOException; import java.io.IOException;
@ -95,16 +96,6 @@ public class HelpExecutorTest {
} }
} }
/** Test method for
* {@link fr.bigeon.gclc.command.HelpExecutor#HelpExecutor(java.lang.String, fr.bigeon.gclc.manager.ConsoleManager, fr.bigeon.gclc.command.ICommand)}.
*
* @throws IOException if an IO occurs */
@Test
public final void testHelpExecutor() throws IOException {
HelpExecutor help;
help = new HelpExecutor("?", new MockCommand("mock"));
}
/** Test method for {@link fr.bigeon.gclc.command.HelpExecutor#tip()}. /** Test method for {@link fr.bigeon.gclc.command.HelpExecutor#tip()}.
* *
* @throws IOException */ * @throws IOException */
@ -113,7 +104,7 @@ public class HelpExecutorTest {
try (PipedConsoleOutput test = new PipedConsoleOutput()) { try (PipedConsoleOutput test = new PipedConsoleOutput()) {
final HelpExecutor help = new HelpExecutor("?", final HelpExecutor help = new HelpExecutor("?",
new MockCommand("mock")); new MockCommand("mock"));
help.tip(); assertNotNull("Tip should be provided", help.tip());
help.help(test); help.help(test);
} }
try (PipedConsoleOutput test = new PipedConsoleOutput()) { try (PipedConsoleOutput test = new PipedConsoleOutput()) {

View File

@ -38,6 +38,7 @@
*/ */
package fr.bigeon.gclc.manager; package fr.bigeon.gclc.manager;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -51,7 +52,8 @@ import java.nio.charset.Charset;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
/** <p> /**
* <p>
* TODO * TODO
* *
* @author Emmanuel Bigeon */ * @author Emmanuel Bigeon */
@ -85,7 +87,8 @@ public class ReadingRunnableTest {
* @throws InterruptedException * @throws InterruptedException
* @throws IOException */ * @throws IOException */
@Test @Test
public final void testGetWaitForDelivery() throws InterruptedException, IOException { public final void testGetWaitForDelivery() throws InterruptedException,
IOException {
try (PipedOutputStream out = new PipedOutputStream(); try (PipedOutputStream out = new PipedOutputStream();
InputStream piped = new PipedInputStream(out); InputStream piped = new PipedInputStream(out);
BufferedReader reader = new BufferedReader( BufferedReader reader = new BufferedReader(
@ -112,6 +115,8 @@ public class ReadingRunnableTest {
}, "get"); }, "get");
th2.start(); th2.start();
th.join(); th.join();
assertFalse("Runnable should have consumed every message",
runnable.hasMessage());
runnable.setRunning(false); runnable.setRunning(false);
out.close(); out.close();
} }