/*
* This file is part of muCommander, http://www.mucommander.com
* Copyright (C) 2002-2010 Maxence Bernard
*
* muCommander is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* muCommander is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.mucommander.command;
import com.mucommander.commons.file.AbstractFile;
import com.mucommander.commons.file.FileFactory;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.io.File;
/**
* Runs tests on {@link Command}.
* @author Nicolas Rinaudo
*/
public class CommandTest {
// - Constants -------------------------------------------------------------
// -------------------------------------------------------------------------
/** Test command's alias. */
private static final String ALIAS = "alias";
/** Test command's command. */
private static final String COMMAND = "ls -la";
/** Test command's display name. */
private static final String DISPLAY_NAME = "test";
// - Instance fields -------------------------------------------------------
// -------------------------------------------------------------------------
/** Used while testing keyword substitution. */
private AbstractFile[] files;
// - Initialisation --------------------------------------------------------
// -------------------------------------------------------------------------
/**
* Creates a batch of files used for testing.
*/
@BeforeClass
public void setUp() {
try {
files = new AbstractFile[6];
files[0] = FileFactory.getFile(System.getProperty("user.dir"));
files[1] = FileFactory.getFile(System.getProperty("user.dir") + System.getProperty("file.separator") + "test.txt");
files[2] = FileFactory.getFile(System.getProperty("user.home"));
files[3] = FileFactory.getFile(System.getProperty("user.home") + System.getProperty("file.separator") + "test.txt");
files[4] = FileFactory.getFile(System.getProperty("java.home"));
files[5] = FileFactory.getFile(System.getProperty("java.home") + System.getProperty("file.separator") + "test.txt");
}
// This is assumed never to happen.
catch(Exception e) {}
}
// - Simple keyword substitution -------------------------------------------
// -------------------------------------------------------------------------
/**
* Tests the <code>$f</code> keyword.
*/
@Test
public void testPathSubstitution() {
String[] tokens;
// Makes sure single file substitution works.
tokens = Command.getTokens("$f", files[0]);
assert 1 == tokens.length;
assert files[0].getAbsolutePath().equals(tokens[0]);
// Makes sure multiple file substitution works.
tokens = Command.getTokens("$f", files);
assert files.length == tokens.length;
for(int i = 0; i < 3; i++)
assert files[i].getAbsolutePath().equals(tokens[i]);
}
/**
* Returns the specified file's parent, or an empty string if it doesn't have one.
* @param file file whose parent should be returned.
* @return the specified file's parent, or an empty string if it doesn't have one.
*/
private String getParent(AbstractFile file) {
AbstractFile parent;
if((parent = file.getParent()) == null)
return "";
return parent.getAbsolutePath();
}
/**
* Tests the <code>$p</code> keyword.
*/
@Test
public void testParentSubstitution() {
String[] tokens;
// Makes sure single file substitution works.
tokens = Command.getTokens("$p", files[0]);
assert 1 == tokens.length;
assert getParent(files[0]).equals(tokens[0]);
// Makes sure multiple file substitution works.
tokens = Command.getTokens("$p", files);
assert files.length == tokens.length;
for(int i = 0; i < 3; i++)
assert getParent(files[i]).equals(tokens[i]);
}
/**
* Returns the specified file's extension, or <code>""</code> if it doesn't have one.
* @return the specified file's extension.
*/
private String getExtension(AbstractFile file) {
String ext;
if((ext = file.getExtension()) == null)
return "";
return ext;
}
/**
* Tests the <code>$e</code> keyword.
*/
@Test
public void testExtensionSubstitution() {
String[] tokens;
// Makes sure single file substitution works (on directory).
tokens = Command.getTokens("$e", files[0]);
assert 1 == tokens.length;
assert getExtension(files[0]).equals(tokens[0]);
// Makes sure single file substitution works (on file).
tokens = Command.getTokens("$e", files[1]);
assert 1 == tokens.length;
assert getExtension(files[1]).equals(tokens[0]);
// Makes sure multiple file substitution works.
tokens = Command.getTokens("$e", files);
assert files.length == tokens.length;
for(int i = 0; i < 3; i++)
assert getExtension(files[i]).equals(tokens[i]);
}
/**
* Tests the <code>$b</code> keyword.
*/
@Test
public void testBasenameSubstitution() {
String[] tokens;
// Makes sure single file substitution works.
tokens = Command.getTokens("$b", files[0]);
assert 1 == tokens.length;
assert files[0].getNameWithoutExtension().equals(tokens[0]);
// Makes sure multiple file substitution works.
tokens = Command.getTokens("$b", files);
assert files.length == tokens.length;
for(int i = 0; i < 3; i++)
assert files[i].getNameWithoutExtension().equals(tokens[i]);
}
/**
* Tests the <code>$n</code> keyword.
*/
@Test
public void testNameSubstitution() {
String[] tokens;
// Makes sure single file substitution works.
tokens = Command.getTokens("$n", files[0]);
assert 1 == tokens.length;
assert files[0].getName().equals(tokens[0]);
// Makes sure multiple file substitution works.
tokens = Command.getTokens("$n", files);
assert files.length == tokens.length;
for(int i = 0; i < 3; i++)
assert files[i].getName().equals(tokens[i]);
}
/**
* Tests the <code>$j</code> keyword.
*/
@Test
public void testCurrentDirSubstitution() {
String[] tokens;
// Makes sure single file substitution works.
tokens = Command.getTokens("$j", files[0]);
assert 1 == tokens.length;
assert new File(System.getProperty("user.dir")).getAbsolutePath().equals(tokens[0]);
// Makes sure multiple file substitution works.
tokens = Command.getTokens("$j", files);
assert 1 == tokens.length;
assert new File(System.getProperty("user.dir")).getAbsolutePath().equals(tokens[0]);
}
// - Tokenisation ----------------------------------------------------------
// -------------------------------------------------------------------------
/**
* Runs tests on parsing behaviour with illegal keywords.
*/
@Test
public void testIllegalKeywords() {
String[] tokens;
// Makes sure unfinished keywords at the end of a command are kept.
tokens = Command.getTokens("ls -la $", files);
assert 3 == tokens.length;
assert "ls".equals(tokens[0]);
assert "-la".equals(tokens[1]);
assert "$".equals(tokens[2]);
// Makes sure illegal keywords are not replaced.
tokens = Command.getTokens("ls $a");
assert 2 == tokens.length;
assert "ls".equals(tokens[0]);
assert "$a".equals(tokens[1]);
// Makes sure unfinished keywords are not replaced.
tokens = Command.getTokens("ls $ la");
assert 3 == tokens.length;
assert "ls".equals(tokens[0]);
assert "$".equals(tokens[1]);
assert "la".equals(tokens[2]);
}
/**
* Runs tests on command parsing (with keyword substitution).
*/
@Test
public void testParsingWithSubstitution() {
String[] tokens;
StringBuilder buffer;
// Makes sure keywords are tokenised when not escaped.
tokens = Command.getTokens("ls $f", files);
assert 1 + files.length == tokens.length;
assert "ls".equals(tokens[0]);
for(int i = 0; i < files.length; i++)
assert tokens[i + 1].equals(files[i].getAbsolutePath());
// Makes sure keywords are not tokenised when escaped.
tokens = Command.getTokens("ls \"$f\"", files);
buffer = new StringBuilder("\"");
buffer.append(files[0].getAbsolutePath());
for(int i = 1; i < files.length; i++) {
buffer.append(' ');
buffer.append(files[i].getAbsolutePath());
}
buffer.append("\"");
assert 2 == tokens.length;
assert "ls".equals(tokens[0]);
assert buffer.toString().equals(tokens[1]);
// Makes sure that keyword substitution happens even if the keyword
// is not a single token.
tokens = Command.getTokens("ls$fla", files[0]);
assert 1 == tokens.length;
assert ("ls" + files[0].getAbsolutePath() + "la").equals(tokens[0]);
tokens = Command.getTokens("ls$fla", files);
assert files.length == tokens.length;
assert ("ls" + files[0].getAbsolutePath()).equals(tokens[0]);
for(int i = 1; i < files.length - 1; i++)
assert files[i].getAbsolutePath().equals(tokens[i]);
assert (files[files.length - 1].getAbsolutePath() + "la").equals(tokens[tokens.length - 1]);
}
/**
* Runs tests on command parsing (without keyword substitution).
*/
@Test
public void testParsingWithoutSubstitution() {
String[] tokens;
// Makes sure simple command parsing works.
tokens = Command.getTokens("ls -la");
assert 2 == tokens.length;
assert "ls".equals(tokens[0]);
assert "-la".equals(tokens[1]);
// Makes sure spaces are trimmed when they're expected to.
tokens = Command.getTokens("ls -la ");
assert 2 == tokens.length;
assert "ls".equals(tokens[0]);
assert "-la".equals(tokens[1]);
// Makes sure quotes:
// - escape spaces.
// - are not removed from the command.
tokens = Command.getTokens("ls \"- l a\"");
assert 2 == tokens.length;
assert "ls".equals(tokens[0]);
assert "\"- l a\"".equals(tokens[1]);
// Makes sure spaces are not trimmed when they're not expected to.
tokens = Command.getTokens("ls \"- l a \"");
assert 2 == tokens.length;
assert "ls".equals(tokens[0]);
assert "\"- l a \"".equals(tokens[1]);
// Makes sure \s:
// - escape quotes.
// - are removed from the command.
tokens = Command.getTokens("ls \\\"- l a");
assert 4 == tokens.length;
assert "ls".equals(tokens[0]);
assert "\"-".equals(tokens[1]);
assert "l".equals(tokens[2]);
assert "a".equals(tokens[3]);
// Makes sure \s:
// - escape spaces.
// - are remoed from the command.
tokens = Command.getTokens("ls My\\ Documents");
assert 2 ==tokens.length;
assert "ls".equals(tokens[0]);
assert "My Documents".equals(tokens[1]);
// Makes sure 'complex' tokenisation works.
tokens = Command.getTokens("/usr/bin/find . -name \\\\*.java -exec sh -c \"echo {}; wc {}\" \\\\;");
assert 9 == tokens.length;
assert "/usr/bin/find".equals(tokens[0]);
assert ".".equals(tokens[1]);
assert "-name".equals(tokens[2]);
assert "\\*.java".equals(tokens[3]);
assert "-exec".equals(tokens[4]);
assert "sh".equals(tokens[5]);
assert "-c".equals(tokens[6]);
assert "\"echo {}; wc {}\"".equals(tokens[7]);
assert "\\;".equals(tokens[8]);
}
// - Constructors tests ----------------------------------------------------
// -------------------------------------------------------------------------
/**
* Makes sure the specified command matches the specified arguments.
*/
private void checkCommand(Command command, CommandType type, boolean isDisplayNameSet) {
// Tests common values.
assert ALIAS.equals(command.getAlias());
assert COMMAND.equals(command.getCommand());
assert type == command.getType();
// Tests context dependant values.
if(isDisplayNameSet) {
assert command.isDisplayNameSet();
assert DISPLAY_NAME.equals(command.getDisplayName());
}
else {
assert !command.isDisplayNameSet();
assert ALIAS.equals(command.getDisplayName());
}
}
/**
* Makes sure all constructors initialise a command to the right values.
*/
@Test
public void testConstructors() {
// Tests the 2 arguments constructor.
checkCommand(new Command(ALIAS, COMMAND), CommandType.NORMAL_COMMAND, false);
// Tests the 3 arguments constructor.
checkCommand(new Command(ALIAS, COMMAND, CommandType.NORMAL_COMMAND), CommandType.NORMAL_COMMAND, false);
checkCommand(new Command(ALIAS, COMMAND, CommandType.SYSTEM_COMMAND), CommandType.SYSTEM_COMMAND, false);
checkCommand(new Command(ALIAS, COMMAND, CommandType.INVISIBLE_COMMAND), CommandType.INVISIBLE_COMMAND, false);
// Tests the 4 arguments constructor.
checkCommand(new Command(ALIAS, COMMAND, CommandType.NORMAL_COMMAND, DISPLAY_NAME), CommandType.NORMAL_COMMAND, true);
checkCommand(new Command(ALIAS, COMMAND, CommandType.SYSTEM_COMMAND, DISPLAY_NAME), CommandType.SYSTEM_COMMAND, true);
checkCommand(new Command(ALIAS, COMMAND, CommandType.INVISIBLE_COMMAND, DISPLAY_NAME), CommandType.INVISIBLE_COMMAND, true);
}
}