Testing JavaCC on a File? - javacc

So after I compile my code, I want it to read input from a file instead of the command line.
So instead of doing this:
javacc Ex.jj
javac *.java
java Ex "x+2"
I want to do this:
javacc Ex.jj
javac *.java
java test.txt
Where test.txt has this in it:
"x+4"

You can declare a class with a main method in your syntax file:
options {
STATIC = false;
IGNORE_CASE = false;
}
PARSER_BEGIN(Ex)
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class Ex {
public static void main(String[] args) {
try (InputStream in = new FileInputStream(args[0])) {
Ex parser = new Ex(in, "UTF-8");
double r = parser.expr();
System.out.println("Result: " + r);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
PARSER_END(Ex)
...
SKIP : { " " | "\r" | "\n" | "\t" }
TOKEN: {
...
}
double expr(): {
}
{
...
}

Related

How to print subcommand result automatically?

I have Java CLI application based on cliche library and I want to migrate it to picocli.
My application was based on cliche so I have a lot of methods with asg.cliche.Command annotation which return some result. cliche prints command methods's result automatically so result was printed in command line. I replaced asg.cliche.Command annotations by picocli.CommandLine.Command and I see that picocli does not print command methods's results.
I have following class:
import picocli.CommandLine;
#CommandLine.Command(subcommandsRepeatable = true)
public class Foo
{
public static void main( String[] args )
{
new CommandLine( new Foo() ).execute( args );
}
#CommandLine.Command
public String sayHello()
{
return "Hello";
}
#CommandLine.Command
public String sayGoodbye()
{
return "GoodBye";
}
}
when I call java -cp myJar.jar Foo sayHello sayGoodbye I do not see any output.
I see three solutions:
1. Modify each methods to print result instead of return it.
import picocli.CommandLine;
#CommandLine.Command( subcommandsRepeatable = true )
public class Foo2
{
public static void main( String[] args )
{
new CommandLine( new Foo2() ).execute( args );
}
#CommandLine.Command
public void sayHello()
{
System.out.println( "Hello" );
}
#CommandLine.Command
public void sayGoodbye()
{
System.out.println( "GoodBye" );
}
}
I am not happy with this solution. I prefer not modify my methods.
Retrieve results after execution.
public static void main( String[] args )
{
final CommandLine commandLine = new CommandLine( new Foo() );
commandLine.execute( args );
CommandLine.ParseResult parseResult = commandLine.getParseResult();
for( CommandLine.ParseResult pr : parseResult.subcommands() )
{
System.out.println( pr.commandSpec().commandLine()
.getExecutionResult()
.toString() );
}
}
I see a few problems with this solution. The main problem is formatting. Execution result can be null, array, collection. The second problem is that results are printed after execution of all subcommands. If second subcommand throws exception then I firstly see exception stack trace and after that I see result of first subcommand.
Ask on stackoverflow if there is some better solution. I do not believe that there is no any configuration option in picocli which enable results printing.
Personally, I like your first solution best, it is simple and easy to maintain. Maybe introduce a helper method for the printing and formatting so the command methods can look like this:
#CommandLine.Command
public String sayGoodbye()
{
return printValue("GoodBye");
}
You already found the CommandLine.getParseResult method; perhaps a helper method could assist with the formatting there as well.
There is a third option, but it is unfortunately quite a bit more complex: you can create a custom IExecutionStrategy that prints the result of each command after executing it. It involves copying a lot of code from the picocli internals and it’s not really a realistic solution; I just mention it for completeness.
// extend RunLast to handle requests for help/version and exit code stuff
class PrintingExecutionStrategy extends CommandLine.RunLast {
#Override
protected List<Object> handle(ParseResult parseResult) throws ExecutionException {
// Simplified: executes only the last subcommand (so no repeating subcommands).
// Look at RunLast.executeUserObjectOfLastSubcommandWithSameParent if you need repeating subcommands.
List<CommandLine> parsedCommands = parseResult.asCommandLineList();
CommandLine last = parsedCommands.get(parsedCommands.size() - 1);
return execute(last, new ArrayList<Object>());
}
// copied from CommandLine.executeUserObject,
// modified to print the execution result
private List<Object> execute(CommandLine cmd, List<Object> executionResultList) throws Exception {
Object command = parsed.getCommand();
if (command instanceof Runnable) {
try {
((Runnable) command).run();
parsed.setExecutionResult(null); // 4.0
executionResultList.add(null); // for compatibility with picocli 2.x
return executionResultList;
} catch (ParameterException ex) {
throw ex;
} catch (ExecutionException ex) {
throw ex;
} catch (Exception ex) {
throw new ExecutionException(parsed, "Error while running command (" + command + "): " + ex, ex);
}
} else if (command instanceof Callable) {
try {
#SuppressWarnings("unchecked") Callable<Object> callable = (Callable<Object>) command;
Object executionResult = callable.call();
System.out.println(executionResult); <-------- print result
parsed.setExecutionResult(executionResult);
executionResultList.add(executionResult);
return executionResultList;
} catch (ParameterException ex) {
throw ex;
} catch (ExecutionException ex) {
throw ex;
} catch (Exception ex) {
throw new ExecutionException(parsed, "Error while calling command (" + command + "): " + ex, ex);
}
} else if (command instanceof Method) {
try {
Method method = (Method) command;
Object[] parsedArgs = parsed.getCommandSpec().argValues();
Object executionResult;
if (Modifier.isStatic(method.getModifiers())) {
executionResult = method.invoke(null, parsedArgs); // invoke static method
} else if (parsed.getCommandSpec().parent() != null) {
executionResult = method.invoke(parsed.getCommandSpec().parent().userObject(), parsedArgs);
} else {
executionResult = method.invoke(parsed.factory.create(method.getDeclaringClass()), parsedArgs);
}
System.out.println(executionResult); <-------- print result
parsed.setExecutionResult(executionResult);
executionResultList.add(executionResult);
return executionResultList;
} catch (InvocationTargetException ex) {
Throwable t = ex.getTargetException();
if (t instanceof ParameterException) {
throw (ParameterException) t;
} else if (t instanceof ExecutionException) {
throw (ExecutionException) t;
} else {
throw new ExecutionException(parsed, "Error while calling command (" + command + "): " + t, t);
}
} catch (Exception ex) {
throw new ExecutionException(parsed, "Unhandled error while calling command (" + command + "): " + ex, ex);
}
}
throw new ExecutionException(parsed, "Parsed command (" + command + ") is not a Method, Runnable or Callable");
}
}
Use it like this:
public static void main(String... args) {
new CommandLine(new Foo())
.setExecutionStrategy(new PrintingExecutionStrategy())
.execute(args);
}
I wouldn’t recommend the above.
Update: I thought of another, fourth, option (actually a variation of your 2nd solution). You can specify a custom IExecutionExceptionHandler that doesn’t print the stacktrace, but instead stores the exception so you can print the stacktrace after printing the command results. Something like this:
class MyHandler extends IExecutionExceptionHandler() {
Exception exception;
public int handleExecutionException(Exception ex,
CommandLine commandLine,
ParseResult parseResult) {
//ex.printStackTrace(); // no stack trace
exception = ex;
}
}
Use it like this:
public static void main(String... args) {
MyHandler handler = new MyHandler();
CommandLine cmd = new CommandLine(new Foo())
.setExecutionExceptionHandler(handler);
cmd.execute(args);
ParseResult parseResult = cmd.getParseResult();
for( ParseResult pr : parseResult.subcommands() )
{
System.out.println( pr.commandSpec().commandLine()
.getExecutionResult()
.toString() );
}
if (handler.exception != null) {
handler.exception.printStackTrace();
}
}

How not to match a token within quote like “hello w"orld in javacc

I'm doing a redis-cli parser by using javacc. I have to handle the quote
for example set "a b" "cd", I hope key token is a b and value token is cd.
There is my solution:
RedisCommand.java
package com.demo.command;
public interface RedisCommand {
}
SetCommand .java
package com.demo.command;
public class SetCommand implements RedisCommand{
private String key;
private String value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
RedisCommand.jj
options {
STATIC = false;
DEBUG_PARSER=true;
}
PARSER_BEGIN(RedisCommandParser)
package com.demo.parser;
import com.demo.command.*;
import java.util.*;
public class RedisCommandParser {
public static void main(String args[]) throws ParseException {
RedisCommandParser parser = new RedisCommandParser(System.in);
parser.RedisCommand();
}
}
PARSER_END(RedisCommandParser)
SKIP :
{
<WHITESPACE: " " | "\t" | "\n" | "\r">
}
TOKEN :
{
<K_SET: "set">
}
TOKEN :
{
<SINGLE_QUOTE: "'">
| <DOUBLE_QUOTE: "\"">
| <SINGLE_STRING: <SINGLE_QUOTE> ((~["'"]) | "\\'" )+ <SINGLE_QUOTE>>
| <DOUBLE_STRING: <DOUBLE_QUOTE> ((~["\""]) | "\\\"" )+ <DOUBLE_QUOTE>>
| <RAW_STRING: (~[" "])+>
}
RedisCommand RedisCommand() :
{
RedisCommand command = null;
}
{
command=SetCommand() <EOF>
{
return command;
}
}
SetCommand SetCommand() :
{
SetCommand command = new SetCommand();
String key = null;
String value = null;
}
{
<K_SET> key=StringParam() value=StringParam()
{
command.setKey(key);
command.setValue(value);
return command;
}
}
String StringParam() :
{
String s = null;
Token token = null;
String im = null;
}
{
(token=<SINGLE_STRING> { im=token.image; s=im.substring(1, im.length()-1);}
| token=<DOUBLE_STRING> { im=token.image; s=im.substring(1, im.length()-1);}
| s=RawString()
)
{return s;}
}
String RawString() :
{}
{
/* for reserved word
* support like 'set set set'
*/
(<K_SET>
| <RAW_STRING>
)
{
return token.image;
}
}
SetCommandTest.java
package com.demo.command;
import com.demo.parser.ParseException;
import com.demo.parser.RedisCommandParser;
import org.junit.Test;
import java.io.StringReader;
public class SetCommandTest {
#Test
public void test() throws ParseException {
//test1
_test("set a b", "a", "b");
//test2
_test("set \"a b\" cd", "a b", "cd");
//test3
_test("set a\"b c\"d", "a\"b", "c\"d");
//test4
_test("set \"ab c\"d", "\"ab", "c\"d");
}
private void _test(String line, String expectKey, String expectValue) throws ParseException {
RedisCommandParser parser = new RedisCommandParser(new StringReader(line));
SetCommand command = (SetCommand) parser.RedisCommand();
String key = command.getKey();
assert key.equals(expectKey) : String.format("command[%s] key[%s] expect[%s]", line, key, expectKey);
String value = command.getValue();
assert value.equals(expectValue) : String.format("command[%s] value[%s] expect[%s]", line, value, expectValue);
}
}
test4 in SetCommandTest failed, error message is
Call: RedisCommand
Call: SetCommand
Consumed token: <"set" at line 1 column 1>
Call: StringParam
Consumed token: <<DOUBLE_STRING>: ""ab c"" at line 1 column 5>
Return: StringParam
Call: StringParam
Call: RawString
Consumed token: <<RAW_STRING>: "d" at line 1 column 11>
Return: RawString
Return: StringParam
Return: SetCommand
Consumed token: <<EOF> at line 1 column 11>
Return: RedisCommand
java.lang.AssertionError: command[set "ab c"d] key[ab c] expect["ab]
at com.demo.command.SetCommandTest._test(SetCommandTest.java:33)
at com.demo.command.SetCommandTest.test(SetCommandTest.java:26)
It take "ab c" as <DOUBLE_STRING>, which is not what I want. I think the problem is <DOUBLE_STRING>, quote after space and quote before space should work fine. Not all quote string is <DOUBLE_STRING>. but I don't know how to do. Please help me

Extent Report showing only one test case result when executing cucumber scripts in parallel using Cucable plugin

I have to generate Extent Report from all executed test scripts. I am running scripts in parallel. When I use TestNG or Selenium Grid for parallel execution, in those implementation, Extent Reports are getting generated perfectly covering each executed test scripts. But when I run scripts in parallel using Cucable Plugin, Extent report gets generated but would have only 1 test case report if 2 test cases were there in execution.
I am using Cucumber (Selenium), Junit Suite Runner, Cucable Plugin
I verified Extent Report code is thread safe. So not sure, why only in case of Cucable Plugin, Extent report gets only 1 test case. Someone told me, In case of testNG, testNG itself provides additional thread safe mechanism which helps internally to have all executed test cases in report.
ExtentTestManager.java
package com.jacksparrow.automation.extent.listeners;
import java.io.IOException;
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.ExtentTest;
import com.aventstack.extentreports.MediaEntityBuilder;
import com.aventstack.extentreports.Status;
import com.aventstack.extentreports.markuputils.ExtentColor;
import com.aventstack.extentreports.markuputils.Markup;
import com.aventstack.extentreports.markuputils.MarkupHelper;
public class ExtentTestManager {
public static ThreadLocal<ExtentTest> testReport = new ThreadLocal<ExtentTest>();
static ExtentReports extent = ExtentManager.getReporter();
public static synchronized ExtentTest getTest() {
return testReport.get();
}
public static synchronized void setTest(ExtentTest tst)
{
testReport.set(tst);
}
public static synchronized void logInfo(String message) {
testReport.get().info(message);
}
public static synchronized void logPass(String message) {
testReport.get().pass(message);
}
public static synchronized void scenarioPass() {
String passLogg = "SCENARIO PASSED";
Markup m = MarkupHelper.createLabel(passLogg, ExtentColor.GREEN);
testReport.get().log(Status.PASS, m);
}
public static synchronized void logFail(String message) {
testReport.get().fail(message);
}
public static synchronized boolean addScreenShotsOnFailure() {
ExtentManager.captureScreenshot();
try {
testReport.get().fail("<b>" + "<font color=" + "red>" + "Screenshot of failure" + "</font>" + "</b>",
MediaEntityBuilder.createScreenCaptureFromPath(ExtentManager.screenshotName).build());
} catch (IOException e) {
}
String failureLogg = "SCENARIO FAILED";
Markup m = MarkupHelper.createLabel(failureLogg, ExtentColor.RED);
testReport.get().log(Status.FAIL, m);
return true;
}
public static synchronized boolean addScreenShots() {
ExtentManager.captureScreenshot();
try {
testReport.get().info(("<b>" + "<font color=" + "green>" + "Screenshot" + "</font>" + "</b>"),
MediaEntityBuilder.createScreenCaptureFromPath(ExtentManager.screenshotName).build());
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
public static synchronized ExtentTest startTest(String testName) {
return startTest(testName, "");
}
public static synchronized ExtentTest startTest(String testName, String desc) {
ExtentTest test = extent.createTest(testName, desc);
testReport.set(test);
return test;
}
}
ExtentManager.java
package com.jacksparrow.automation.extent.listeners;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import com.jacksparrow.automation.utilities.DriverManager;
import com.aventstack.extentreports.AnalysisStrategy;
import com.aventstack.extentreports.ExtentReports;
import com.aventstack.extentreports.reporter.ExtentHtmlReporter;
import com.aventstack.extentreports.reporter.configuration.ChartLocation;
import com.aventstack.extentreports.reporter.configuration.Theme;
public class ExtentManager {
static ExtentReports extent;
static Date d = new Date();
static String fileName = "Extent_" + d.toString().replace(":", "_").replace(" ", "_") + ".html";
public synchronized static ExtentReports getReporter() {
if (extent == null) {
ExtentHtmlReporter htmlReporter = new ExtentHtmlReporter(System.getProperty("user.dir")+"/target/extent-report/"+fileName);
htmlReporter.loadXMLConfig(".\\src\\test\\resources\\extent-config.xml");
htmlReporter.config().setTestViewChartLocation(ChartLocation.BOTTOM);
htmlReporter.config().setChartVisibilityOnOpen(true);
htmlReporter.config().setTheme(Theme.STANDARD);
htmlReporter.config().setDocumentTitle(fileName);
htmlReporter.config().setEncoding("utf-8");
htmlReporter.config().setReportName(fileName);
//htmlReporter.setAppendExisting(true);
extent = new ExtentReports();
extent.setAnalysisStrategy(AnalysisStrategy.TEST);
extent.attachReporter(htmlReporter);
extent.setSystemInfo("Automation Analyst", "Robin Tyagi");
extent.setSystemInfo("Organization", "Way2Automation");
extent.setSystemInfo("Build no", "W2A-1234");
}
return extent;
}
public static String screenshotPath;
public static String screenshotName;
static int i=0;
public static void captureScreenshot() {
i = i + 1;
File scrFile = ((TakesScreenshot) DriverManager.getDriver()).getScreenshotAs(OutputType.FILE);
Date d = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("E dd MMM HH:mm:ss z yyyy");
String strDate = formatter.format(d);
screenshotName = strDate.replace(":", "_").replace(" ", "_") + "_"+i+".jpg";
try {
FileUtils.copyFile(scrFile, new File(System.getProperty("user.dir") + "/target/extent-report/" + screenshotName));
} catch (IOException e) {
e.printStackTrace();
}
}
public static void createExtentReportDirectory() {
File file = new File(System.getProperty("user.dir") + "/target/extent-report/");
if (!file.exists()) {
if (file.mkdir()) {
} else {
}
}
}
}
Please help me to understand what could be the correct thought in order to generate Extent Report having summary of all executed test scripts when Cucable Plugin is used for achieving parallel execution in Cucumber (Selenium)
After migrating to cucumber 4.0, I am able to generate single consolidated extent report. Thank you.

java.nio.file.FileSystemException when I move a file

I'm trying to move image files from beforePath to afterPath, and below is my Code
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
public class ImageClass {
String fileName, beforePath, afterPath;
void moveFile() {
afterPath = afterPath + "\\" + fileName;
beforePath = beforePath + "\\" + fileName;
System.out.println(beforePath + " ,and, " + afterPath);
Path movefrom = FileSystems.getDefault().getPath(beforePath);
Path target = FileSystems.getDefault().getPath(afterPath);
try {
Files.move(movefrom, target, REPLACE_EXISTING);
} catch (IOException e) {
System.err.println(e);
}
}
}
however the code returns java.nio.file.FileSystemException to me and it says that another process is already using the file. I tried many ways but I can't. How can I fix it?

Vaadin 7: File Upload

I have a Upload component in which I´m supposed to import a xml file in order to parse it.
I´m trying to use the File.createTempFile method to create the file phisically,but something weird is going on.
For example,if I take the file named "test.xml" and use the createTempFile method to create it on the disk,the name of the generate file becomes something like 'test.xml13234xml'.How can I create the file the correct way?
This is expected when using i.e. createTempFile method as it implicitly creates a file with random prefix:
// a part of createTempFile method
private static final SecureRandom random = new SecureRandom();
static File generateFile(String prefix, String suffix, File dir) {
long n = random.nextLong();
if (n == Long.MIN_VALUE) {
n = 0; // corner case
} else {
n = Math.abs(n);
}
return new File(dir, prefix + Long.toString(n) + suffix);
}
which should give something like 'test.xml13234xml'.
If you want to create a file with the correct name and keep it for later use you can rename/move it within uploadSucceeded method.
public class ExampleUpload implements Upload.Receiver, Upload.SucceededListener {
private Upload xmlUpload;
private File tempFile;
public ExampleUpload() {
this.xmlUpload = new Upload("Upload:", this);
this.xmlUpload.addSucceededListener(this);
}
#Override
public OutputStream receiveUpload(String filename, String mimeType) {
try {
tempFile = File.createTempFile(filename, "xml");
tempFile.deleteOnExit();
return new FileOutputStream(tempFile);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
public void uploadSucceeded(SucceededEvent event) {
try {
File destinationFile = new File("c:\\" + event.getFilename());
FileUtils.moveFile(tempFile, destinationFile));
// TODO read and parse destinationFile
} catch (IOException e) {
e.printStackTrace();
}
}
}

Resources