├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── examples
├── arrays.javauto
├── controlFlow.javauto
├── conversion.javauto
├── globalVariables.javauto
├── javaIntegration.javauto
├── logicalOperators.javauto
├── mathOperators.javauto
├── notifier.javauto
├── stringFormatting.javauto
├── structsData.javauto
├── udf.javauto
├── userInput.javauto
└── variables.javauto
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── automation
│ │ └── javauto
│ │ ├── Javauto.java
│ │ ├── compiler
│ │ ├── CustomJarCompiler.java
│ │ ├── CustomJavaCompiler.java
│ │ └── DealWithCompilerErrors.java
│ │ ├── debugger
│ │ └── SimpleDebugger.java
│ │ └── parser
│ │ └── Create.java
└── resources
│ └── Javauto.java
└── test
├── java
└── com
│ └── automation
│ └── javauto
│ └── test
│ ├── JavautoTest.java
│ └── TestPanel.java
└── resources
├── fermat.txt
└── script
└── tests.javauto
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | test-output
3 | apidocs
4 | apidocs.json
5 | .classpath
6 | .project
7 | .settings
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 |
3 | jdk:
4 | - oraclejdk8
5 |
6 | matrix:
7 | fast_finish: true
8 |
9 | before_install:
10 | - "export DISPLAY=:99.0"
11 | - "sh -e /etc/init.d/xvfb start"
12 |
13 | script:
14 | - "mvn clean install"
15 | - "java -jar /home/travis/build/Javauto/javauto-core/target/javauto-1.1.0.jar /home/travis/build/Javauto/javauto-core/src/test/resources/script/tests.javauto"
16 | - "java -jar tests.jar"
17 |
18 | sudo: false
19 |
20 | notifications:
21 | webhooks:
22 | urls:
23 | - https://webhooks.gitter.im/e/56a42f65b462c237bbe9
24 | on_success: change
25 | on_failure: always
26 | on_start: false
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2015 Javauto
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | Javauto is a programming language for automation. Derived from Java, it is a cross platform alternative to something like AutoIt.
4 |
5 |  [](https://gitter.im/Javauto/javauto-core?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6 |
7 | # Links
8 |
9 | * Website: http://javauto.github.io/
10 | * Gitter.im chats: [javauto-core](https://gitter.im/Javauto/javauto-core?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge#)
11 | * [Javauto Helper](https://github.com/Javauto/javauto-helper) exists to simplify the process of finding mouse coordinates and pixel colors.
12 | * [Java Lookup](https://github.com/Javauto/javauto-lookup) helps a user find relevant documentation for a specific function.
13 | * StackOverflow: questions with the [javauto](http://stackoverflow.com/questions/tagged/javauto) tag
14 | * Syntax highlighting and auto completion for Javauto files in [Notepad++](https://github.com/Javauto/javauto-notepad-plusplus)
15 | * If you're looking to report a bug, please use the [issue tracker](https://github.com/Javauto/javauto-core/issues).
16 | * [Twitter account](https://twitter.com/JavautoL)
17 |
18 | # Projects Using Javauto
19 |
20 | * [adbutil](https://github.com/ohtejera/adbutil) - A simple Javauto (cross platform) wrapper around Android Debug Bridge to enable multi device support.
21 | * [ImperiusGeorge Client](https://github.com/ohtejera/JavautoImperiusGeorge) - A test automation library which drives off the UI of Android native applications.
22 |
23 |
24 |
25 | # License
26 |
27 | Javauto is licensed under the terms of the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html)
28 |
--------------------------------------------------------------------------------
/examples/arrays.javauto:
--------------------------------------------------------------------------------
1 | // define two arrays
2 | String[] strArr = {"each", "of", "these", "is", "an", "element"};
3 | int[] intArr = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34};
4 |
5 | print( strArr[0] ); // print the first element of the string array
6 | strArr[0] = "new!"; // change the first element
7 | print( strArr[0] ); // print it again
8 |
9 | // we can get the size of the array with .length
10 | int strArrSize = strArr.length; // this will return 6, there are six elements
11 |
12 | // print the last element
13 | print( strArr[strArrSize-1] ); // the last element is one less than the length
14 |
15 | // print everything in the intArray
16 | print("Index\tValue");
17 | for (int i = 0; i < intArr.length; i++) {
18 | print( toString(i) + "\t" + toString( intArr[i] ) );
19 | }
--------------------------------------------------------------------------------
/examples/controlFlow.javauto:
--------------------------------------------------------------------------------
1 | int a = -1;
2 | if (a > 0) {
3 | print( "%s is positive!" % ( toString(a) ) );
4 | } else if (a < 0) {
5 | print( "%s is negative!" % ( toString(a) ) );
6 | } else {
7 | // if it isn't positive or negative it's 0
8 | print( "%s is zero" % ( toString(a) ) );
9 | }
10 |
11 |
12 | String name = "john";
13 | if (name == "john") { // this compares the two addresses in memory, will not always be true
14 | print("This will not always happen");
15 | }
16 | if (name.equals("john")) { // this compares the contents of the string, will equal true
17 | print("This should always happend");
18 | }
19 |
20 |
21 | int i = 0;
22 | while ( i <= 5 ) {
23 | print(i);
24 | i = i + 1; // add one to i
25 | }
26 |
27 | for (int c = 0; c <= 5; c++) {
28 | print(c);
29 | }
30 |
31 | String[] alpha = {"a","b","c","d","e","f"};
32 | for (String letter : alpha) {
33 | print(letter);
34 | }
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/examples/conversion.javauto:
--------------------------------------------------------------------------------
1 | String input = input("Enter a number: "); // get their number as a string
2 | int number = toInt(input); // get number as an int
3 | print(input + " + 5 = " + toString(number + 5)); // add five to it and display as string
4 | print(number/2); // divide number by 2 (will return an integer)
5 | print(toDouble(number)/2); // convert number to double and then divide
--------------------------------------------------------------------------------
/examples/globalVariables.javauto:
--------------------------------------------------------------------------------
1 | global String var; // let the compiler know it's global
2 | var = "A variable";
3 | func void printVar() {
4 | print(var); // print our var
5 | }
6 | printVar();
--------------------------------------------------------------------------------
/examples/javaIntegration.javauto:
--------------------------------------------------------------------------------
1 | import java.util.Date;
2 |
3 | //both of the below are valid
4 | System.out.println("Printing with Java");
5 | print("Printing with Javauto");
6 |
7 | Date date = new Date();
8 | // display time and date using toString()
9 | System.out.println(date.toString());
10 |
--------------------------------------------------------------------------------
/examples/logicalOperators.javauto:
--------------------------------------------------------------------------------
1 | int a = 10;
2 | int b = 3;
3 | int c = 3;
4 | boolean bool = true;
5 |
6 | print(a > b); // 10 > 3 => true
7 | print(b < a); // 3 < 10 => true
8 | print(b > c); // 3 is not greater than 3 => false
9 | print(b == c); // 3 does equal 3 => true
10 | print(c != a); // 3 does not equal 10 => true
11 | print(b >= c); // 3 is equal to 3, so greate than or equals works => true
12 | print(b <= c); // less than will also work => true
13 |
14 | print(bool); // true is true
15 | print(!bool); // !true is the same as not true = false
16 |
17 | // statements can be grouped in ()
18 | print( !( (a + b) < c ) ); // evaluates to not (13 < 3). 13 is not less than 3. not (false) => true
19 |
20 | // the and operator is &&
21 | print( (b < a) && (c < a) ); // both are true => true
22 | print( (b < a) && (a < c) ); // a is not less than c => false
23 |
24 | // the or operator is ||
25 | print( (b < a) || (a < c) ); // as long as one is true or is satisfied => true
26 | print( (!bool) || (a < c) ); // if neither is true => false
--------------------------------------------------------------------------------
/examples/mathOperators.javauto:
--------------------------------------------------------------------------------
1 | int a = 10;
2 | int b = 3;
3 |
4 | print("10 + 3 = " + (a + b)); // add the two
5 | print("10 x 3 = " + (a * b)); // multiply the two
6 | print("10 / 3 = " + (a / b)); // divide the two, since the result is in int it will be truncated, so instead of 3.333333333 it returns 3
7 | print("10 % 3 = " + (a % b)); // get the remainder. 10 divided by 3 has a remainder of 1
--------------------------------------------------------------------------------
/examples/notifier.javauto:
--------------------------------------------------------------------------------
1 | //Check program arguments.
2 | if(args.length == 0){
3 | printHelp();
4 | }
5 |
6 | if (!isFlagged(args, "-u") || !isFlagged(args, "-p") ) {
7 | printHelp();
8 | }
9 |
10 | do {
11 | notify(getFlaggedArg(args, "-u"));
12 | sleep(toInt(getFlaggedArg(args, "-p")));
13 | } while(true);
14 |
15 | // Print program help and exit.
16 | func void printHelp(){
17 | print("Usage: notifier.jar -u URL -p Time (Inserts a fixed delay between httpGet [milliseconds])");
18 | print("Example: java -jar notifier.jar -u http://www.javauto.org -p 1000 ");
19 | System.exit(0);
20 | }
21 |
22 | func void notify(String url){
23 | String response = httpGet(url);
24 | if(response.isEmpty()){
25 | print( "[ERROR] %s is not reachable! You may panic now." % (url) );
26 | } else {
27 | print( "[OK] %s is online" % (url));
28 | }
29 | }
--------------------------------------------------------------------------------
/examples/stringFormatting.javauto:
--------------------------------------------------------------------------------
1 | String name = "John";
2 | String greeting = "Hello %s, I'm %s." % (name, "Javauto");
3 | print(greeting);
--------------------------------------------------------------------------------
/examples/structsData.javauto:
--------------------------------------------------------------------------------
1 | // define a struct for a user datatype
2 | struct user {
3 | String ID;
4 | }
5 |
6 | // define a function that can return a variable of type user
7 | func user getUser() {
8 | user c = new user(); // create an instance of this type of variable
9 | c.ID = USER_NAME.toLowerCase() + "@" + SYSTEM_OS.toLowerCase(); // assign it an ID
10 | return c; // return all this data wrapped in our user datatype
11 | }
12 |
13 | // now we call this function and store the data in "us"
14 | user us = getUser();
15 |
16 | // display its ID
17 | print("USER ID: %s" % (us.ID));
18 |
--------------------------------------------------------------------------------
/examples/udf.javauto:
--------------------------------------------------------------------------------
1 | //User Defined Functions
2 |
3 | // Define a function to move the mouse to random coordinates.
4 | // This function is void, meaning it doesn't return any value.
5 | func void randomMouseMove() {
6 | int x = intGetRandom(0, 500); // get a random int for x
7 | int y = intGetRandom(0, 500); // get a random int for y
8 | mouseMove(x,y); // move the mouse to these generated coordinates
9 | }
10 |
11 | msgBox("Moving the mouse to random coordinates...");
12 | randomMouseMove(); // execute the function
13 |
14 |
15 | // This function tells us whether the mouse
16 | // is on the left side of the screen.
17 | func boolean isLeft() {
18 | int xCoord = cursorGetPos()[0]; // get the x mouse position
19 |
20 | if (xCoord < (SCREEN_WIDTH / 2)) { // if we're left of the half way point
21 | return true;
22 | } else {
23 | return false;
24 | }
25 | }
26 |
27 | if (isLeft()) {
28 | print("The cursor is on the left side of the screen.");
29 | } else {
30 | print("The cursor is not on the left side of the screen.");
31 | }
32 |
--------------------------------------------------------------------------------
/examples/userInput.javauto:
--------------------------------------------------------------------------------
1 | // get input from command line and print it
2 | String userResponse = input("Enter your name: "); // get user input from the console
3 | String greeting = "Hello " + userResponse + ", it's nice to meet you.";
4 | print(greeting);
5 |
6 | // get input from a dialog box and display response in a message box
7 | userResponse = inputBox("Enter your name");
8 | greeting = "Hello " + userResponse + ", it's nice to meet you.";
9 | msgBox(greeting, "Hello There");
--------------------------------------------------------------------------------
/examples/variables.javauto:
--------------------------------------------------------------------------------
1 | // the type must be specified when defining each variable
2 | String str = "This is a string."; // Strings must be enclosed in double quotes
3 | int number = 100;
4 | double pi = 3.1415926535;
5 | boolean b = true;
6 |
7 | // since these variables have already been defined we don't have to specify their types
8 | str = "A different string.";
9 | number = number - 50; // subtract 50 from our number
10 | pi = pi * 2; // double pi's value
11 | b = false; // change b's value
12 |
13 | // print it all
14 | print(str);
15 | print(number);
16 | print(pi);
17 | print(b);
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.automation
5 | javauto
6 | 1.1.0
7 |
8 | Javauto
9 | http://javauto.org
10 | Javauto is a programming language for automation.
11 |
12 |
13 | UTF-8
14 | 1.8
15 | 1.8
16 |
17 |
18 |
19 |
20 | junit
21 | junit
22 | 4.12
23 |
24 |
25 |
26 | org.assertj
27 | assertj-core
28 | 3.1.0
29 |
30 |
31 |
32 | commons-lang
33 | commons-lang
34 | 2.1
35 |
36 |
37 |
38 | org.codehaus.plexus
39 | plexus-utils
40 | 1.1
41 |
42 |
43 |
44 |
45 |
46 |
47 | org.apache.maven.plugins
48 | maven-compiler-plugin
49 |
50 | ${maven.compiler.source}
51 | ${maven.compiler.target}
52 |
53 |
54 |
55 | maven-antrun-plugin
56 | 1.8
57 |
58 |
59 | copy-javauto-file
60 | package
61 |
62 |
63 |
64 |
66 |
67 |
68 |
69 | run
70 |
71 |
72 |
73 |
74 |
75 | org.apache.maven.plugins
76 | maven-jar-plugin
77 | 2.6
78 |
79 |
80 | com/automation/javauto/Javauto.class
81 | com/automation/javauto/Javauto$1.class
82 |
83 |
84 |
85 | true
86 | com.automation.javauto.parser.Create
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/src/main/java/com/automation/javauto/compiler/CustomJarCompiler.java:
--------------------------------------------------------------------------------
1 | package com.automation.javauto.compiler;
2 |
3 | import java.io.BufferedInputStream;
4 | import java.io.BufferedOutputStream;
5 | import java.io.File;
6 | import java.io.FileInputStream;
7 | import java.io.FileNotFoundException;
8 | import java.io.FileOutputStream;
9 | import java.io.IOException;
10 | import java.util.Map;
11 | import java.util.jar.Attributes;
12 | import java.util.jar.JarEntry;
13 | import java.util.jar.JarOutputStream;
14 | import java.util.jar.Manifest;
15 | import java.util.zip.Deflater;
16 |
17 | /**
18 | * Takes a directory and adds each class file within it to a JAR file.
19 | *
20 | * @author matthew.downey
21 | *
22 | */
23 | public class CustomJarCompiler {
24 | /* define constants for different terminal colors */
25 | private static String GREEN = "\033[92m";
26 | private static String YELLOW = "\033[93m";
27 | private static String NORMAL = "\033[0m";
28 |
29 | public static boolean colors = true;
30 |
31 | public static boolean verbose = false;
32 |
33 | public static void create(String output, String mainClass, String inputDir)
34 | throws IOException {
35 | if (!colors) {
36 | GREEN = "";
37 | YELLOW = "";
38 | NORMAL = "";
39 | }
40 | verbose("Building " + GREEN + (new File(output)).getAbsolutePath()
41 | + NORMAL);
42 | Manifest manifest = new Manifest();
43 | manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION,
44 | "1.0");
45 | manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, mainClass);
46 | JarOutputStream target = new JarOutputStream(new FileOutputStream(
47 | output), manifest);
48 | add(new File(inputDir), target);
49 | target.close();
50 | }
51 |
52 | private static void add(File source, JarOutputStream target)
53 | throws IOException {
54 | BufferedInputStream in = null;
55 | try {
56 | if (source.isDirectory()) {
57 | String name = source.getPath().replace("\\", "/");
58 | if (!name.isEmpty()) {
59 | if (!name.endsWith("/"))
60 | name += "/";
61 | JarEntry entry = new JarEntry(name);
62 | entry.setTime(source.lastModified());
63 | target.putNextEntry(entry);
64 | target.closeEntry();
65 | }
66 | for (File nestedFile : source.listFiles())
67 | add(nestedFile, target);
68 | return;
69 | }
70 |
71 | JarEntry entry = new JarEntry(source.getName());
72 | entry.setTime(source.lastModified());
73 | target.putNextEntry(entry);
74 | in = new BufferedInputStream(new FileInputStream(source));
75 |
76 | byte[] buffer = new byte[1024];
77 | while (true) {
78 | int count = in.read(buffer);
79 | if (count == -1)
80 | break;
81 | target.write(buffer, 0, count);
82 | }
83 | target.closeEntry();
84 | verbose("\tadded " + YELLOW + source.getName() + NORMAL);
85 | } finally {
86 | if (in != null)
87 | in.close();
88 | }
89 | }
90 |
91 | private static void verbose(String msg) {
92 | if (verbose)
93 | System.out.println(msg);
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/com/automation/javauto/compiler/CustomJavaCompiler.java:
--------------------------------------------------------------------------------
1 | package com.automation.javauto.compiler;
2 |
3 | import java.net.URI;
4 | import java.util.Arrays;
5 | import java.util.List;
6 | import java.util.ArrayList;
7 | import java.io.File;
8 | import java.io.IOException;
9 |
10 | import javax.tools.Diagnostic;
11 | import javax.tools.DiagnosticCollector;
12 | import javax.tools.JavaCompiler;
13 | import javax.tools.JavaFileObject;
14 | import javax.tools.SimpleJavaFileObject;
15 | import javax.tools.ToolProvider;
16 | import javax.tools.StandardLocation;
17 | import javax.tools.StandardJavaFileManager;
18 | import javax.tools.JavaCompiler.CompilationTask;
19 | import javax.tools.JavaFileObject.Kind;
20 |
21 | /**
22 | * Takes Java code and generates a class file. Errors are sent to
23 | * {@link DealWithCompilerErrors}.
24 | *
25 | * @author matthew.downey
26 | *
27 | */
28 | public class CustomJavaCompiler {
29 | public static DiagnosticCollector compile(String name,
30 | String code, String outDir, String classpath) throws IOException {
31 | /* get JavaCompiler object to create the .class file */
32 | JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
33 |
34 | /* throw an exception if there's an issue with the compiler */
35 | if (compiler == null) {
36 | throw new NullPointerException(
37 | "Couldn't find java system compiler.");
38 | }
39 |
40 | /* get a file manager object that lets us control the output location */
41 | StandardJavaFileManager fileManager = compiler.getStandardFileManager(
42 | null, null, null);
43 |
44 | /* tell the file manager where to put the generated class files */
45 | fileManager.setLocation(StandardLocation.CLASS_OUTPUT,
46 | Arrays.asList(new File(outDir)));
47 |
48 | /*
49 | * tell the file manager where to look for related class files that may
50 | * be referenced
51 | */
52 | fileManager.setLocation(StandardLocation.CLASS_PATH,
53 | Arrays.asList(new File(classpath)));
54 |
55 | /*
56 | * get a DiagnosticCollector object to hold a list of
57 | * potential errors
58 | */
59 | DiagnosticCollector diagnostics = new DiagnosticCollector();
60 |
61 | /* create a JavaFileObject from our source code and class name */
62 | JavaFileObject file = new JavaSourceFromString(name, code);
63 |
64 | /* place our file as the only item in a list of files to be compiled */
65 | Iterable compilationUnits = Arrays.asList(file);
66 |
67 | /* supply the compiler with all the information required to compile */
68 | CompilationTask task = compiler.getTask(null, fileManager, diagnostics,
69 | null, null, compilationUnits);
70 |
71 | /*
72 | * compile it -- note that errors will be inserted into our diagnostics
73 | * variable
74 | */
75 | boolean win = task.call();
76 |
77 | /* win == true if there weren't compilation errors */
78 | if (win)
79 | return null;
80 | else
81 | /* return errors */
82 | return diagnostics;
83 | }
84 | }
85 |
86 | class JavaSourceFromString extends SimpleJavaFileObject {
87 | final String code;
88 |
89 | JavaSourceFromString(String name, String code) {
90 | super(URI.create("string:///" + name.replace('.', '/')
91 | + Kind.SOURCE.extension), Kind.SOURCE);
92 | this.code = code;
93 | }
94 |
95 | @Override
96 | public CharSequence getCharContent(boolean ignoreEncodingErrors) {
97 | return code;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/com/automation/javauto/compiler/DealWithCompilerErrors.java:
--------------------------------------------------------------------------------
1 | package com.automation.javauto.compiler;
2 |
3 | import javax.tools.*;
4 | import java.io.*;
5 | import java.util.ArrayList;
6 |
7 | /**
8 | * Attempt to make any compiler errors from {@link CustomJavaCompiler} relevant
9 | * to the user's original Javauto code and display these errors.
10 | *
11 | * @author matthew.downey
12 | *
13 | */
14 | public class DealWithCompilerErrors {
15 | /**
16 | * Handle errors that may crop up during compilation. This entails letting
17 | * the user know what caused the error and where.
18 | */
19 | public static void dealWithIt(
20 | DiagnosticCollector compileErrors,
21 | String generatedCode, String userCode, String userCodeFileName) {
22 | for (Diagnostic diagnostic : compileErrors.getDiagnostics()) {
23 | /* get the text of the line the error appears on */
24 | String line = getLine(diagnostic.getPosition(), generatedCode);
25 |
26 | /*
27 | * get all line numbers in the original code that contain the error
28 | * line
29 | */
30 | ArrayList originalLineNums = getOriginalLineNums(line,
31 | userCode);
32 |
33 | /* if we only found it once in the original code we're all good! */
34 | if (originalLineNums.size() == 1) {
35 | System.out
36 | .println(userCodeFileName
37 | + " line "
38 | + (originalLineNums.get(0) + 1)
39 | + "\n"
40 | + line
41 | + "\n"
42 | + diagnostic.getKind().toString().toLowerCase()
43 | + ": "
44 | + diagnostic.getMessage(null).replace(
45 | "java.lang.", ""));
46 | }
47 |
48 | /*
49 | * if we found it more than once specify where in the generated code
50 | * to look for it and tell them to use --generate
51 | */
52 | else {
53 | String className = new File(userCodeFileName).getName().split(
54 | "\\.(?=[^\\.]+$)")[0];
55 | System.out
56 | .println("Generated file: "
57 | + className
58 | + ".java line "
59 | + getLineNumber((int) diagnostic.getPosition(),
60 | generatedCode)
61 | + "\n"
62 | + line
63 | + "\n"
64 | + diagnostic.getKind().toString().toLowerCase()
65 | + ": "
66 | + diagnostic.getMessage(null).replace(
67 | "java.lang.", ""));
68 | System.out
69 | .println("This was an error in generated code -- to understand what caused the error please compile with the --generate flag to enable the writing of generated files. During compilation a directory called \""
70 | + className
71 | + "/gen/\" will be created, and this directory will contain "
72 | + className
73 | + ".java, the file that caused the error.");
74 | }
75 | }
76 | }
77 |
78 | /**
79 | * Find the line that a character appears on based on the character
80 | * position.
81 | *
82 | * @param pos
83 | * the position of the character
84 | * @param generatedCode
85 | * the string the character position is in
86 | * @return the line number containing the character
87 | */
88 | private static int getLineNumber(int pos, String generatedCode) {
89 | int line = 1;
90 | char[] genChars = generatedCode.toCharArray();
91 | for (int i = 0; i < pos; i++)
92 | if (genChars[i] == '\n')
93 | line++;
94 | return line;
95 | }
96 |
97 | /**
98 | * Gets the line numbers in the user code of lines that exactly match the
99 | * given line of generated code. That way if a line of generated code causes
100 | * an error and appears only once in the user code we can inform the user of
101 | * the line of their code that causes an error.
102 | *
103 | * @param line
104 | * the line of generated code that causes an error
105 | * @param userCode
106 | * the user code file to match the line against
107 | * @return an ArrayList of lines that match the error line
108 | */
109 | private static ArrayList getOriginalLineNums(String line,
110 | String userCode) {
111 | ArrayList lineNums = new ArrayList();
112 | Integer l = 0;
113 | for (String userLine : userCode.split("\n")) {
114 | if (userLine.trim().equals(line.trim())
115 | || removeComments(userLine).trim().equals(line.trim())) {
116 | lineNums.add(l);
117 | }
118 | l = l + 1;
119 | }
120 | return lineNums;
121 | }
122 |
123 | /**
124 | * Get the whole line that contains the error.
125 | *
126 | * @param startPosition
127 | * the Diagnostic.getPosition() value for the error
128 | * @param generatedCode
129 | * the code that caused the error
130 | * @return the line containing the error
131 | */
132 | private static String getLine(long startPosition, String generatedCode) {
133 | /* get the line bounds */
134 | int[] bounds = getLineBounds((int) startPosition, generatedCode);
135 |
136 | /* return the line based on the bounds */
137 | return generatedCode.substring(bounds[0], bounds[1]);
138 | }
139 |
140 | private static int[] getLineBounds(int pos, String generatedCode) {
141 | /*
142 | * find the indexes of the "\n" characters on either side of the
143 | * position
144 | */
145 | return new int[] {
146 | generatedCode.substring(0, pos).lastIndexOf("\n") + 1,
147 | pos + generatedCode.substring(pos).indexOf("\n") };
148 | }
149 |
150 | private static String removeComments(String line) {
151 | ArrayList commentIgnores = getIgnoreIndexes(line).get(0);
152 | String temp = "";
153 | for (int i = 0; i < line.length(); i++) {
154 | if (!inIgnoredText(i, commentIgnores))
155 | temp = temp + line.substring(i, i + 1);
156 | }
157 | return temp;
158 | }
159 |
160 | private static boolean inIgnoredText(int charIndex,
161 | ArrayList ignoredIndexes) {
162 | /* check each set of bounds to see if they hold our charIndex */
163 | for (Integer[] i : ignoredIndexes) {
164 | if (charIndex >= i[0] && charIndex <= i[1])
165 | return true;
166 | }
167 |
168 | /* if we got to here we haven't found it inside any of the bounds */
169 | return false;
170 | }
171 |
172 | /**
173 | * Build a list of character indexes that should be ignored during
174 | * processing. Characters to be ignored are those inside of comments, string
175 | * literals, and character literals. This function returns the bounds of
176 | * indexes of characters and literals in two separate lists.
177 | *
178 | * @param code
179 | * the string to generate this list of bounds for
180 | * @return returns two ArrayList objects, wrapped inside of one
181 | * ArrayList, with the format [comment indexes, literal indexes].
182 | * Then each of those elements is a list with the format [start
183 | * ignore index, end ignore index].
184 | */
185 | private static ArrayList> getIgnoreIndexes(String code) {
186 | /* Lists to hold bounds for both comments and literals */
187 | ArrayList commentIndexes = new ArrayList();
188 | ArrayList literalIndexes = new ArrayList();
189 |
190 | /*
191 | * List to hold our other two lists, so that the user can separate them
192 | * at will
193 | */
194 | ArrayList> finalValues = new ArrayList>();
195 |
196 | /*
197 | * iterate through character by character looking for comments and
198 | * literals
199 | */
200 | char[] codeChars = code.toCharArray();
201 | int index = 0;
202 | while (index < codeChars.length) {
203 | if (codeChars[index] == '/') {
204 | Integer startIndex = -1;
205 | Integer endIndex = -1;
206 |
207 | index++;
208 | if (index >= codeChars.length)
209 | break;
210 |
211 | if (codeChars[index] == '/') {
212 | startIndex = index - 1;
213 | index++;
214 | while (codeChars[index] != '\n') {
215 | index++;
216 | if (index == codeChars.length) {
217 | index--;
218 | break;
219 | }
220 | }
221 | endIndex = index;
222 | index++;
223 | } else if (codeChars[index] == '*') {
224 | startIndex = index - 1;
225 | index++;
226 |
227 | try {
228 | boolean done = false;
229 | while (!done) {
230 | if (codeChars[index] == '*') {
231 | index++;
232 | if (codeChars[index] == '/') {
233 | done = true;
234 | endIndex = index;
235 | }
236 | }
237 | index++;
238 | }
239 | } catch (ArrayIndexOutOfBoundsException e) {
240 | endIndex = codeChars.length - 1;
241 | }
242 | }
243 |
244 | /* if we found stuff add to array */
245 | if (startIndex != -1)
246 | commentIndexes.add(new Integer[] { startIndex, endIndex });
247 | } else if (codeChars[index] == '"') {
248 | Integer startIndex = index;
249 | Integer endIndex = -1;
250 | index++;
251 |
252 | try {
253 | while (codeChars[index] != '"') {
254 | if (codeChars[index] == '\\') {
255 | index++;
256 | }
257 | index++;
258 | }
259 | endIndex = index;
260 | index++;
261 | } catch (ArrayIndexOutOfBoundsException e) {
262 | }
263 |
264 | /* add to array */
265 | literalIndexes.add(new Integer[] { startIndex, endIndex });
266 | } else if (codeChars[index] == '\'') {
267 | Integer startIndex = index;
268 | Integer endIndex = -1;
269 | index++;
270 |
271 | try {
272 | while (codeChars[index] != '\'') {
273 | if (codeChars[index] == '\\') {
274 | index++;
275 | }
276 | index++;
277 | }
278 | endIndex = index;
279 | index++;
280 | } catch (ArrayIndexOutOfBoundsException e) {
281 | }
282 |
283 | /* add to array */
284 | literalIndexes.add(new Integer[] { startIndex, endIndex });
285 | } else {
286 | index++;
287 | }
288 | }
289 |
290 | /* put our two lists inside of a third list */
291 | finalValues.add(commentIndexes);
292 | finalValues.add(literalIndexes);
293 |
294 | /* return our final list */
295 | return finalValues;
296 | }
297 |
298 | }
299 |
--------------------------------------------------------------------------------
/src/main/java/com/automation/javauto/debugger/SimpleDebugger.java:
--------------------------------------------------------------------------------
1 | package com.automation.javauto.debugger;
2 |
3 | import java.util.ArrayList;
4 | import java.util.regex.*;
5 | import java.util.Collections;
6 | import java.io.*;
7 |
8 | import com.automation.javauto.parser.Create;
9 |
10 | /**
11 | * Takes Java code and does a preliminary debugging to make sure things are
12 | * ready to be compiled.
13 | *
14 | * @author matthew.downey
15 | *
16 | */
17 | public class SimpleDebugger {
18 |
19 | /* list to hold errors */
20 | private static ArrayList errors = new ArrayList();
21 | private static ArrayList errorLines = new ArrayList();
22 |
23 | private static String userCodeFileName = "";
24 | private static String javautoFile = "Javauto.java";
25 |
26 | public static void main(String[] args) {
27 | String userCode = fileRead("thisHasErrors.ja");
28 | debug(userCode, "thisHasErrors.ja");
29 | }
30 |
31 | /**
32 | * Does some simple debugging of a user code file.
33 | *
34 | * @param userCode
35 | * the user code to debug
36 | * @return true only if there are no errors, false otherwise
37 | */
38 | public static boolean debug(String userCode, String fileName) {
39 | /*
40 | * set the global file name so errors can be specific about where an
41 | * error happens
42 | */
43 | userCodeFileName = fileName;
44 |
45 | /*
46 | * build ignore lists for the data -- this step also handles unclosed
47 | * String literals, character literals, and comments.
48 | */
49 | ArrayList commentIgnores = getIgnoreIndexes(userCode).get(0);
50 |
51 | /* get rid of all the comments */
52 | String t = "";
53 | for (int i = 0; i < userCode.length(); i++) {
54 | if (!inIgnoredText(i, commentIgnores))
55 | t = t + userCode.substring(i, i + 1);
56 | }
57 |
58 | userCode = t;
59 |
60 | /* build a list of literal ignores */
61 | ArrayList allIgnores = getIgnoreIndexes(userCode).get(1);
62 |
63 | /* we're gonna need a character array and a line array */
64 | char[] userChars = userCode.toCharArray();
65 | String[] userLines = userCode.split("\n");
66 |
67 | /* first we check to make sure every { has a close } */
68 | for (int i = 0; i < userChars.length; i++) {
69 | if (userChars[i] == '{' && !inIgnoredText(i, allIgnores)) {
70 | findEndBracket(i, userCode, allIgnores);
71 | }
72 | }
73 |
74 | /* now make sure every } has a { */
75 | for (int i = userChars.length - 1; i >= 0; i--) {
76 | if (userChars[i] == '}' && !inIgnoredText(i, allIgnores)) {
77 | findStartBracket(i, userCode, allIgnores);
78 | }
79 | }
80 |
81 | /* make sure every line with a ( has a corresponding ) */
82 | for (int l = 0; l < userLines.length; l++) {
83 | /* use these indexes to populate a list of general ignore indexes */
84 | ArrayList allIgs = getIgnoreIndexes(userLines[l]).get(1);
85 |
86 | char[] lineChars = userLines[l].toCharArray();
87 |
88 | /* make sure each ( has a ) */
89 | for (int i = 0; i < lineChars.length; i++) {
90 | if (lineChars[i] == '(' && !inIgnoredText(i, allIgs)) {
91 | findEndParen(i, userLines[l], allIgs, l);
92 | }
93 |
94 | if (lineChars[i] == ')' && !inIgnoredText(i, allIgs)) {
95 | findStartParen(i, userLines[l], allIgs, l);
96 | }
97 | }
98 | }
99 |
100 | /* make sure string replacements are all right */
101 | checkStringReplaceFormat(userCode);
102 |
103 | /* make sure any javauto functions/constants are in the right case */
104 | checkJavautoCase(userCode, allIgnores);
105 |
106 | /* make sure the user doesn't try to override a built in function */
107 | checkFunctionDeclarations(userCode, allIgnores);
108 |
109 | /* make sure the user doesn't override a javauto variable */
110 | checkVariableDeclarations(userCode, allIgnores);
111 |
112 | /* if there are no errors return true */
113 | if (errors.size() == 0)
114 | return false;
115 |
116 | /* remove duplicate line numbers from errorLines */
117 | ArrayList temp = new ArrayList();
118 | temp.addAll(errorLines);
119 | errorLines = new ArrayList();
120 | for (Integer j : temp)
121 | if (!errorLines.contains(j))
122 | errorLines.add(j);
123 |
124 | /* at the end we display the errors in order of line number */
125 | Collections.sort(errorLines);
126 | for (int el : errorLines) {
127 | for (String[] e : errors) {
128 | if (el == Integer.parseInt(e[0]))
129 | System.out.println(e[1] + "\n");
130 | }
131 | }
132 |
133 | /* show how many errors */
134 | int errorCount = errors.size();
135 | if (errorCount == 1)
136 | System.out.println(errors.size() + " error.");
137 | else
138 | System.out.println(errors.size() + " errors.");
139 |
140 | return true;
141 | }
142 |
143 | /**
144 | * Find the line that a character appears on based on the character
145 | * position.
146 | *
147 | * @param pos
148 | * the position of the character
149 | * @param generatedCode
150 | * the string the character position is in
151 | * @return the line number containing the character
152 | */
153 | private static int getLineNumber(int pos, String generatedCode) {
154 | int line = 1;
155 | char[] genChars = generatedCode.toCharArray();
156 | for (int i = 0; i < pos; i++)
157 | if (genChars[i] == '\n')
158 | line++;
159 | return line;
160 | }
161 |
162 | /**
163 | * Make sure the python file String replacement is formatted like: String s
164 | * = "Hello, my name is %s" % ("John") with the parenthesis after the %
165 | *
166 | * @param userCode
167 | * the code we're auditing
168 | */
169 | private static void checkStringReplaceFormat(String userCode) {
170 | /* regex to find bad replacements */
171 | String regexp = "\".*\"\\s*%\\s+";
172 | Pattern pattern = Pattern.compile(regexp);
173 | Matcher matcher = pattern.matcher(userCode);
174 |
175 | while (matcher.find()) {
176 | /* get the next char that's supposed to be a ( */
177 | int end = matcher.end();
178 | String nextChar = userCode.substring(end, end + 1);
179 |
180 | /* add an error if it isn't a ( */
181 | if (!nextChar.equals("(")) {
182 | int lineNum = getLineNumber(end, userCode);
183 | errorLines.add(lineNum);
184 | String message = "Error in "
185 | + userCodeFileName
186 | + " line "
187 | + lineNum
188 | + "\n"
189 | + "\t"
190 | + userCode.split("\n")[lineNum - 1]
191 | + "\n"
192 | + "Expected a ( after the %.\nLike \"Hello %s\" % (\"John\")";
193 | errors.add(new String[] { String.valueOf(lineNum), message });
194 |
195 | }
196 | }
197 |
198 | }
199 |
200 | private static void checkVariableDeclarations(String userCode,
201 | ArrayList allIgnores) {
202 | ArrayList vars = getVariables();
203 | ArrayList lowerVars = new ArrayList();
204 | for (String s : vars)
205 | lowerVars.add(s.toLowerCase());
206 |
207 | String[] lines = userCode.split("\n");
208 | for (int i = 0; i < lines.length; i++) {
209 | /* regex to search for variable declaration */
210 | String regexp = "^\\s*[\\S+\\s+]*\\s+(\\w+)\\s*=|^\\s*(\\w+)\\s*=";
211 | Pattern pattern = Pattern.compile(regexp);
212 | Matcher matcher = pattern.matcher(lines[i]);
213 |
214 | while (matcher.find()) {
215 | String found = matcher.group(1);
216 |
217 | /* if it's not part of the first half it's the second */
218 | if (found == null)
219 | found = matcher.group(2);
220 |
221 | if (lowerVars.contains(found.toLowerCase())
222 | || found.toLowerCase().equals("args")) {
223 | errorLines.add(i + 1);
224 | String message = "Error in " + userCodeFileName + " line "
225 | + (i + 1) + "\n" + "\t" + userCode.split("\n")[i]
226 | + "\n" + "Cannot override \"" + found
227 | + "\", use a different name.";
228 | errors.add(new String[] { String.valueOf(i + 1), message });
229 | }
230 | }
231 |
232 | }
233 |
234 | }
235 |
236 | private static void checkFunctionDeclarations(String userCode,
237 | ArrayList allIgnores) {
238 | ArrayList funcs = getFunctions();
239 | ArrayList lowerFuncs = new ArrayList();
240 | for (String s : funcs)
241 | lowerFuncs.add(s.toLowerCase());
242 |
243 | String[] lines = userCode.split("\n");
244 | for (int i = 0; i < lines.length; i++) {
245 | /* regex to search for function declaration */
246 | String regexp = "^\\s*func[\\s+\\w+]+\\s(\\w+)\\s*\\(";
247 | Pattern pattern = Pattern.compile(regexp);
248 | Matcher matcher = pattern.matcher(lines[i]);
249 |
250 | while (matcher.find()) {
251 | String found = matcher.group(1);
252 | if (lowerFuncs.contains(found.toLowerCase())) {
253 | errorLines.add(i + 1);
254 | String message = "Error in "
255 | + userCodeFileName
256 | + " line "
257 | + (i + 1)
258 | + "\n"
259 | + "\t"
260 | + userCode.split("\n")[i]
261 | + "\n"
262 | + "Cannot override this function, use a different name.";
263 | errors.add(new String[] { String.valueOf(i + 1), message });
264 | }
265 | }
266 | }
267 | }
268 |
269 | private static void checkJavautoCase(String userCode,
270 | ArrayList allIgnores) {
271 | ArrayList funcs = getJavauto();
272 | for (String s : funcs) {
273 |
274 | /* regex to search for function s within code */
275 | String regexp = "(?i)([^a-zA-Z0-9]+)(" + s + ")([^a-zA-Z0-9]+)";
276 | Pattern pattern = Pattern.compile(regexp);
277 | Matcher matcher = pattern.matcher(userCode);
278 |
279 | while (matcher.find()) {
280 | String foundFunc = matcher.group(2);
281 | int index = matcher.start() + matcher.group(1).length();
282 | if (!foundFunc.equals(s)
283 | && foundFunc.toLowerCase().equals(s.toLowerCase())
284 | && !inIgnoredText(index, allIgnores)) {
285 | int lineNum = getLineNumber(index, userCode);
286 | errorLines.add(lineNum);
287 | String message = "Error in " + userCodeFileName + " line "
288 | + lineNum + "\n" + "\t"
289 | + userCode.split("\n")[lineNum - 1] + "\n"
290 | + "Case of \"" + foundFunc
291 | + "\" is incorrect, it should be \"" + s + "\".";
292 | errors.add(new String[] { String.valueOf(lineNum), message });
293 | }
294 | }
295 |
296 | /*
297 | * do the whole regex again looking for func at the beginning of
298 | * file
299 | */
300 | regexp = "(?i)^(" + s + ")[^a-zA-Z0-9]+";
301 | pattern = Pattern.compile(regexp);
302 | matcher = pattern.matcher(userCode);
303 |
304 | while (matcher.find()) {
305 | String foundFunc = matcher.group(1);
306 | if (!foundFunc.equals(s)
307 | && foundFunc.toLowerCase().equals(s.toLowerCase())) {
308 | int lineNum = 1;
309 | errorLines.add(lineNum);
310 | String message = "Error in " + userCodeFileName + " line "
311 | + lineNum + "\n" + "\t"
312 | + userCode.split("\n")[lineNum - 1] + "\n"
313 | + "Case of \"" + foundFunc
314 | + "\" is incorrect, it should be \"" + s + "\".";
315 | errors.add(new String[] { String.valueOf(lineNum), message });
316 | }
317 | }
318 | }
319 | }
320 |
321 | /**
322 | * Search the javautoFile for all class variables and return them
323 | *
324 | * @return class variables that have been generated
325 | */
326 | private static ArrayList getVariables() {
327 | /* get raw file contents of the file containing our variables */
328 | String[] variablesContents = resourceRead(javautoFile).split("\n");
329 |
330 | /* variable to store our generated class vars */
331 | ArrayList classVars = new ArrayList();
332 |
333 | /* add each line that has a class varaible to our classVars */
334 | for (String line : variablesContents) {
335 | if ((line.trim().startsWith("public ") || line.trim().startsWith(
336 | "private "))
337 | && line.trim().endsWith(";")) {
338 | String[] parts = line.split("=")[0].split(" ");
339 | String name = parts[parts.length - 1].trim();
340 | classVars.add(name);
341 | }
342 | }
343 |
344 | /* return our class vars */
345 | return classVars;
346 | }
347 |
348 | /**
349 | * Gets a list of functions and their source code from the javautoFile
350 | */
351 | private static ArrayList getFunctions() {
352 | /* define the list where we'll store all the data */
353 | ArrayList functionDataList = new ArrayList();
354 |
355 | /* get raw file contents of the file containing our functions */
356 | String functionContents = resourceRead(javautoFile);
357 |
358 | /* split into lines for evaluation */
359 | String[] functionContentsLines = functionContents.split("\n");
360 |
361 | /* check each line and extract function names */
362 | for (String line : functionContentsLines) {
363 | /*
364 | * if the line is like "public *{" or "private *{" but isn't like
365 | * "public class"
366 | */
367 | if ((line.trim().startsWith("public ") || line.trim().startsWith(
368 | "private "))
369 | && (line.trim().endsWith("{"))
370 | && (!line.trim().startsWith("public class"))) {
371 | /*
372 | * if it meets the above criteria it's a function & we add it to
373 | * the list
374 | */
375 |
376 | /* get function name & code */
377 | String functionName = line.trim().split(" ")[2].split("[(]")[0];
378 |
379 | /*
380 | * add it to the list unless it's the "run" function used in a
381 | * thread
382 | */
383 | if (!functionName.toLowerCase().equals("run")
384 | && !functionDataList.contains(functionName.trim())) {
385 | functionDataList.add(functionName.trim());
386 | }
387 | }
388 | }
389 |
390 | /* return our list without duplicates */
391 | return functionDataList;
392 | }
393 |
394 | private static ArrayList getJavauto() {
395 | /* define the list where we'll store all the data */
396 | ArrayList functionDataList = new ArrayList();
397 |
398 | /* get raw file contents of the file containing our functions */
399 | String functionContents = resourceRead(javautoFile);
400 |
401 | /* split into lines for evaluation */
402 | String[] functionContentsLines = functionContents.split("\n");
403 |
404 | /* check each line and extract function names */
405 | for (String line : functionContentsLines) {
406 | /*
407 | * if the line is like "public *{" or "private *{" but isn't like
408 | * "public class"
409 | */
410 | if ((line.trim().startsWith("public ") || line.trim().startsWith(
411 | "private "))
412 | && (line.trim().endsWith("{"))
413 | && (!line.trim().startsWith("public class"))) {
414 | /*
415 | * if it meets the above criteria it's a function & we add it to
416 | * the list
417 | */
418 |
419 | /* get function name & code */
420 | String functionName = line.trim().split(" ")[2].split("[(]")[0];
421 |
422 | /*
423 | * add it to the list unless it's the "run" function used in a
424 | * thread
425 | */
426 | if (!functionName.toLowerCase().equals("run")) {
427 | String function = functionName.trim();
428 | if (!functionDataList.contains(function))
429 | functionDataList.add(function);
430 | }
431 | }
432 |
433 | /* if it's a variable */
434 | else if ((line.trim().startsWith("public ") || line.trim()
435 | .startsWith("private ")) && line.trim().endsWith(";")) {
436 | String[] parts = line.split("=")[0].split(" ");
437 | String name = parts[parts.length - 1].trim();
438 | functionDataList.add(name);
439 | }
440 | }
441 |
442 | /* return our list without duplicates */
443 | return functionDataList;
444 | }
445 |
446 | /**
447 | * Reads file contents (from a resource inside the JAR) into string
448 | *
449 | * @param resourcePath
450 | * the path to the resource within the JAR file
451 | * @return file contents as string
452 | */
453 | private static String resourceRead(String resourcePath) {
454 | try {
455 | InputStream inputStream = Thread.currentThread()
456 | .getContextClassLoader().getResourceAsStream(resourcePath);
457 |
458 | BufferedReader bufferedReader = new BufferedReader(
459 | new InputStreamReader(inputStream, "UTF-8"));
460 | StringBuilder stringBuilder = new StringBuilder();
461 | String line = bufferedReader.readLine();
462 | while (line != null) {
463 | stringBuilder.append(line);
464 | if (line != null) {
465 | stringBuilder.append("\n");
466 | }
467 | line = bufferedReader.readLine();
468 | }
469 | return stringBuilder.toString();
470 | } catch (Exception e) {
471 | System.out
472 | .println("Compiler encountered an error reading JAR resource \""
473 | + resourcePath
474 | + "\" -- the JAR file may be corrupt.");
475 | e.printStackTrace();
476 | System.exit(1);
477 | return "";
478 | }
479 | }
480 |
481 | /**
482 | * Reads file contents into a string
483 | *
484 | * @param filePath
485 | * path of file to read
486 | * @return file contents as string
487 | */
488 | private static String fileRead(String filePath) {
489 | try {
490 | BufferedReader br = new BufferedReader(new FileReader(filePath));
491 | StringBuilder data = new StringBuilder();
492 | String line = br.readLine();
493 | while (line != null) {
494 | data.append(line);
495 | data.append('\n');
496 | line = br.readLine();
497 | }
498 | String fileData = data.toString();
499 | br.close();
500 | return fileData;
501 | } catch (Exception e) {
502 | System.out.println("Compiler encountered an error reading file \""
503 | + filePath + "\"");
504 | e.printStackTrace();
505 | System.exit(1);
506 | return "null";
507 | }
508 | }
509 |
510 | /**
511 | * Given the index of a '{', find the corresponding '}'.
512 | *
513 | * @param startBracket
514 | * the index of the '{'.
515 | * @param context
516 | * the string within which the parens are located.
517 | * @param indexesToIgnore
518 | * A list of Integers like [start, end] that specify indexes that
519 | * should be ignored, this list usually contains the start and
520 | * end bounds of each comment and string literal in the context.
521 | * @return the index of the closing paren
522 | */
523 | private static int findEndBracket(int startBracket, String context,
524 | ArrayList indexesToIgnore) {
525 | char[] contextChars = context.toCharArray();
526 | int index = startBracket + 1;
527 | int open = 1;
528 | int close = 0;
529 | try {
530 | while (open > close) {
531 | /*
532 | * if the current character is a ( and it's not inside a comment
533 | * or literal
534 | */
535 | if (contextChars[index] == '{'
536 | && !inIgnoredText(index, indexesToIgnore)) {
537 | open++;
538 | }
539 | /*
540 | * if the current character is a ) and it's not inside a comment
541 | * or literal
542 | */
543 | else if (contextChars[index] == '}'
544 | && !inIgnoredText(index, indexesToIgnore)) {
545 | close++;
546 | }
547 | /* on to the next one */
548 | index++;
549 | }
550 | } catch (ArrayIndexOutOfBoundsException e) {
551 | int lineNum = getLineNumber(startBracket, context);
552 | errorLines.add(lineNum);
553 | String message = "Error in " + userCodeFileName + " line "
554 | + lineNum + "\n" + "\t" + context.split("\n")[lineNum - 1]
555 | + "\n" + "Expected corresponding '}'";
556 | errors.add(new String[] { String.valueOf(lineNum), message });
557 | }
558 | return index;
559 | }
560 |
561 | private static int findStartBracket(int endBracket, String context,
562 | ArrayList indexesToIgnore) {
563 | char[] contextChars = context.toCharArray();
564 | int index = endBracket - 1;
565 | int open = 0;
566 | int close = 1;
567 | try {
568 | while (close > open) {
569 | /*
570 | * if the current character is a ( and it's not inside a comment
571 | * or literal
572 | */
573 | if (contextChars[index] == '{'
574 | && !inIgnoredText(index, indexesToIgnore)) {
575 | open++;
576 | }
577 | /*
578 | * if the current character is a ) and it's not inside a comment
579 | * or literal
580 | */
581 | else if (contextChars[index] == '}'
582 | && !inIgnoredText(index, indexesToIgnore)) {
583 | close++;
584 | }
585 | /* on to the next one */
586 | index--;
587 | }
588 | } catch (ArrayIndexOutOfBoundsException e) {
589 | int lineNum = getLineNumber(endBracket, context);
590 | errorLines.add(lineNum);
591 | String message = "Error in " + userCodeFileName + " line "
592 | + lineNum + "\n" + "\t" + context.split("\n")[lineNum - 1]
593 | + "\n" + "Unexpected '}'";
594 | errors.add(new String[] { String.valueOf(lineNum), message });
595 | }
596 | return index;
597 | }
598 |
599 | /**
600 | * Given the index of a '(', find the corresponding ')'.
601 | *
602 | * @param startParen
603 | * the index of the '('.
604 | * @param context
605 | * the string within which the parens are located.
606 | * @param indexesToIgnore
607 | * A list of Integers like [start, end] that specify indexes that
608 | * should be ignored, this list usually contains the start and
609 | * end bounds of each comment and string literal in the context.
610 | * @return the index of the closing paren
611 | */
612 | private static int findEndParen(int startParen, String context,
613 | ArrayList indexesToIgnore, int lineNumber) {
614 | char[] contextChars = context.toCharArray();
615 | int index = startParen + 1;
616 | int open = 1;
617 | int close = 0;
618 | try {
619 | while (open > close) {
620 | /*
621 | * if the current character is a ( and it's not inside a comment
622 | * or literal
623 | */
624 | if (contextChars[index] == '('
625 | && !inIgnoredText(index, indexesToIgnore)) {
626 | open++;
627 | }
628 | /*
629 | * if the current character is a ) and it's not inside a comment
630 | * or literal
631 | */
632 | else if (contextChars[index] == ')'
633 | && !inIgnoredText(index, indexesToIgnore)) {
634 | close++;
635 | }
636 | /* on to the next one */
637 | index++;
638 | }
639 | } catch (ArrayIndexOutOfBoundsException e) {
640 | errorLines.add(lineNumber);
641 | String message = "Error in " + userCodeFileName + " line "
642 | + (lineNumber + 1) + "\n" + "\t" + context + "\n"
643 | + "Unclosed '(', expected corresponding ')'";
644 | errors.add(new String[] { String.valueOf(lineNumber), message });
645 | }
646 | return index;
647 | }
648 |
649 | private static int findStartParen(int endParen, String context,
650 | ArrayList indexesToIgnore, int lineNumber) {
651 | char[] contextChars = context.toCharArray();
652 | int index = endParen - 1;
653 | int open = 0;
654 | int close = 1;
655 | try {
656 | while (close > open) {
657 | /*
658 | * if the current character is a ( and it's not inside a comment
659 | * or literal
660 | */
661 | if (contextChars[index] == '('
662 | && !inIgnoredText(index, indexesToIgnore)) {
663 | open++;
664 | }
665 | /*
666 | * if the current character is a ) and it's not inside a comment
667 | * or literal
668 | */
669 | else if (contextChars[index] == ')'
670 | && !inIgnoredText(index, indexesToIgnore)) {
671 | close++;
672 | }
673 | /* on to the next one */
674 | index--;
675 | }
676 | } catch (ArrayIndexOutOfBoundsException e) {
677 | errorLines.add(lineNumber);
678 | String message = "Error in " + userCodeFileName + " line "
679 | + (lineNumber + 1) + "\n" + "\t" + context + "\n"
680 | + "Unexpected ')'";
681 | errors.add(new String[] { String.valueOf(lineNumber), message });
682 | }
683 | return index;
684 | }
685 |
686 | /**
687 | * Determines if a character is inside any of the bounds of a list of blocks
688 | * of text to ignore.
689 | *
690 | * @param charIndex
691 | * the index of the character whose position is being checked
692 | * @param ignoredIndex
693 | * a list of items like [int startIgnoreIndex, int
694 | * endIgnoreIndex] that specifies which indexes are supposed to
695 | * be ignored
696 | * @return returns true if the character index is within any of the ignore
697 | * bounds, otherwise returns false.
698 | */
699 | private static boolean inIgnoredText(int charIndex,
700 | ArrayList ignoredIndexes) {
701 | /* check each set of bounds to see if they hold our charIndex */
702 | for (Integer[] i : ignoredIndexes) {
703 | if (charIndex >= i[0] && charIndex <= i[1])
704 | return true;
705 | }
706 |
707 | /* if we got to here we haven't found it inside any of the bounds */
708 | return false;
709 | }
710 |
711 | /**
712 | * Build a list of character indexes that should be ignored during
713 | * processing. Characters to be ignored are those inside of comments, string
714 | * literals, and character literals. This function returns the bounds of
715 | * indexes of characters and literals in two separate lists.
716 | *
717 | * @param code
718 | * the string to generate this list of bounds for
719 | * @return returns two ArrayList objects, wrapped inside of one
720 | * ArrayList, with the format [comment indexes, literal indexes].
721 | * Then each of those elements is a list with the format [start
722 | * ignore index, end ignore index].
723 | */
724 | private static ArrayList> getIgnoreIndexes(String code) {
725 | /* Lists to hold bounds for both comments and literals */
726 | ArrayList commentIndexes = new ArrayList();
727 | ArrayList literalIndexes = new ArrayList();
728 |
729 | /*
730 | * List to hold our other two lists, so that the user can separate them
731 | * at will
732 | */
733 | ArrayList> finalValues = new ArrayList>();
734 |
735 | /*
736 | * iterate through character by character looking for comments and
737 | * literals
738 | */
739 | char[] codeChars = code.toCharArray();
740 | int index = 0;
741 | while (index < codeChars.length) {
742 | if (codeChars[index] == '/') {
743 | Integer startIndex = -1;
744 | Integer endIndex = -1;
745 |
746 | index++;
747 |
748 | if (codeChars[index] == '/') {
749 | startIndex = index - 1;
750 | index++;
751 | while (codeChars[index] != '\n') {
752 | index++;
753 | if (index == codeChars.length) {
754 | index--;
755 | break;
756 | }
757 | }
758 | endIndex = index - 1;
759 | index++;
760 | } else if (codeChars[index] == '*') {
761 | startIndex = index - 1;
762 | index++;
763 |
764 | try {
765 | boolean done = false;
766 | while (!done) {
767 | if (codeChars[index] == '*') {
768 | index++;
769 | if (codeChars[index] == '/') {
770 | done = true;
771 | endIndex = index;
772 | }
773 | }
774 | index++;
775 | }
776 | } catch (ArrayIndexOutOfBoundsException e) {
777 | int lineNum = getLineNumber(startIndex, code);
778 | errorLines.add(lineNum);
779 |
780 | String message = "Error in " + userCodeFileName
781 | + " line " + lineNum + "\n" + "\t"
782 | + code.split("\n")[lineNum - 1] + "\n"
783 | + "Unclosed comment.";
784 | errors.add(new String[] { String.valueOf(lineNum),
785 | message });
786 | }
787 | }
788 |
789 | /* if we found stuff add to array */
790 | if (startIndex != -1)
791 | commentIndexes.add(new Integer[] { startIndex, endIndex });
792 | } else if (codeChars[index] == '"') {
793 | Integer startIndex = index;
794 | Integer endIndex = -1;
795 | index++;
796 |
797 | try {
798 | while (codeChars[index] != '"') {
799 | if (codeChars[index] == '\\') {
800 | index++;
801 | }
802 | index++;
803 | }
804 | endIndex = index;
805 | index++;
806 | } catch (ArrayIndexOutOfBoundsException e) {
807 | int lineNum = getLineNumber(startIndex, code);
808 | errorLines.add(lineNum);
809 |
810 | String message = "Error in " + userCodeFileName + " line "
811 | + lineNum + "\n" + "\t"
812 | + code.split("\n")[lineNum - 1] + "\n"
813 | + "Unclosed string literal.";
814 | errors.add(new String[] { String.valueOf(lineNum), message });
815 | }
816 |
817 | /* add to array */
818 | literalIndexes.add(new Integer[] { startIndex, endIndex });
819 | } else if (codeChars[index] == '\'') {
820 | Integer startIndex = index;
821 | Integer endIndex = -1;
822 | index++;
823 |
824 | try {
825 | while (codeChars[index] != '\'') {
826 | if (codeChars[index] == '\\') {
827 | index++;
828 | }
829 | index++;
830 | }
831 | endIndex = index;
832 | index++;
833 | } catch (ArrayIndexOutOfBoundsException e) {
834 | int lineNum = getLineNumber(startIndex, code);
835 | errorLines.add(lineNum);
836 |
837 | String message = "Error in " + userCodeFileName + " line "
838 | + lineNum + "\n" + "\t"
839 | + code.split("\n")[lineNum - 1] + "\n"
840 | + "Unclosed character literal.";
841 | errors.add(new String[] { String.valueOf(lineNum), message });
842 | }
843 |
844 | /* add to array */
845 | literalIndexes.add(new Integer[] { startIndex, endIndex });
846 | } else {
847 | index++;
848 | }
849 | }
850 |
851 | /* put our two lists inside of a third list */
852 | finalValues.add(commentIndexes);
853 | finalValues.add(literalIndexes);
854 |
855 | /* return our final list */
856 | return finalValues;
857 | }
858 | }
859 |
--------------------------------------------------------------------------------
/src/main/java/com/automation/javauto/parser/Create.java:
--------------------------------------------------------------------------------
1 | package com.automation.javauto.parser;
2 |
3 | import java.io.*;
4 | import java.util.Locale;
5 | import java.util.List;
6 | import java.util.ArrayList;
7 | import java.util.regex.*;
8 |
9 | import javax.tools.*;
10 |
11 | import com.automation.javauto.compiler.CustomJarCompiler;
12 | import com.automation.javauto.compiler.CustomJavaCompiler;
13 | import com.automation.javauto.debugger.SimpleDebugger;
14 | import com.automation.javauto.compiler.DealWithCompilerErrors;
15 |
16 | /**
17 | *
18 | * This class handles the top level user code parsing. It takes a .ja or
19 | * .javauto file and parses a copy of the Javauto.java file in order to create
20 | * functions, it creates struct objects and class variables, and then it uses
21 | * the {@link SimpleDebugger} class to check its generated code. If everything
22 | * checks out, it runs the code through {@link CustomJavaCompiler} to generate
23 | * class files; any errors at this point are sent directly to
24 | * {@link DealWithCompilerErrors} to be displayed. Finally
25 | * {@link CustomJarCompiler} * is used to bundle the class files into a jar.
26 | *
27 | * @author matthew.downey
28 | *
29 | */
30 | public class Create {
31 | /* define constants for different terminal colors */
32 | private static String RED = "\033[91m";
33 | private static String GREEN = "\033[92m";
34 | private static String YELLOW = "\033[93m";
35 | private static String BLUE = "\033[96m";
36 | private static String NORMAL = "\033[0m";
37 |
38 | /* controls whether we're in verbose mode */
39 | private static boolean verbose = false;
40 |
41 | /* controls whether we're generating .java files */
42 | private static boolean genJava = false;
43 |
44 | /* controls whether we're keeping the generated .class files */
45 | private static boolean keepClass = false;
46 |
47 | /* the file our javauto functions are located in */
48 | private static String javautoFile = "Javauto.java";
49 |
50 | /* used by various functions to determine if they've printed to terminal */
51 | private static boolean printedResults = false;
52 |
53 | /* if this variable is true we will execute a search and then exit */
54 | private static boolean doSearch = false;
55 |
56 | /*
57 | * ArrayList to hold our struct objects, which are converted into java
58 | * objects and must be written to a separate file in the same directory.
59 | * Each index should have [struct name, struct code]
60 | */
61 | private static ArrayList structFiles;
62 |
63 | /* the template used to organize generated code */
64 | private static String template = "\n" + "\n"
65 | + "\n" + "\n"
66 | + "\n" + "\n" + "\n"
67 | + "<{_*_generatedFunctions_*_}>\n" + "";
68 |
69 | public static void main(String[] args) {
70 | /* check to see if colors are in use */
71 | boolean useColors = true;
72 | try {
73 | BufferedReader br = new BufferedReader(
74 | new FileReader("colors.conf"));
75 | StringBuilder data = new StringBuilder();
76 | String line = br.readLine();
77 | while (line != null) {
78 | data.append(line);
79 | data.append('\n');
80 | line = br.readLine();
81 | }
82 | String fileData = data.toString().trim();
83 | br.close();
84 | int c = Integer.parseInt(fileData);
85 | if (c == 0)
86 | useColors = false;
87 | } catch (Exception e) {
88 | }
89 | if (!useColors) {
90 | RED = "";
91 | GREEN = "";
92 | YELLOW = "";
93 | BLUE = "";
94 | NORMAL = "";
95 | }
96 |
97 | /* display error if no arguments are provided or if it's just a -v flag */
98 | if (args.length == 0) {
99 | System.out.println("Usage: javauto ");
100 | System.out.println("Options:");
101 | System.out.println("\t-v\t--verbose\t\tcompile in verbose mode");
102 | System.out
103 | .println("\t-g\t--generate\t\tgenerate .java and .class files");
104 | System.out
105 | .println("\t-gj\t--generate-java\t\tgenerate .java files");
106 | System.out
107 | .println("\t-gc\t--generate-class\tgenerate .class files");
108 | }
109 |
110 | /* compile each file provided */
111 | for (String userCodeFile : args) {
112 |
113 | /*
114 | * initialize the struct files as an empty array for potential user
115 | * structs in this userCodeFile
116 | */
117 | structFiles = new ArrayList();
118 |
119 | /* if it's not a file but a no-colors flag */
120 | if (userCodeFile.equals("-nc")
121 | || userCodeFile.equals("--no-colors")) {
122 | /* set all the colors to empty */
123 | RED = "";
124 | GREEN = "";
125 | YELLOW = "";
126 | BLUE = "";
127 | NORMAL = "";
128 | continue;
129 | }
130 |
131 | /* if it's not a file but a verbose flag */
132 | if (userCodeFile.equals("-v") || userCodeFile.equals("--verbose")) {
133 | /* set verbose to true and continue with next iteration */
134 | verbose = true;
135 | continue;
136 | }
137 |
138 | /* if it's not a file but a flag */
139 | else if (userCodeFile.equals("-g")
140 | || userCodeFile.equals("--generate")) {
141 | /* set keeps to true and continue with next iteration */
142 | keepClass = true;
143 | genJava = true;
144 | continue;
145 | }
146 |
147 | /* if it's not a file but a flag */
148 | else if (userCodeFile.equals("-gj")
149 | || userCodeFile.equals("--generate-java")) {
150 | /* set keeps to true and continue with next iteration */
151 | genJava = true;
152 | continue;
153 | }
154 |
155 | /* if it's not a file but a flag */
156 | else if (userCodeFile.equals("-gc")
157 | || userCodeFile.equals("--generate-class")) {
158 | /* set keeps to true and continue with next iteration */
159 | keepClass = true;
160 | continue;
161 | }
162 |
163 | /* check to make sure it's a .javauto file */
164 | if (!userCodeFile.toLowerCase().endsWith(".javauto")
165 | && !userCodeFile.toLowerCase().endsWith(".ja")) {
166 | System.out.println("Not a .javauto file: " + GREEN
167 | + userCodeFile + NORMAL);
168 | continue;
169 | }
170 |
171 | /* check to make sure the file exists */
172 | if (!new File(userCodeFile).exists()) {
173 | System.out.println("File not found: " + GREEN + userCodeFile
174 | + NORMAL);
175 | continue;
176 | }
177 |
178 | /* the class name of our main user code */
179 | String className = new File(userCodeFile).getName().split(
180 | "\\.(?=[^\\.]+$)")[0];
181 |
182 | verbose("Generating " + GREEN + className + NORMAL + "...");
183 |
184 | if (!className.matches("^[a-zA-Z].*")) {
185 | System.out.println(RED
186 | + "Error: class names must start with a letter. "
187 | + GREEN + className + RED
188 | + " does not start with a letter." + NORMAL);
189 | System.exit(1);
190 | }
191 | if (!className.matches("^\\S+$")) {
192 | System.out.println(RED
193 | + "Error: class names must not contain spaces. "
194 | + GREEN + className + RED + " contains spaces."
195 | + NORMAL);
196 | System.exit(1);
197 | }
198 |
199 | /* file path of our build folder (currentDir/build) */
200 | String directory = new File(userCodeFile).getAbsolutePath()
201 | .substring(
202 | 0,
203 | new File(userCodeFile).getAbsolutePath()
204 | .lastIndexOf(File.separator))
205 | + File.separator + className;
206 |
207 | /*
208 | * if we're not keeping any of the generated files make the dir
209 | * hidden
210 | */
211 | if (!keepClass && !genJava)
212 | directory = new File(userCodeFile).getAbsolutePath().substring(
213 | 0,
214 | new File(userCodeFile).getAbsolutePath().lastIndexOf(
215 | File.separator))
216 | + File.separator + "." + className;
217 |
218 | /*
219 | * file path of our gen directory (build/gen) for generated java
220 | * files
221 | */
222 | String genDirectory = directory + File.separator + "gen";
223 |
224 | /*
225 | * file path of our class directory (build/class) for our compiled
226 | * .class files
227 | */
228 | String classDirectory = directory + File.separator + "class";
229 |
230 | /* get javauto code to compile */
231 | String javautoCode = fileRead(userCodeFile);
232 |
233 | /*
234 | * perform rudimentary debugging and stop compiling if there's an
235 | * error
236 | */
237 | boolean err = SimpleDebugger.debug(javautoCode, userCodeFile);
238 | if (err)
239 | System.exit(1);
240 |
241 | /* generate java code from the provided javauto code */
242 | String generatedCode = generateJavaCode(javautoCode, className);
243 | verbose("Generation complete... starting build");
244 |
245 | /*** Now the build begins ***/
246 |
247 | /* create our build folder if it doesn't exist */
248 | File outDir = new File(directory);
249 | if (!outDir.exists()) {
250 | verbose("Creating directory " + GREEN + directory + NORMAL
251 | + "...");
252 | if (!outDir.mkdir()) {
253 | System.out
254 | .println("Error: couldn't create build directory "
255 | + GREEN
256 | + directory
257 | + NORMAL
258 | + "\nPlease create this directory manually.");
259 | System.exit(1);
260 | }
261 | }
262 | /*
263 | * if our build folder is temporary and we're on windows hide the
264 | * folder manually
265 | */
266 | if (!keepClass
267 | && !genJava
268 | && System.getProperty("os.name").toLowerCase()
269 | .contains("windows")) {
270 | String cmd = "Executing cmd /c attrib +s +h \"" + directory
271 | + "\"...";
272 | verbose(cmd);
273 | try {
274 | Process p = Runtime.getRuntime().exec(
275 | "cmd /c attrib +s +h \"" + directory + "\"");
276 | } catch (Exception e) {
277 | verbose(RED + "Failed." + NORMAL);
278 | }
279 | }
280 |
281 | /* create our gen folder if it doesn't exist */
282 | if (genJava) {
283 | outDir = new File(genDirectory);
284 | if (!outDir.exists()) {
285 | verbose("Creating directory " + GREEN + genDirectory
286 | + NORMAL + "...");
287 | if (!outDir.mkdir()) {
288 | System.out
289 | .println("Error: couldn't create gen directory "
290 | + GREEN
291 | + genDirectory
292 | + NORMAL
293 | + "\nPlease create this directory manually.");
294 | System.exit(1);
295 | }
296 | }
297 | }
298 |
299 | /* create our class folder if it doesn't exist */
300 | outDir = new File(classDirectory);
301 | if (!outDir.exists()) {
302 | verbose("Creating directory " + GREEN + classDirectory + NORMAL
303 | + "...");
304 | if (!outDir.mkdir()) {
305 | System.out
306 | .println("Error: couldn't create class directory "
307 | + GREEN
308 | + classDirectory
309 | + NORMAL
310 | + "\nPlease create this directory manually.");
311 | System.exit(1);
312 | }
313 | }
314 |
315 | if (genJava) {
316 | /* build all of our user struct files */
317 | for (String[] structFile : structFiles) {
318 | String outPath = genDirectory + File.separator
319 | + structFile[0] + ".java";
320 | verbose("Building " + GREEN + outPath + NORMAL + "...");
321 | fileWrite(outPath, structFile[1] + "\n");
322 | }
323 | }
324 |
325 | if (genJava) {
326 | /* build our main file */
327 | String outputFile = genDirectory + File.separator + className
328 | + ".java";
329 | verbose("Building " + GREEN + outputFile + NORMAL + "...");
330 | fileWrite(outputFile, generatedCode);
331 | }
332 |
333 | /*** Now it's time to generate class files ***/
334 |
335 | /* first generate each struct */
336 | for (String[] structFile : structFiles) {
337 | verbose("Building " + GREEN + classDirectory + File.separator
338 | + structFile[0] + ".class" + NORMAL + "...");
339 |
340 | /*
341 | * use our custom compiler {@link CustomJavaCompiler} to attempt
342 | * to compile the file, if it doesn't work out errors will be
343 | * stored in the DiagnosticCollector
344 | */
345 | DiagnosticCollector compileErrors = null;
346 | try {
347 | compileErrors = CustomJavaCompiler.compile(structFile[0],
348 | structFile[1], classDirectory, classDirectory);
349 | } catch (IOException ioe) {
350 | System.out.println(RED
351 | + "Error: couldn't write to file in directory "
352 | + classDirectory + NORMAL);
353 | ioe.printStackTrace();
354 | }
355 |
356 | /* if there is an error */
357 | if (compileErrors != null) {
358 |
359 | /* iterate through each error */
360 | for (Diagnostic diagnostic : compileErrors.getDiagnostics()) {
361 |
362 | /*
363 | * find the struct in the user code that is causing the
364 | * issue
365 | */
366 | String[] javautoCodeLines = javautoCode.split("\n");
367 | int structlinenum = -1;
368 | for (int k = 0; k < javautoCodeLines.length; k++) {
369 | if (removeLiterals(
370 | removeComments(javautoCodeLines[k])).trim()
371 | .startsWith("struct " + structFile[0]))
372 | structlinenum = k;
373 | }
374 |
375 | /* if we found the struct declaration include that */
376 | if (structlinenum == -1)
377 | /* print the error message */
378 | System.out.println(diagnostic.getKind().toString()
379 | .toLowerCase()
380 | + " in struct " + structFile[0] + ":");
381 | else
382 | /* print the error message */
383 | System.out.println(diagnostic.getKind()
384 | + " in struct declaration for "
385 | + structFile[0] + " starting on line "
386 | + structlinenum + ":\n\t"
387 | + javautoCodeLines[structlinenum]);
388 | System.out.println(diagnostic.getMessage(Locale
389 | .getDefault()) + "\n");
390 | }
391 |
392 | /* clean up */
393 | if (!keepClass && !genJava) {
394 | if (deleteDirectory(new File(directory))) {
395 | verbose("Removed temporary dir " + GREEN
396 | + directory + NORMAL);
397 | } else {
398 | verbose(RED + "Failed to remove temporary dir "
399 | + directory + NORMAL);
400 | }
401 | }
402 |
403 | /* exit because we found an error */
404 | System.exit(1);
405 | }
406 | }
407 |
408 | /* now compile main user code */
409 | verbose("Building " + GREEN + classDirectory + File.separator
410 | + className + ".class" + NORMAL + "...");
411 |
412 | /*
413 | * use our custom compiler {@link CustomJavaCompiler.java} to
414 | * attempt to compile the file, if it doesn't work out errors will
415 | * be stored in the DiagnosticCollector
416 | */
417 | DiagnosticCollector compileErrors = null;
418 | try {
419 | compileErrors = CustomJavaCompiler.compile(className,
420 | generatedCode, classDirectory, classDirectory);
421 | } catch (IOException ioe) {
422 | System.out.println(RED
423 | + "Error: couldn't write to file in directory "
424 | + classDirectory + NORMAL);
425 | ioe.printStackTrace();
426 | }
427 |
428 | /* if there is an error */
429 | if (compileErrors != null) {
430 |
431 | /*
432 | * give the errors to our DealWithCompilerErrors.java to take
433 | * care of
434 | */
435 | DealWithCompilerErrors.dealWithIt(compileErrors, generatedCode,
436 | javautoCode, userCodeFile);
437 |
438 | /* clean up */
439 | if (!keepClass && !genJava) {
440 | if (deleteDirectory(new File(directory))) {
441 | verbose("Removed temporary dir " + GREEN + directory
442 | + NORMAL);
443 | } else {
444 | verbose(RED + "Failed to remove temporary dir "
445 | + directory + NORMAL);
446 | }
447 | }
448 |
449 | /* exit because we found an error */
450 | System.exit(1);
451 | }
452 |
453 | /* now create a .jar file from our class files */
454 | if (verbose)
455 | CustomJarCompiler.verbose = true;
456 | if (GREEN.equals("")) // if colors are blank
457 | CustomJarCompiler.colors = false;
458 | String jarOut = className + ".jar";
459 | if (keepClass || genJava)
460 | jarOut = directory + File.separator + className + ".jar";
461 |
462 | try {
463 | CustomJarCompiler.create(jarOut, className, classDirectory);
464 | } catch (IOException ioe) {
465 | System.out.println(RED + "Error: could not write to file "
466 | + jarOut + NORMAL);
467 | ioe.printStackTrace();
468 | } finally {
469 | if (!keepClass && !genJava) {
470 | if (deleteDirectory(new File(directory))) {
471 | verbose("Removed temporary dir " + GREEN + directory
472 | + NORMAL);
473 | } else {
474 | verbose(RED + "Failed to remove temporary dir "
475 | + directory + NORMAL);
476 | }
477 | }
478 | }
479 |
480 | /* set our jar file to be executable */
481 | verbose("Setting executable permissions for " + GREEN + jarOut
482 | + NORMAL + "...");
483 | File ourJar = new File(jarOut);
484 | ourJar.setExecutable(true);
485 |
486 | /* we're done compiling */
487 | verbose("Operation complete.");
488 |
489 | }
490 |
491 | }
492 |
493 | /**
494 | * Highlight a term inside of a string.
495 | *
496 | * @param term
497 | * the term to highlight (ingores anything thats not a letter or
498 | * number)
499 | * @param context
500 | * the string in which the term is found and highlighted
501 | * @param startHighlight
502 | * the chracter to use to "highlight" the beginning
503 | * @param endHighlight
504 | * the character to end the highlighting with
505 | * @return the highlighted string
506 | */
507 | private static String highlight(String term, String context,
508 | String startHighlight, String endHighlight) {
509 | /*
510 | * convert to lower case and replace non word characters with spaces so
511 | * that indexes remain the same
512 | */
513 | String indexedCon = context.replaceAll("[^a-zA-Z0-9]", " ")
514 | .toLowerCase();
515 |
516 | /* get our term without non words */
517 | String stripTerm = term.replaceAll("[^a-zA-Z0-9]", "").toLowerCase();
518 |
519 | /* build a regex to find the starting and ending indexes of our term */
520 | String regexp = "";
521 | String[] termParts = stripTerm.split("");
522 | for (int i = 1; i < termParts.length; i++) {
523 | regexp = regexp + termParts[i] + "\\s*";
524 | }
525 | regexp = regexp.substring(0, regexp.length() - 3);
526 |
527 | /* search for our pattern in the string */
528 | Pattern pattern = Pattern.compile(regexp);
529 | Matcher matcher = pattern.matcher(indexedCon);
530 |
531 | /* get start and end indexes of our term inside the string */
532 | ArrayList startEnd = new ArrayList();
533 | while (matcher.find())
534 | startEnd.add(new Integer[] { matcher.start(), matcher.end() });
535 |
536 | /* craft our highlighted result */
537 | int shiftLen = 0;
538 | String res = context;
539 | for (Integer[] coords : startEnd) {
540 | int start = coords[0] + shiftLen;
541 | int end = coords[1] + shiftLen;
542 | res = res.substring(0, start) + startHighlight
543 | + res.substring(start, end) + endHighlight
544 | + res.substring(end, res.length());
545 | shiftLen = shiftLen + startHighlight.length()
546 | + endHighlight.length();
547 | }
548 |
549 | return res;
550 | }
551 |
552 | /**
553 | * Generate java code from javauto code with the help of our template
554 | *
555 | * @param javautoCode
556 | * raw javauto code to be converted
557 | * @param userClassName
558 | * the name of the class/output file
559 | * @return java code as String
560 | */
561 | private static String generateJavaCode(String javautoCode,
562 | String userClassName) {
563 | /* get a template for our generated code */
564 | String templateContents = template;
565 |
566 | /* get functions that might need to be implimented */
567 | ArrayList javautoFunctions = getFunctions();
568 |
569 | /* define where we're gonna store our final code */
570 | String generatedCode = "";
571 |
572 | /* code we generate (supporting functions will be handled later on) */
573 | String generatedImports = generateImports();
574 | String generatedVariables = generateVariables();
575 |
576 | /* define different variables to categorize the user code */
577 | String userImports = "";
578 | String userGlobalVariables = "";
579 | String userCode = "";
580 | String userFunctions = "";
581 |
582 | /* handle python file string replacements in user code */
583 | javautoCode = doPythonStringReplacements(javautoCode);
584 |
585 | /* remove comments from the user code */
586 | javautoCode = removeComments(javautoCode);
587 |
588 | /* remove whitespace */
589 | String cleanedCode = "";
590 | for (String line : javautoCode.split("\n")) {
591 | if (!line.equals("\n")) {
592 | cleanedCode = cleanedCode + line.trim() + "\n";
593 | }
594 | }
595 | while (cleanedCode.contains("\n\n"))
596 | cleanedCode = cleanedCode.replace("\n\n", "\n");
597 | javautoCode = cleanedCode;
598 |
599 | /* extract user imports */
600 | String[] jaCodeLines = javautoCode.split("\n");
601 | verbose("Getting user imports... ", 0);
602 | printedResults = false;
603 | for (int i = 0; i < jaCodeLines.length; i++) {
604 | if (jaCodeLines[i].trim().startsWith("import ")) {
605 | if (!alreadyImported(jaCodeLines[i].trim(), generatedImports)) {
606 | userImports = userImports + jaCodeLines[i].trim() + "\n";
607 | verbose(YELLOW
608 | + jaCodeLines[i].trim().substring(
609 | jaCodeLines[i].trim().lastIndexOf(".") + 1,
610 | jaCodeLines[i].trim().lastIndexOf(";"))
611 | + " " + NORMAL, 0);
612 | printedResults = true;
613 | }
614 | jaCodeLines[i] = "";
615 | }
616 | }
617 | if (!printedResults)
618 | verbose("None", 0);
619 | verbose("");
620 |
621 | /* rebuild code without imports */
622 | javautoCode = "";
623 | for (String line : jaCodeLines)
624 | javautoCode = javautoCode + line + "\n";
625 |
626 | /* extract user global/class level variables */
627 | verbose("Getting user global variables... ", 0);
628 | printedResults = false;
629 | jaCodeLines = javautoCode.split("\n");
630 | for (int i = 0; i < jaCodeLines.length; i++) {
631 | if (jaCodeLines[i].trim().startsWith("global ")) {
632 | boolean empty = false;
633 | if (!jaCodeLines[i].trim().contains("="))
634 | empty = true; // they're just declaring it, not assigning
635 | // value
636 | String[] declarationParts = jaCodeLines[i].trim().split(" ");
637 | if (declarationParts[2].endsWith(";"))
638 | declarationParts[2] = declarationParts[2].substring(0,
639 | declarationParts[2].length() - 1);
640 | verbose(YELLOW + declarationParts[2] + " " + NORMAL, 0);
641 | printedResults = true;
642 | userGlobalVariables = userGlobalVariables + "public static "
643 | + declarationParts[1] + " " + declarationParts[2]
644 | + ";\n";
645 | String restOfDeclaration = "";
646 | for (int j = 2; j < declarationParts.length; j++)
647 | restOfDeclaration = restOfDeclaration + declarationParts[j]
648 | + " ";
649 | jaCodeLines[i] = restOfDeclaration;
650 | if (empty)
651 | jaCodeLines[i] = "";
652 | }
653 | }
654 | javautoCode = "";
655 | for (String line : jaCodeLines)
656 | javautoCode = javautoCode + line + "\n";
657 | if (!printedResults)
658 | verbose("None", 0);
659 | verbose("");
660 |
661 | /* extract user defined functions from code */
662 | verbose("Getting user functions... ", 0);
663 | String[] codeParts = splitUserFunctions(javautoCode);
664 | if (!printedResults)
665 | verbose("None", 0);
666 | verbose("");
667 | userFunctions = codeParts[0];
668 | userCode = codeParts[1];
669 |
670 | /* clean up the main user code */
671 | while (userCode.contains("\n\n"))
672 | userCode = userCode.replace("\n\n", "\n");
673 | userCode = indent(userCode, 2);
674 |
675 | /*
676 | * insert ~most~ of our generated and user sourced code into the
677 | * template
678 | */
679 | generatedCode = templateContents;
680 | generatedCode = generatedCode.replace("", "}");
681 | generatedCode = generatedCode.replace("", userImports);
682 | generatedCode = generatedCode.replace("",
683 | "public class " + userClassName + " {");
684 | generatedCode = generatedCode.replace("",
685 | indent(userGlobalVariables));
686 | generatedCode = generatedCode.replace("",
687 | "\tpublic static void main(String[] args) {\n" + userCode
688 | + "\n\t}\n");
689 | generatedCode = generatedCode.replace("",
690 | indent(userFunctions));
691 |
692 | /*
693 | * now we generate javauto functions based on what the user has
694 | * implemented until no replacements have been made
695 | */
696 | int replacements = 1;
697 | ArrayList alreadyGenerated = new ArrayList();
698 | verbose("Generating functions... ", 0);
699 | printedResults = false;
700 | String noLiteralsCode;
701 | while (replacements != 0) {
702 | replacements = 0;
703 | noLiteralsCode = removeLiterals(generatedCode);
704 | for (String[] javautoFunction : javautoFunctions) {
705 | /*
706 | * if a the function name + ( is present anywhere in our code
707 | * AND we haven't already generated a function for it
708 | */
709 | if (noLiteralsCode.contains(javautoFunction[0].trim())
710 | && !alreadyGenerated
711 | .contains(javautoFunction[0].trim())) {
712 | /* add code for that function to the file */
713 | generatedCode = generatedCode.replace(
714 | "<{_*_generatedFunctions_*_}>",
715 | removeComments(javautoFunction[1])
716 | + "\n<{_*_generatedFunctions_*_}>");
717 | verbose(YELLOW + javautoFunction[0] + " " + NORMAL, 0);
718 | printedResults = true;
719 |
720 | /* add function to the list of already generated functions */
721 | alreadyGenerated.add(javautoFunction[0]);
722 |
723 | /* there's been a replacement => increment the variable */
724 | replacements++;
725 |
726 | }
727 | }
728 | }
729 | if (!printedResults)
730 | verbose("None", 0);
731 | verbose("");
732 |
733 | /*
734 | * we've generated all the functions we need => remove the
735 | * tag
736 | */
737 | generatedCode = generatedCode.replace("<{_*_generatedFunctions_*_}>",
738 | "");
739 |
740 | /* build a list of class variable declarations and their variable names */
741 | ArrayList classVariableData = new ArrayList();
742 | for (String line : generatedVariables.split("\n")) {
743 | String[] parts = line.split("=")[0].split(" ");
744 | String name = parts[parts.length - 1].trim();
745 |
746 | /* make class variables static */
747 | String[] lineParts = line.trim().split(" ");
748 | String modifiedLine = lineParts[0] + " static ";
749 |
750 | for (int i = 1; i < lineParts.length; i++) {
751 | modifiedLine = modifiedLine + lineParts[i] + " ";
752 | }
753 |
754 | String[] data = { name, "\t" + modifiedLine.trim() };
755 | classVariableData.add(data);
756 | }
757 |
758 | /* check if the names are in the code => add the variable if they are */
759 | String usedVariables = "";
760 | String skeletonCode = removeLiterals(generatedCode);
761 | verbose("Generating class variables... ", 0);
762 | printedResults = false;
763 | for (String[] declaration : classVariableData) {
764 | if (skeletonCode.contains(declaration[0])) {
765 | usedVariables = usedVariables + declaration[1] + "\n";
766 | verbose(YELLOW + declaration[0] + " " + NORMAL, 0);
767 | printedResults = true;
768 | }
769 | }
770 | if (!printedResults)
771 | verbose("None", 0);
772 | verbose("");
773 |
774 | /* add all the variables we determine have been used */
775 | generatedCode = generatedCode.replace("",
776 | usedVariables);
777 |
778 | /* update the skeletonCode to inclue the generated variables */
779 | skeletonCode = removeLiterals(generatedCode);
780 |
781 | /* build a list of imported classes */
782 | ArrayList generatedImportData = new ArrayList();
783 | for (String line : generatedImports.split("\n")) {
784 | String importedClass = line.substring(line.lastIndexOf(".") + 1,
785 | line.lastIndexOf(";"));
786 | String[] data = { importedClass, line };
787 | generatedImportData.add(data);
788 | }
789 |
790 | /* check if class names are in code => add the import if they are */
791 | generatedImports = "";
792 | verbose("Generating imports... ", 0);
793 | printedResults = false;
794 | for (String[] d : generatedImportData) {
795 | if (skeletonCode.contains(d[0]) || d[0].equals("*")) {
796 | generatedImports = generatedImports + d[1] + "\n";
797 | verbose(YELLOW + d[0] + " " + NORMAL, 0);
798 | printedResults = true;
799 | }
800 | }
801 | if (!printedResults)
802 | verbose("None", 0);
803 | verbose("");
804 |
805 | /* parse out user struct declarations */
806 | verbose("Generating struct objects... ", 0);
807 | printedResults = false;
808 | String structName = "";
809 | do {
810 | String[] sParts = getStruct(generatedCode);
811 | structName = sParts[1];
812 | if (!structName.trim().equals("")) {
813 | structFiles.add(new String[] { sParts[1], sParts[2] });
814 | verbose(YELLOW + structName + " " + NORMAL, 0);
815 | printedResults = true;
816 | generatedCode = sParts[0];
817 | }
818 | } while (!structName.trim().equals(""));
819 | if (!printedResults)
820 | verbose("None", 0);
821 | verbose("");
822 |
823 | /* check if class names are in structs => add the import if they are */
824 | for (String[] d : generatedImportData) {
825 | for (int j = 0; j < structFiles.size(); j++) {
826 | String[] structFile = structFiles.get(j);
827 | if (structFile[1].contains(d[0]) || d[0].equals("*")) {
828 | structFile[1] = d[1] + "\n" + structFile[1];
829 | structFiles.set(j, structFile);
830 | }
831 | }
832 | }
833 |
834 | /* add all the imports we determine have been used */
835 | generatedCode = generatedCode.replace("",
836 | generatedImports);
837 |
838 | /* get rid of all empty lines */
839 | String[] generatedCodeLines = generatedCode.split("\n");
840 | generatedCode = "";
841 | for (int i = 0; i < generatedCodeLines.length; i++) {
842 | if (!generatedCodeLines[i].trim().equals(""))
843 | generatedCode = generatedCode + generatedCodeLines[i] + "\n";
844 | }
845 |
846 | return generatedCode;
847 | }
848 |
849 | /**
850 | * Searches user code for a struct, pieces it together, and returns the
851 | * struct code and the new user code.
852 | *
853 | * @param code
854 | * the user code
855 | * @return String array index 0: new user code index 1: the struct name
856 | * index 2: the struct code
857 | */
858 | private static String[] getStruct(String code) {
859 | /* split the user code into lines and characters for parsing */
860 | String[] codeLines = code.split("\n");
861 | char[] codeChars = code.toCharArray();
862 |
863 | /* get the indexes of string/character literals and comments */
864 | ArrayList> ignores = getIgnoreIndexes(code);
865 | ArrayList allIgnores = new ArrayList();
866 | allIgnores.addAll(ignores.get(0));
867 | allIgnores.addAll(ignores.get(1));
868 |
869 | /* look for a struct declaration */
870 | int startIndex = 0;
871 | for (int i = 0; i < codeLines.length; i++) {
872 | /* if a line starts with struct it's a struct declaration */
873 | if (removeComments(codeLines[i]).trim().startsWith("struct ")) {
874 | /*
875 | * increment the start index until we're at the beginning of the
876 | * declaration
877 | */
878 | while (inIgnoredText(startIndex, allIgnores)
879 | || codeChars[startIndex] != 's')
880 | startIndex++;
881 |
882 | /* find the index of the last bracket in the struct */
883 | int endIndex = startIndex;
884 | String insideElements = "";
885 | while (endIndex < codeChars.length) {
886 | if (codeChars[endIndex] == '{'
887 | && !inIgnoredText(endIndex, allIgnores)) {
888 | break;
889 | }
890 | endIndex++;
891 | }
892 | endIndex++;
893 | while (endIndex < codeChars.length) {
894 | if (codeChars[endIndex] == '}'
895 | && !inIgnoredText(endIndex, allIgnores)) {
896 | break;
897 | }
898 | insideElements = insideElements
899 | + String.valueOf(codeChars[endIndex]);
900 | endIndex++;
901 | }
902 | endIndex++;
903 |
904 | /* get the user code without the struct object */
905 | String newCode = code.substring(0, startIndex)
906 | + code.substring(endIndex, codeChars.length);
907 |
908 | /* get the name of the struct object to create */
909 | String structName = removeComments(
910 | code.substring(startIndex, endIndex)).split(" ")[1]
911 | .trim();
912 |
913 | /* get each individual variable within the struct */
914 | String[] insideElementsLines = insideElements.split("\n");
915 | for (int j = 0; j < insideElementsLines.length; j++) {
916 | insideElementsLines[j] = removeComments(
917 | insideElementsLines[j]).trim();
918 | }
919 | insideElements = "";
920 | for (String s : insideElementsLines)
921 | insideElements = insideElements + s;
922 | String[] elements = insideElements.split(";");
923 | for (int j = 0; j < elements.length; j++)
924 | elements[j] = "public " + elements[j].trim() + ";";
925 |
926 | /* construct java code from these elements */
927 | String elementCode = "";
928 | for (String e : elements)
929 | elementCode = elementCode + "\t" + e + "\n";
930 | elementCode = elementCode
931 | .substring(0, elementCode.length() - 1);
932 |
933 | /* construct code for the whole struct */
934 | String structCode = "public class " + structName + " {\n"
935 | + elementCode + "\n}";
936 |
937 | /* return our results */
938 | return new String[] { newCode, structName, structCode };
939 | }
940 | startIndex = startIndex + codeLines[i].length() + 1; // +1 for the
941 | // \n char
942 | }
943 | /* if we don't find anything */
944 | return new String[] { code, "", "" };
945 | }
946 |
947 | /**
948 | * Get the end index of a function
949 | *
950 | * @param userCode
951 | * the text from which to extract the function
952 | * @param lowerBound
953 | * the start index of the function
954 | * @return the end index of the function
955 | */
956 | private static int getFunctionUpperBound(String userCode, int lowerBound) {
957 | /* get the code as a char array */
958 | char[] codeChars = userCode.toCharArray();
959 |
960 | /* get the indexes of string/character literals and comments */
961 | ArrayList> ignores = getIgnoreIndexes(userCode);
962 | ArrayList allIgnores = new ArrayList();
963 | allIgnores.addAll(ignores.get(0));
964 | allIgnores.addAll(ignores.get(1));
965 |
966 | int startIndex = lowerBound;
967 |
968 | /* find the index of the first bracket in the func */
969 | int endIndex = startIndex;
970 | while (endIndex < codeChars.length) {
971 | if (codeChars[endIndex] == '{'
972 | && !inIgnoredText(endIndex, allIgnores)) {
973 | break;
974 | }
975 | endIndex++;
976 | }
977 | endIndex++;
978 |
979 | /* find the value of the last bracket in the func */
980 | int open = 1;
981 | int close = 0;
982 | while (open > close) {
983 | if (codeChars[endIndex] == '}'
984 | && !inIgnoredText(endIndex, allIgnores)) {
985 | close++;
986 | } else if (codeChars[endIndex] == '{'
987 | && !inIgnoredText(endIndex, allIgnores)) {
988 | open++;
989 | }
990 | endIndex++;
991 | }
992 | return endIndex;
993 | }
994 |
995 | /**
996 | * Split user code into an array; one indice will contain user functions and
997 | * the other will contain all other user code.
998 | *
999 | * @param userCode
1000 | * @return String[] { userFunctions, userCode }
1001 | */
1002 | private static String[] splitUserFunctions(String userCode) {
1003 | /* two variables to hold the two parts of the code */
1004 | String userFunctions = "";
1005 | String userNormalCode = "";
1006 |
1007 | /* keep track of the character index we're at */
1008 | int charIndex = 0;
1009 |
1010 | /* create a list to store function start & end indexes */
1011 | ArrayList functionIndexes = new ArrayList();
1012 |
1013 | /* iterate by lines looking for functions */
1014 | for (String line : userCode.split("\n")) {
1015 | /* check for function declaration */
1016 | if (line.trim().startsWith("func ")) {
1017 | int[] bounds = { charIndex,
1018 | getFunctionUpperBound(userCode, charIndex) };
1019 | functionIndexes.add(bounds);
1020 | }
1021 |
1022 | /* advance the character index (+1 for the \n char) */
1023 | charIndex = charIndex + line.length() + 1;
1024 | }
1025 |
1026 | /* split the original string into parts based on the function bounds */
1027 | int nonFunctionIndex = 0;
1028 | for (int[] bounds : functionIndexes) {
1029 | /*
1030 | * append what is outside the function bounds to the userNormalCode
1031 | * variable
1032 | */
1033 | userNormalCode = userNormalCode
1034 | + userCode.substring(nonFunctionIndex, bounds[0]) + "\n";
1035 |
1036 | /*
1037 | * get the current user function & change its first line for java
1038 | * func decalration
1039 | */
1040 | String[] functionLines = userCode.substring(bounds[0], bounds[1])
1041 | .split("\n");
1042 | functionLines[0] = functionLines[0].trim();
1043 |
1044 | /* remove the first five letters; the "func " & add in public */
1045 | functionLines[0] = "public static " + functionLines[0].substring(5);
1046 |
1047 | /* get the function name for verbose output */
1048 | String[] fparts = functionLines[0].split(" ");
1049 | String restoff = "";
1050 | for (int i = 3; i < fparts.length; i++)
1051 | restoff = restoff + fparts[i] + " ";
1052 | verbose(YELLOW + restoff.substring(0, restoff.indexOf("(")) + " "
1053 | + NORMAL, 0);
1054 | printedResults = true;
1055 |
1056 | /* add each of the elements in the array together into a function */
1057 | String function = "";
1058 | for (int i = 0; i < functionLines.length; i++) {
1059 | if (i != 0 && i < functionLines.length - 1)
1060 | function = function + "\t" + functionLines[i] + "\n";
1061 | else
1062 | function = function + functionLines[i] + "\n";
1063 |
1064 | }
1065 |
1066 | /*
1067 | * append what is inside the function bounds to the userFunctions
1068 | * variable
1069 | */
1070 | userFunctions = userFunctions + function + "\n\n";
1071 |
1072 | /*
1073 | * advance the lower bound of the "non function" code to the upper
1074 | * bound of the function code
1075 | */
1076 | nonFunctionIndex = bounds[1];
1077 | }
1078 |
1079 | /* add any remaining code to the user "non-function" code */
1080 | userNormalCode = userNormalCode
1081 | + userCode.substring(nonFunctionIndex, userCode.length());
1082 |
1083 | /* return the two parts */
1084 | String[] r = { userFunctions, userNormalCode };
1085 | return r;
1086 | }
1087 |
1088 | /**
1089 | * Search the javautoFile for imports and add them all to the generated
1090 | * imports
1091 | *
1092 | * @return imports that have been generated
1093 | */
1094 | private static String generateImports() {
1095 | /* get raw file contents of the file containing our imports */
1096 | String[] importContents = resourceRead(javautoFile).split("\n");
1097 |
1098 | /* variable to store our generated imports */
1099 | String imports = "";
1100 |
1101 | /* add each line that starts with "import " to our imports variable */
1102 | for (String importLine : importContents) {
1103 | if (importLine.startsWith("import "))
1104 | imports = imports + importLine + "\n";
1105 | }
1106 |
1107 | /* return our imports */
1108 | return imports;
1109 | }
1110 |
1111 | /**
1112 | * Search the javautoFile for all class variables and return them
1113 | *
1114 | * @return class variables that have been generated
1115 | */
1116 | private static String generateVariables() {
1117 | /* get raw file contents of the file containing our variables */
1118 | String[] variablesContents = resourceRead(javautoFile).split("\n");
1119 |
1120 | /* variable to store our generated class vars */
1121 | String classVars = "";
1122 |
1123 | /* add each line that has a class varaible to our classVars */
1124 | for (String line : variablesContents) {
1125 | if ((line.trim().startsWith("public ") || line.trim().startsWith(
1126 | "private "))
1127 | && line.trim().endsWith(";"))
1128 | classVars = classVars + line + "\n";
1129 | }
1130 |
1131 | /* return our class vars */
1132 | return classVars;
1133 | }
1134 |
1135 | /**
1136 | * Gets a list of functions and their source code from the javautoFile
1137 | *
1138 | * @return ArrayList with each element containing {function name,
1139 | * function code}
1140 | */
1141 | private static ArrayList getFunctions() {
1142 | /* define the list where we'll store all the data */
1143 | ArrayList functionDataList = new ArrayList();
1144 |
1145 | /* get raw file contents of the file containing our functions */
1146 | String functionContents = resourceRead(javautoFile);
1147 |
1148 | /* split into lines for evaluation */
1149 | String[] functionContentsLines = functionContents.split("\n");
1150 |
1151 | /* check each line and extract function names */
1152 | for (String line : functionContentsLines) {
1153 | /*
1154 | * if the line is like "public *{" or "private *{" but isn't like
1155 | * "public class"
1156 | */
1157 | if ((line.trim().startsWith("public ") || line.trim().startsWith(
1158 | "private "))
1159 | && (line.trim().endsWith("{"))
1160 | && (!line.trim().startsWith("public class"))) {
1161 | /*
1162 | * if it meets the above criteria it's a function & we add it to
1163 | * the list
1164 | */
1165 |
1166 | /* get function name & code */
1167 | String functionName = line.trim().split(" ")[2].split("[(]")[0];
1168 | String functionCode = getFunctionCode(line, functionContents);
1169 |
1170 | /*
1171 | * modify the function code so that the declaration becomes
1172 | * static
1173 | */
1174 | String[] lines = functionCode.split("\n");
1175 | lines[0] = lines[0].trim();
1176 | if (lines[0].startsWith("private ")) {
1177 | lines[0] = "\tprivate static " + lines[0].substring(8);
1178 | } else if (lines[0].startsWith("public ")) {
1179 | lines[0] = "\tpublic static " + lines[0].substring(7);
1180 | }
1181 | functionCode = "";
1182 | for (String l : lines)
1183 | functionCode = functionCode + l + "\n";
1184 |
1185 | /*
1186 | * add it to the list unless it's the "run" function used in a
1187 | * thread
1188 | */
1189 | if (!functionName.toLowerCase().equals("run")) {
1190 | String[] function = { functionName.trim(), functionCode };
1191 | functionDataList.add(function);
1192 | }
1193 | }
1194 | }
1195 |
1196 | /* return our list without duplicates */
1197 | return combineFunctionDuplicates(functionDataList);
1198 | }
1199 |
1200 | /**
1201 | * Take an array list with each item having a format {function name,
1202 | * function code} and combine duplicate function names into one entry that
1203 | * still has the source code of each so an array list containing two
1204 | * elements like this: {doSomething, code1}, {doSomething, code2} would
1205 | * become {doSomething, code1\n\ncode2} combineFunctionDuplicates() is
1206 | * necessary because some of our functions are defined multiple times to
1207 | * allow for different parameters and this allows us to add all iterations
1208 | * of a function at once.
1209 | *
1210 | * @param functionListWithDuplicates
1211 | * the list to run through
1212 | * @return a version of the list without duplicates but with all the code
1213 | */
1214 | private static ArrayList combineFunctionDuplicates(
1215 | ArrayList functionListWithDuplicates) {
1216 | /* define our final list that wont have duplicates */
1217 | ArrayList functionListNoDuplicates = new ArrayList();
1218 |
1219 | /* list to keep track of function names that have already been combined */
1220 | ArrayList alreadyCombined = new ArrayList();
1221 |
1222 | for (String[] f : functionListWithDuplicates) {
1223 | /* the name of the function is stored in the first indice */
1224 | String functionName = f[0];
1225 |
1226 | /* if we haven't already combined the function */
1227 | if (!alreadyCombined.contains(functionName)) {
1228 | /* the combined code of all functions of the same name */
1229 | String combinedCode = "";
1230 |
1231 | /* check every item in the list */
1232 | for (String[] function : functionListWithDuplicates) {
1233 | /* if the names match add the code in */
1234 | if (functionName.equals(function[0])) {
1235 | combinedCode = combinedCode + function[1] + "\n\n";
1236 | }
1237 | }
1238 |
1239 | /* add the function to the list */
1240 | String[] combinedFunction = { functionName, combinedCode };
1241 | functionListNoDuplicates.add(combinedFunction);
1242 |
1243 | /* mark the name as covered */
1244 | alreadyCombined.add(functionName);
1245 | }
1246 | }
1247 |
1248 | /* return our final results */
1249 | return functionListNoDuplicates;
1250 | }
1251 |
1252 | /**
1253 | * Get the code for a single function from a java file of functions based
1254 | * off its signature
1255 | *
1256 | * @param signature
1257 | * All or part of the function signature, eg.
1258 | * "public void function(int i)" If there are two declarations
1259 | * with the same name and you only provide
1260 | * "public void functionName" it will return the first one. To
1261 | * get a specific one include the full signature like
1262 | * "public void functionName(int i, int j)"
1263 | * @param fullFunctionsText
1264 | * The contents of a java file that contains the function we're
1265 | * trying to extract
1266 | * @return Full text of the single function we're trying to find
1267 | */
1268 | private static String getFunctionCode(String signature, String wholeFile) {
1269 | /* find the index of the function */
1270 | int funcIndex = wholeFile.indexOf(signature);
1271 |
1272 | /* trim the file so that it starts at this index */
1273 | wholeFile = wholeFile.substring(funcIndex);
1274 |
1275 | /* file as string -> file as char array */
1276 | char[] wholeFileChars = wholeFile.toCharArray();
1277 |
1278 | /* variables to hold position and brace counts */
1279 | int index = 0;
1280 | int openBrace = 0;
1281 | int closeBrace = 0;
1282 |
1283 | /* find the opening bracket of function */
1284 | while (openBrace == 0) {
1285 |
1286 | /* if we find the brace we're done */
1287 | if (wholeFileChars[index] == '{') {
1288 | openBrace++;
1289 | index++;
1290 | }
1291 |
1292 | /* check for different kinds of comments */
1293 | else if (wholeFileChars[index] == '/') {
1294 | index++;
1295 |
1296 | /* if it's // comment until end of line */
1297 | if (wholeFileChars[index] == '/') {
1298 | while (wholeFileChars[index] != '\n') {
1299 | index++;
1300 | }
1301 | index++;
1302 | }
1303 |
1304 | /* if it's a /* comment until * / */
1305 | else if (wholeFileChars[index] == '*') {
1306 | index++;
1307 | boolean done = false;
1308 | while (done == false) {
1309 | if (wholeFileChars[index] == '*') {
1310 | index++;
1311 | if (wholeFileChars[index] == '/') {
1312 | index++;
1313 | done = true;
1314 | }
1315 | } else {
1316 | index++;
1317 | }
1318 | }
1319 | }
1320 | }
1321 |
1322 | /* if it's some other character just keep going */
1323 | else {
1324 | index++;
1325 | }
1326 | }
1327 |
1328 | while (openBrace > closeBrace) {
1329 | /* if we find a brace then increment */
1330 | if (wholeFileChars[index] == '{') {
1331 | openBrace++;
1332 | index++;
1333 | } else if (wholeFileChars[index] == '}') {
1334 | closeBrace++;
1335 | index++;
1336 | }
1337 |
1338 | /* check for string literals */
1339 | else if (wholeFileChars[index] == '"') {
1340 | index++;
1341 | while (wholeFileChars[index] != '"') {
1342 | if (wholeFileChars[index] == '\\') {
1343 | index++;
1344 | }
1345 | index++;
1346 | }
1347 | index++;
1348 | }
1349 |
1350 | /* check for character literals */
1351 | else if (wholeFileChars[index] == '\'') {
1352 | index++;
1353 | while (wholeFileChars[index] != '\'') {
1354 | if (wholeFileChars[index] == '\\') {
1355 | index++;
1356 | }
1357 | index++;
1358 | }
1359 | index++;
1360 | }
1361 |
1362 | /* check for different kinds of comments */
1363 | else if (wholeFileChars[index] == '/') {
1364 | index++;
1365 |
1366 | /* if it's // comment until end of line */
1367 | if (wholeFileChars[index] == '/') {
1368 | while (wholeFileChars[index] != '\n') {
1369 | index++;
1370 | }
1371 | index++;
1372 | }
1373 |
1374 | /* if it's a /* comment until * / */
1375 | else if (wholeFileChars[index] == '*') {
1376 | index++;
1377 | boolean done = false;
1378 | while (done == false) {
1379 | if (wholeFileChars[index] == '*') {
1380 | index++;
1381 | if (wholeFileChars[index] == '/') {
1382 | index++;
1383 | done = true;
1384 | }
1385 | } else {
1386 | index++;
1387 | }
1388 | }
1389 | }
1390 | }
1391 |
1392 | /* if it's some other character just keep going */
1393 | else {
1394 | index++;
1395 | }
1396 |
1397 | }
1398 |
1399 | return wholeFile.substring(0, index + 1);
1400 | }
1401 |
1402 | /**
1403 | * Handle all python like string replacements ("%s" % something) within a
1404 | * string.
1405 | *
1406 | * @param data
1407 | * Data within which replacements happen.
1408 | * @return Data with all replacements done.
1409 | */
1410 | private static String doPythonStringReplacements(String data) {
1411 | /*
1412 | * As long as some are being replaced keep replacing them. We have to do
1413 | * this one at a time because as soon as one part is changed the indexes
1414 | * to ignore (string literals and comments) change so we have to rebuild
1415 | * everything
1416 | */
1417 | String replaced = "some";
1418 | while (replaced.equals("some")) {
1419 | String[] returned = doPythonStringReplacement(data);
1420 | replaced = returned[1];
1421 | data = returned[0];
1422 | }
1423 | return data;
1424 | }
1425 |
1426 | /**
1427 | * Handle a _single_ python style string replacement within a string. For
1428 | * instance, the following string: System.out.println("Time: \t%s" %
1429 | * (time)); Would become:
1430 | * System.out.println("Time: \t%s".replaceFirst("%s",time));
1431 | *
1432 | * @param data
1433 | * the string to search through and perform a replacement in.
1434 | * @return a string array, the first index being the modified string data,
1435 | * the second index being either "some" or "none", depending on if a
1436 | * replacement was made or if no replacement was made.
1437 | */
1438 | private static String[] doPythonStringReplacement(String data) {
1439 | /* build a regex for the data */
1440 | String regexp = "(\".+\")(\\s*%\\s*(\\())";
1441 | Pattern pattern = Pattern.compile(regexp);
1442 | Matcher matcher = pattern.matcher(data);
1443 |
1444 | /* build ignore lists for the data */
1445 | ArrayList> ignores = getIgnoreIndexes(data);
1446 | ArrayList commentIgnores = ignores.get(0);
1447 | ArrayList literalIgnores = ignores.get(1);
1448 |
1449 | /* use these indexes to populate a list of general ignore indexes */
1450 | ArrayList allIgnores = new ArrayList();
1451 | for (Integer[] j : commentIgnores)
1452 | allIgnores.add(j);
1453 | for (Integer[] j : literalIgnores)
1454 | allIgnores.add(j);
1455 |
1456 | while (matcher.find()) {
1457 | /* use the regex search to get all the relevant indexes */
1458 | int matchedStartIndex = matcher.start();
1459 | int literalEndIndex = matchedStartIndex + matcher.group(1).length();
1460 | int elementsStartIndex = matcher.end() - matcher.group(3).length();
1461 |
1462 | /*
1463 | * this is the index of the % character -- it's the "check index"
1464 | * because we can check whether it's inside a comment/string to see
1465 | * if we should actually do the modification.
1466 | */
1467 | int checkIndex = matcher.end() - matcher.group(2).length();
1468 |
1469 | /* only proceed if the checkIndex isn't inside our ignore list */
1470 | if (!inIgnoredText(checkIndex, allIgnores)) {
1471 | /*
1472 | * find the upper bound of the elements we're adding into the
1473 | * string
1474 | */
1475 | int elementsEndIndex = findEndParen(elementsStartIndex, data,
1476 | allIgnores);
1477 |
1478 | /* get the elements that need to be subbed in */
1479 | ArrayList elements = getElements(elementsStartIndex,
1480 | elementsEndIndex, data, allIgnores);
1481 |
1482 | /* build the .replaceFirst() line */
1483 | String rCode = "";
1484 | for (String e : elements) {
1485 | rCode = rCode + ".replaceFirst(\"%s\"," + e + ")";
1486 | }
1487 |
1488 | /* build the whole literal */
1489 | String modString = data.substring(matchedStartIndex,
1490 | literalEndIndex) + rCode;
1491 |
1492 | /* build a new string with the replacement */
1493 | String fixed = data.substring(0, matchedStartIndex) + modString
1494 | + data.substring(elementsEndIndex);
1495 |
1496 | return new String[] { fixed, "some" };
1497 | }
1498 | }
1499 |
1500 | /* if we get to this point no replacements have been made */
1501 | return new String[] { data, "none" };
1502 | }
1503 |
1504 | /**
1505 | * Get each element inside of a tuple like structure. So for a given line of
1506 | * code: String intro = "My name is %s %s %s" % ("John",
1507 | * getMiddleName("John"), getLastName("John")); The tuple-like structure
1508 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The element list
1509 | * would look like ["\"John\"", "getMiddleName(\"John\")",
1510 | * "getLastName(\"John\")"]
1511 | *
1512 | * @param startElement
1513 | * the index of the opening ( of the tuple-like structure
1514 | * @param endElements
1515 | * the index of the closing ) of the tuple-like structure
1516 | * @param context
1517 | * the greater string in which it resides
1518 | * @param indexesToIgnore
1519 | * a list of index bounds we want to ignore, eg comments or
1520 | * string literals. Each element should have the format
1521 | * [startOfIgnore, endOfIgnore]
1522 | * @return a list of individual elements
1523 | */
1524 | private static ArrayList getElements(int startElement,
1525 | int endElement, String context, ArrayList indexesToIgnore) {
1526 | /* get the comma indexes */
1527 | ArrayList splitIndexes = getElementCommas(startElement,
1528 | endElement, context, indexesToIgnore);
1529 |
1530 | /* add the beginning and end of the structure to the slip indexes */
1531 | splitIndexes.add(0, startElement);
1532 | splitIndexes.add(endElement - 1);
1533 |
1534 | /* list to hold the elements we parse */
1535 | ArrayList elements = new ArrayList();
1536 |
1537 | if (splitIndexes.size() > 0) {
1538 | for (int i = 1; i < splitIndexes.size(); i++) {
1539 | elements.add(context.substring(splitIndexes.get(i - 1) + 1,
1540 | splitIndexes.get(i)).trim());
1541 | }
1542 | }
1543 |
1544 | return elements;
1545 | }
1546 |
1547 | /**
1548 | * Very specific use. Gets the "real" commas inside of a tuple-like
1549 | * structure. This shows which indexes it would return for an example:
1550 | * ("parameter1", someFunction("foo", getData("foo", "bar")), "parameter3")
1551 | * ^ ^
1552 | *
1553 | * @param startElement
1554 | * the index of the beginning of the tuple like element
1555 | * @param endElement
1556 | * the index of the end of the tuple like element
1557 | * @param context
1558 | * the String within which this "tuple" is contained
1559 | * @param indexesToIgnore
1560 | * a list of index bounds we want to ignore, eg comments or
1561 | * string literals. Each element should have the format
1562 | * [startOfIgnore, endOfIgnore]
1563 | * @return a List of indexes where "true" commas are present
1564 | */
1565 | private static ArrayList getElementCommas(int startElement,
1566 | int endElement, String context, ArrayList indexesToIgnore) {
1567 | /* to store our final values */
1568 | ArrayList realCommas = new ArrayList();
1569 |
1570 | char[] contextChars = context.toCharArray();
1571 |
1572 | int index = startElement + 1; // the plus one is to skip the initial (
1573 |
1574 | /* search through every character in the string */
1575 | while (index < endElement) {
1576 | /*
1577 | * if it's a comma and it's not inside our comments/literals add it
1578 | * to the list
1579 | */
1580 | if (contextChars[index] == ','
1581 | && !inIgnoredText(index, indexesToIgnore)) {
1582 | realCommas.add(index);
1583 | index++;
1584 | }
1585 | /*
1586 | * if it's an open paren but it isn't inside a comment/literal skip
1587 | * to the end paren
1588 | */
1589 | else if (contextChars[index] == '('
1590 | && !inIgnoredText(index, indexesToIgnore)) {
1591 | index = findEndParen(index, context, indexesToIgnore);
1592 | }
1593 | /* otherwise it's just a normal character so skip to the next one */
1594 | else {
1595 | index++;
1596 | }
1597 | }
1598 |
1599 | /* now that we're all the way through return our list */
1600 | return realCommas;
1601 | }
1602 |
1603 | /**
1604 | * Given the index of a '(', find the corresponding ')'.
1605 | *
1606 | * @param startParen
1607 | * the index of the '('.
1608 | * @param context
1609 | * the string within which the parens are located.
1610 | * @param indexesToIgnore
1611 | * A list of Integers like [start, end] that specify indexes that
1612 | * should be ignored, this list usually contains the start and
1613 | * end bounds of each comment and string literal in the context.
1614 | * @return the index of the closing paren
1615 | */
1616 | private static int findEndParen(int startParen, String context,
1617 | ArrayList indexesToIgnore) {
1618 | char[] contextChars = context.toCharArray();
1619 | int index = startParen + 1;
1620 | int open = 1;
1621 | int close = 0;
1622 | while (open > close) {
1623 | /*
1624 | * if the current character is a ( and it's not inside a comment or
1625 | * literal
1626 | */
1627 | if (contextChars[index] == '('
1628 | && !inIgnoredText(index, indexesToIgnore)) {
1629 | open++;
1630 | }
1631 | /*
1632 | * if the current character is a ) and it's not inside a comment or
1633 | * literal
1634 | */
1635 | else if (contextChars[index] == ')'
1636 | && !inIgnoredText(index, indexesToIgnore)) {
1637 | close++;
1638 | }
1639 | /* on to the next one */
1640 | index++;
1641 | }
1642 | return index;
1643 | }
1644 |
1645 | /**
1646 | * Determines if a character is inside any of the bounds of a list of blocks
1647 | * of text to ignore.
1648 | *
1649 | * @param charIndex
1650 | * the index of the character whose position is being checked
1651 | * @param ignoredIndex
1652 | * a list of items like [int startIgnoreIndex, int
1653 | * endIgnoreIndex] that specifies which indexes are supposed to
1654 | * be ignored
1655 | * @return returns true if the character index is within any of the ignore
1656 | * bounds, otherwise returns false.
1657 | */
1658 | private static boolean inIgnoredText(int charIndex,
1659 | ArrayList ignoredIndexes) {
1660 | /* check each set of bounds to see if they hold our charIndex */
1661 | for (Integer[] i : ignoredIndexes) {
1662 | if (charIndex >= i[0] && charIndex <= i[1])
1663 | return true;
1664 | }
1665 |
1666 | /* if we got to here we haven't found it inside any of the bounds */
1667 | return false;
1668 | }
1669 |
1670 | /**
1671 | * Build a list of character indexes that should be ignored during
1672 | * processing. Characters to be ignored are those inside of comments, string
1673 | * literals, and character literals. This function returns the bounds of
1674 | * indexes of characters and literals in two separate lists.
1675 | *
1676 | * @param code
1677 | * the string to generate this list of bounds for
1678 | * @return returns two ArrayList objects, wrapped inside of one
1679 | * ArrayList, with the format [comment indexes, literal indexes].
1680 | * Then each of those elements is a list with the format [start
1681 | * ignore index, end ignore index].
1682 | */
1683 | private static ArrayList> getIgnoreIndexes(String code) {
1684 | /* Lists to hold bounds for both comments and literals */
1685 | ArrayList commentIndexes = new ArrayList();
1686 | ArrayList literalIndexes = new ArrayList();
1687 |
1688 | /*
1689 | * List to hold our other two lists, so that the user can separate them
1690 | * at will
1691 | */
1692 | ArrayList> finalValues = new ArrayList>();
1693 |
1694 | /*
1695 | * iterate through character by character looking for comments and
1696 | * literals
1697 | */
1698 | char[] codeChars = code.toCharArray();
1699 | int index = 0;
1700 | while (index < codeChars.length) {
1701 | if (codeChars[index] == '/') {
1702 | Integer startIndex = -1;
1703 | Integer endIndex = -1;
1704 |
1705 | index++;
1706 |
1707 | if (codeChars[index] == '/') {
1708 | startIndex = index - 1;
1709 | index++;
1710 | while (codeChars[index] != '\n') {
1711 | index++;
1712 | if (index == codeChars.length) {
1713 | index--;
1714 | break;
1715 | }
1716 | }
1717 | endIndex = index;
1718 | index++;
1719 | } else if (codeChars[index] == '*') {
1720 | startIndex = index - 1;
1721 | index++;
1722 | boolean done = false;
1723 | while (!done) {
1724 | if (codeChars[index] == '*') {
1725 | index++;
1726 | if (codeChars[index] == '/') {
1727 | done = true;
1728 | endIndex = index;
1729 | }
1730 | }
1731 | index++;
1732 | }
1733 | }
1734 |
1735 | /* if we found stuff add to array */
1736 | if (startIndex != -1)
1737 | commentIndexes.add(new Integer[] { startIndex, endIndex });
1738 | } else if (codeChars[index] == '"') {
1739 | Integer startIndex = index;
1740 | Integer endIndex = -1;
1741 | index++;
1742 |
1743 | while (codeChars[index] != '"') {
1744 | if (codeChars[index] == '\\') {
1745 | index++;
1746 | }
1747 | index++;
1748 | }
1749 | endIndex = index;
1750 | index++;
1751 |
1752 | /* add to array */
1753 | literalIndexes.add(new Integer[] { startIndex, endIndex });
1754 | } else if (codeChars[index] == '\'') {
1755 | Integer startIndex = index;
1756 | Integer endIndex = -1;
1757 | index++;
1758 |
1759 | while (codeChars[index] != '\'') {
1760 | if (codeChars[index] == '\\') {
1761 | index++;
1762 | }
1763 | index++;
1764 | }
1765 | endIndex = index;
1766 | index++;
1767 |
1768 | /* add to array */
1769 | literalIndexes.add(new Integer[] { startIndex, endIndex });
1770 | } else {
1771 | index++;
1772 | }
1773 | }
1774 |
1775 | /* put our two lists inside of a third list */
1776 | finalValues.add(commentIndexes);
1777 | finalValues.add(literalIndexes);
1778 |
1779 | /* return our final list */
1780 | return finalValues;
1781 | }
1782 |
1783 | /**
1784 | * Removes all comments from a String and return the stripped String
1785 | * "Th/*comment*\/is line //other stuff" becomes "This line" Necessary so
1786 | * that line by line searching for beginning/ending with things can be
1787 | * accurate
1788 | *
1789 | * @param commented
1790 | * The String to remove comments from
1791 | * @return String stripped of comments
1792 | */
1793 | private static String removeComments(String commented) {
1794 | /* string -> char array, so we can analyze one char at a time */
1795 | char[] commentedChars = commented.toCharArray();
1796 |
1797 | /* variable to hold our position */
1798 | int index = 0;
1799 |
1800 | /* variable to hold our final String */
1801 | String noComments = "";
1802 |
1803 | /* go through each character */
1804 | while (index < commentedChars.length) {
1805 | /* check for a string literal */
1806 | if (commentedChars[index] == '"') {
1807 | /*
1808 | * we don't want to remove something that looks like a comment
1809 | * if it's in here
1810 | */
1811 | noComments = noComments + String.valueOf(commentedChars[index]);
1812 | index++;
1813 | while (commentedChars[index] != '"') {
1814 | noComments = noComments
1815 | + String.valueOf(commentedChars[index]);
1816 | if (commentedChars[index] == '\\') {
1817 | index++;
1818 | noComments = noComments
1819 | + String.valueOf(commentedChars[index]);
1820 | }
1821 | index++;
1822 | }
1823 | noComments = noComments + String.valueOf(commentedChars[index]);
1824 | index++;
1825 | }
1826 |
1827 | /* check for character literals */
1828 | else if (commentedChars[index] == '\'') {
1829 | noComments = noComments + String.valueOf(commentedChars[index]);
1830 | index++;
1831 | while (commentedChars[index] != '\'') {
1832 | noComments = noComments
1833 | + String.valueOf(commentedChars[index]);
1834 | if (commentedChars[index] == '\\') {
1835 | index++;
1836 | noComments = noComments
1837 | + String.valueOf(commentedChars[index]);
1838 | }
1839 | index++;
1840 | }
1841 | noComments = noComments + String.valueOf(commentedChars[index]);
1842 | index++;
1843 | }
1844 |
1845 | /* check for the start of a comment */
1846 | else if (commentedChars[index] == '/') {
1847 | index++;
1848 |
1849 | /* if it's this // kind of comment */
1850 | if (commentedChars[index] == '/') {
1851 | index++;
1852 | while (commentedChars[index] != '\n') {
1853 | index++;
1854 | if (index >= commentedChars.length) {
1855 | return noComments;
1856 | }
1857 | }
1858 | noComments = noComments + "\n";
1859 | index++;
1860 | }
1861 | /* if it's this /* kind of comment */
1862 | else if (commentedChars[index] == '*') {
1863 | index++;
1864 | boolean done = false;
1865 | while (done == false) {
1866 | /* maybe it's finishing... */
1867 | if (commentedChars[index] == '*') {
1868 | index++;
1869 | if (commentedChars[index] == '/') {
1870 | done = true;
1871 | }
1872 | index++;
1873 | } else {
1874 | index++;
1875 | }
1876 |
1877 | }
1878 | }
1879 | /* if it's not even a comment */
1880 | else {
1881 | noComments = noComments + "/";
1882 | }
1883 | }
1884 |
1885 | /* if there's no doubt just add it on */
1886 | else {
1887 | noComments = noComments + String.valueOf(commentedChars[index]);
1888 | index++;
1889 | }
1890 | }
1891 | return noComments;
1892 | }
1893 |
1894 | /**
1895 | * Removes all String/char literals from a String and return the stripped
1896 | * String "System.out.println("\"Hello,\" he said." +
1897 | * String.valueOf('\n'));" becomes "System.out.println( +
1898 | * String.valueOf());" Doesn't remove literals from comments, so
1899 | * "// Method "removeLiterals" removes literals" would be untouched
1900 | * Necessary so that we can reliably check which functions are present in
1901 | * user code
1902 | *
1903 | * @param stringWithLiterals
1904 | * The String to remove String/char literals from
1905 | * @return String stripped of literals
1906 | */
1907 | private static String removeLiterals(String stringWithLiterals) {
1908 | /* string -> char array, so we can analyze one char at a time */
1909 | char[] literalsChars = stringWithLiterals.toCharArray();
1910 |
1911 | /* variable to hold our position */
1912 | int index = 0;
1913 |
1914 | /* variable to hold our final String */
1915 | String noLiterals = "";
1916 |
1917 | /* go through each character */
1918 | while (index < literalsChars.length) {
1919 | /* check for a string literal */
1920 | if (literalsChars[index] == '"') {
1921 | index++;
1922 | while (literalsChars[index] != '"') {
1923 | if (literalsChars[index] == '\\') {
1924 | index++;
1925 | }
1926 | index++;
1927 | }
1928 | index++;
1929 | }
1930 |
1931 | /* check for character literals */
1932 | else if (literalsChars[index] == '\'') {
1933 | index++;
1934 | while (literalsChars[index] != '\'') {
1935 | if (literalsChars[index] == '\\') {
1936 | index++;
1937 | }
1938 | index++;
1939 | }
1940 | index++;
1941 | }
1942 |
1943 | /* check for the start of a comment */
1944 | else if (literalsChars[index] == '/') {
1945 | noLiterals = noLiterals + String.valueOf(literalsChars[index]);
1946 | index++;
1947 |
1948 | /* if it's this // kind of comment */
1949 | if (literalsChars[index] == '/') {
1950 | noLiterals = noLiterals
1951 | + String.valueOf(literalsChars[index]);
1952 | index++;
1953 | while (literalsChars[index] != '\n') {
1954 | noLiterals = noLiterals
1955 | + String.valueOf(literalsChars[index]);
1956 | index++;
1957 | }
1958 | noLiterals = noLiterals + "\n";
1959 | index++;
1960 | }
1961 | /* if it's this /* kind of comment */
1962 | else if (literalsChars[index] == '*') {
1963 | noLiterals = noLiterals
1964 | + String.valueOf(literalsChars[index]);
1965 | index++;
1966 | boolean done = false;
1967 | while (done == false) {
1968 | noLiterals = noLiterals
1969 | + String.valueOf(literalsChars[index]);
1970 | /* maybe it's finishing... */
1971 | if (literalsChars[index] == '*') {
1972 | index++;
1973 | noLiterals = noLiterals
1974 | + String.valueOf(literalsChars[index]);
1975 | if (literalsChars[index] == '/') {
1976 | done = true;
1977 | }
1978 | index++;
1979 | } else {
1980 | index++;
1981 | }
1982 | }
1983 | }
1984 | /* if it's not even a comment */
1985 | else {
1986 | noLiterals = noLiterals + "/";
1987 | }
1988 | }
1989 |
1990 | /* if there's no doubt just add it on */
1991 | else {
1992 | noLiterals = noLiterals + String.valueOf(literalsChars[index]);
1993 | index++;
1994 | }
1995 | }
1996 | return noLiterals;
1997 | }
1998 |
1999 | /**
2000 | * Reads file contents (from a resource inside the JAR) into string
2001 | *
2002 | * @param resourcePath
2003 | * the path to the resource within the JAR file
2004 | * @return file contents as string
2005 | */
2006 | private static String resourceRead(String resourcePath) {
2007 | try {
2008 | InputStream inputStream = Thread.currentThread()
2009 | .getContextClassLoader().getResourceAsStream(resourcePath);
2010 | BufferedReader bufferedReader = new BufferedReader(
2011 | new InputStreamReader(inputStream, "UTF-8"));
2012 | StringBuilder stringBuilder = new StringBuilder();
2013 | String line = bufferedReader.readLine();
2014 | while (line != null) {
2015 | stringBuilder.append(line);
2016 | if (line != null) {
2017 | stringBuilder.append("\n");
2018 | }
2019 | line = bufferedReader.readLine();
2020 | }
2021 | return stringBuilder.toString();
2022 | } catch (Exception e) {
2023 | System.out
2024 | .println("Compiler encountered an error reading JAR resource \""
2025 | + resourcePath
2026 | + "\" -- the JAR file may be corrupt.");
2027 | e.printStackTrace();
2028 | System.exit(1);
2029 | return "";
2030 | }
2031 | }
2032 |
2033 | /**
2034 | * Reads file contents into a string
2035 | *
2036 | * @param filePath
2037 | * path of file to read
2038 | * @return file contents as string
2039 | */
2040 | private static String fileRead(String filePath) {
2041 | try {
2042 | BufferedReader br = new BufferedReader(new FileReader(filePath));
2043 | StringBuilder data = new StringBuilder();
2044 | String line = br.readLine();
2045 | while (line != null) {
2046 | data.append(line);
2047 | data.append('\n');
2048 | line = br.readLine();
2049 | }
2050 | String fileData = data.toString();
2051 | br.close();
2052 | return fileData;
2053 | } catch (Exception e) {
2054 | System.out.println("Compiler encountered an error reading file \""
2055 | + filePath + "\"");
2056 | e.printStackTrace();
2057 | System.exit(1);
2058 | return "null";
2059 | }
2060 | }
2061 |
2062 | /**
2063 | * Write data to a file
2064 | *
2065 | * @param fPath
2066 | * the file to write to
2067 | * @param data
2068 | * the data to write to file
2069 | * @return true or false with success/failure
2070 | */
2071 | private static boolean fileWrite(String fPath, String data) {
2072 | BufferedWriter bufferedWriter = null;
2073 | boolean encounteredError = false;
2074 | try {
2075 | File myFile = new File(fPath);
2076 | if (!myFile.exists())
2077 | myFile.createNewFile();
2078 | Writer writer = new FileWriter(myFile);
2079 | bufferedWriter = new BufferedWriter(writer);
2080 | bufferedWriter.write(data);
2081 | return true;
2082 | } catch (IOException e) {
2083 | System.out
2084 | .println("Compiler encountered an error writing to file \""
2085 | + fPath + "\"");
2086 | e.printStackTrace();
2087 | encounteredError = true;
2088 | } finally {
2089 | /* if there's an error try to close the file if we can */
2090 | try {
2091 | if (bufferedWriter != null)
2092 | bufferedWriter.close();
2093 | } catch (Exception ex) {
2094 |
2095 | }
2096 | if (encounteredError)
2097 | System.exit(1);
2098 | }
2099 | return false;
2100 | }
2101 |
2102 | /**
2103 | * Remove a directory and its contents.
2104 | *
2105 | * @param directory
2106 | * File object representing directory to remove
2107 | * @return true on success, false on failure
2108 | */
2109 | private static boolean deleteDirectory(File directory) {
2110 | if (directory == null)
2111 | return false;
2112 | if (!directory.exists())
2113 | return true;
2114 | if (!directory.isDirectory())
2115 | return false;
2116 |
2117 | String[] list = directory.list();
2118 |
2119 | // Some JVMs return null for File.list() when the
2120 | // directory is empty.
2121 | if (list != null) {
2122 | for (int i = 0; i < list.length; i++) {
2123 | File entry = new File(directory, list[i]);
2124 | if (entry.isDirectory()) {
2125 | if (!deleteDirectory(entry))
2126 | return false;
2127 | } else {
2128 | if (!entry.delete())
2129 | return false;
2130 | }
2131 | }
2132 | }
2133 | return directory.delete();
2134 | }
2135 |
2136 | /**
2137 | * Check to see if a user's import statement is redundant
2138 | *
2139 | * @param userImport
2140 | * the user's import statement
2141 | * @param generatedImports
2142 | * the generated list of imports
2143 | * @return true if the userImport is a line inside of generatedImports
2144 | */
2145 | private static boolean alreadyImported(String userImport,
2146 | String generatedImports) {
2147 | for (String line : generatedImports.split("\n")) {
2148 | if (line.equals(userImport))
2149 | return true;
2150 | }
2151 | return false;
2152 | }
2153 |
2154 | /**
2155 | * Indent each line of a string with one tab
2156 | *
2157 | * @param x
2158 | * the string to indent
2159 | * @return indented string
2160 | */
2161 | private static String indent(String x) {
2162 | return indent(x, 1);
2163 | }
2164 |
2165 | /**
2166 | * Indent each line of a string with n tabs
2167 | *
2168 | * @param x
2169 | * String to indent
2170 | * @param n
2171 | * The number of tabs to indent by
2172 | * @return indented string
2173 | */
2174 | private static String indent(String x, int n) {
2175 | String indentedString = "";
2176 | String indent = "";
2177 | for (int i = 0; i < n; i++)
2178 | indent = indent + "\t";
2179 | for (String line : x.split("\n"))
2180 | indentedString = indentedString + indent + line + "\n";
2181 | return indentedString;
2182 | }
2183 |
2184 | /**
2185 | * Print a message to the terminal if verbose is set to true
2186 | *
2187 | * @param message
2188 | * string to print
2189 | * @param newLines
2190 | * amount of newline characters to print at end of string
2191 | */
2192 | private static void verbose(String message, int newLines) {
2193 | if (verbose) {
2194 | System.out.print(message);
2195 | for (int i = 0; i < newLines; i++)
2196 | System.out.print("\n");
2197 | }
2198 | }
2199 |
2200 | /**
2201 | * Print a message to the terminal if verbose is set to true
2202 | *
2203 | * @param message
2204 | * string to print
2205 | */
2206 | private static void verbose(String message) {
2207 | verbose(message, 1);
2208 | }
2209 |
2210 | }
2211 |
--------------------------------------------------------------------------------
/src/test/java/com/automation/javauto/test/JavautoTest.java:
--------------------------------------------------------------------------------
1 | package com.automation.javauto.test;
2 |
3 | import static org.assertj.core.api.StrictAssertions.assertThat;
4 | import static org.assertj.core.api.StrictAssertions.fail;
5 | import static org.assertj.core.api.Assertions.*;
6 |
7 | import java.awt.MouseInfo;
8 | import java.io.File;
9 | import java.io.FileNotFoundException;
10 | import java.io.PrintWriter;
11 | import java.io.UnsupportedEncodingException;
12 | import java.util.Arrays;
13 | import java.util.List;
14 | import java.util.concurrent.TimeUnit;
15 |
16 | import org.junit.Test;
17 |
18 | import com.automation.javauto.Javauto;
19 |
20 | /**
21 | * Some test for the {@link Javauto} class.
22 | *
23 | * @author henry.tejera
24 | *
25 | */
26 | public class JavautoTest {
27 |
28 | public final String SEP = File.separator;
29 | public final String TEST_RESOURCES_PATH = "src" + SEP + "test" + SEP
30 | + "resources" + SEP;
31 | public final String TEST_FILE = "fermat.txt";
32 |
33 | @Test
34 | public void testGetAndSetSpeed() {
35 | Javauto javauto = new Javauto();
36 | double defaultSpeed = 0.95D;
37 | double newSpeed = 0.5D;
38 | double maxLimitSpeed = 1.0D;
39 | double minLimitSpeed = 0.0D;
40 | double upLimitSpeed = 1.1D;
41 | double underLimitSpeed = -1.0D;
42 |
43 | assertThat(javauto.getSpeed()).isEqualTo(defaultSpeed);
44 |
45 | javauto.setSpeed(newSpeed);
46 | assertThat(javauto.getSpeed()).isEqualTo(newSpeed);
47 |
48 | javauto.setSpeed(maxLimitSpeed);
49 | assertThat(javauto.getSpeed()).isEqualTo(maxLimitSpeed);
50 |
51 | javauto.setSpeed(minLimitSpeed);
52 | assertThat(javauto.getSpeed()).isEqualTo(minLimitSpeed);
53 |
54 | javauto.setSpeed(upLimitSpeed);
55 | assertThat(javauto.getSpeed()).isEqualTo(maxLimitSpeed);
56 |
57 | javauto.setSpeed(underLimitSpeed);
58 | assertThat(javauto.getSpeed()).isEqualTo(minLimitSpeed);
59 | }
60 |
61 | @Test()
62 | public void testKeyDownShouldBeReturnRuntimeExceptionWithBadKey() {
63 | Javauto javauto = new Javauto();
64 | String badKey = "{INVALIDENTER}";
65 |
66 | try {
67 | javauto.keyDown(badKey);
68 | fail("RuntimeException expected because the Key is invalid.");
69 | } catch (RuntimeException e) {
70 | assertThat(e).hasMessage("Cannot type " + badKey);
71 | }
72 | }
73 |
74 | @Test()
75 | public void testKeyDownShouldBeReturnRuntimeExceptionWithInvalidKeyCode() {
76 | Javauto javauto = new Javauto();
77 | int badKeyCode = 0;
78 |
79 | try {
80 | javauto.keyDown(badKeyCode);
81 | fail("RuntimeException expected because the keycode is not a valid key.");
82 | } catch (RuntimeException e) {
83 | assertThat(e);
84 | }
85 | }
86 |
87 | @Test()
88 | public void testKeyUpShouldBeReturnRuntimeExceptionWithBadKey() {
89 | Javauto javauto = new Javauto();
90 | String badKey = "{INVALIDENTER}";
91 |
92 | try {
93 | javauto.keyUp(badKey);
94 | fail("RuntimeException expected because the Key is invalid.");
95 | } catch (RuntimeException e) {
96 | assertThat(e);
97 | }
98 | }
99 |
100 | @Test()
101 | public void testKeyUpShouldBeReturnRuntimeExceptionWithInvalidKeyCode() {
102 | Javauto javauto = new Javauto();
103 | int badKey = 0;
104 |
105 | try {
106 | javauto.keyUp(badKey);
107 | fail("RuntimeException expected because the keycode is not a valid key.");
108 | } catch (RuntimeException e) {
109 | assertThat(e);
110 | }
111 | }
112 |
113 | @Test()
114 | public void testKeyPressShouldBeReturnRuntimeExceptionWithInvalidKeyCode() {
115 | Javauto javauto = new Javauto();
116 | int badKey = 0;
117 |
118 | try {
119 | javauto.keyPress(badKey);
120 | fail("RuntimeException expected because the keycode is not a valid key.");
121 | } catch (RuntimeException e) {
122 | assertThat(e);
123 | }
124 | }
125 |
126 | @Test
127 | public void testSleephouldBeReturnRuntimeExceptionWithInvalidTimeout() {
128 | Javauto javauto = new Javauto();
129 | int timeout = 600001;
130 |
131 | try {
132 | javauto.sleep(timeout);
133 | fail("RuntimeException expected because the timeout is not a valid timeout.");
134 | } catch (RuntimeException e) {
135 | assertThat(e);
136 | }
137 | }
138 |
139 | @Test
140 | // Do not move your mouse :).
141 | public void testMouseMove() throws InterruptedException {
142 | Javauto javauto = new Javauto();
143 |
144 | // if x is larger than y.
145 | int x1 = 40;
146 | int y1 = 10;
147 | javauto.mouseMove(x1, y1);
148 | TimeUnit.SECONDS.sleep(1);
149 |
150 | int actualX = MouseInfo.getPointerInfo().getLocation().x;
151 | int actualY = MouseInfo.getPointerInfo().getLocation().y;
152 |
153 | assertThat(x1).isEqualTo(actualX);
154 | assertThat(y1).isEqualTo(actualY);
155 |
156 | // if y is larger than x.
157 | int x2 = 10;
158 | int y2 = 40;
159 | javauto.mouseMove(x2, y2);
160 | TimeUnit.SECONDS.sleep(1);
161 |
162 | actualX = MouseInfo.getPointerInfo().getLocation().x;
163 | actualY = MouseInfo.getPointerInfo().getLocation().y;
164 |
165 | assertThat(x2).isEqualTo(actualX);
166 | assertThat(y2).isEqualTo(actualY);
167 |
168 | // equals.
169 | int x3 = 40;
170 | int y3 = 40;
171 | javauto.mouseMove(x3, y3);
172 | TimeUnit.SECONDS.sleep(1);
173 |
174 | actualX = MouseInfo.getPointerInfo().getLocation().x;
175 | actualY = MouseInfo.getPointerInfo().getLocation().y;
176 |
177 | assertThat(x3).isEqualTo(actualX);
178 | assertThat(y3).isEqualTo(actualY);
179 | }
180 |
181 | @Test
182 | public void testMouseClickStringIntInt() throws InterruptedException {
183 | Javauto javauto = new Javauto();
184 | int locationX = (javauto.SCREEN_HEIGHT / 2) - (600 / 2);
185 | int locationY = (javauto.SCREEN_WIDTH / 2) - (800 / 2);
186 |
187 | TestPanel panel = new TestPanel(800, 600, locationX, locationY);
188 | javauto.setSpeed(0.5D);
189 |
190 | // Left
191 | int x = locationX + 120;
192 | int y = locationY + 120;
193 | javauto.mouseClick("left", x, y);
194 | TimeUnit.SECONDS.sleep(2);
195 |
196 | int actualX = MouseInfo.getPointerInfo().getLocation().x;
197 | int actualY = MouseInfo.getPointerInfo().getLocation().y;
198 |
199 | assertThat(panel.getClickedButton()).isEqualToIgnoringCase("left");
200 | assertThat(x).isEqualTo(actualX);
201 | assertThat(y).isEqualTo(actualY);
202 |
203 | // middle
204 | x = locationX + 130;
205 | y = locationY + 130;
206 | javauto.mouseMove(x, y);
207 | javauto.mouseClick("middle");
208 | TimeUnit.SECONDS.sleep(2);
209 |
210 | actualX = MouseInfo.getPointerInfo().getLocation().x;
211 | actualY = MouseInfo.getPointerInfo().getLocation().y;
212 |
213 | assertThat(panel.getClickedButton()).isEqualToIgnoringCase("middle");
214 | assertThat(x).isEqualTo(actualX);
215 | assertThat(y).isEqualTo(actualY);
216 |
217 | // right
218 | x = locationX + 140;
219 | y = locationY + 140;
220 | javauto.mouseMove(x, y);
221 | javauto.mouseClick("right");
222 | TimeUnit.SECONDS.sleep(2);
223 |
224 | actualX = MouseInfo.getPointerInfo().getLocation().x;
225 | actualY = MouseInfo.getPointerInfo().getLocation().y;
226 |
227 | assertThat(panel.getClickedButton()).isEqualToIgnoringCase("right");
228 | assertThat(x).isEqualTo(actualX);
229 | assertThat(y).isEqualTo(actualY);
230 |
231 | // Invalid
232 | x = locationX + 150;
233 | y = locationY + 150;
234 | javauto.mouseMove(x, y);
235 | javauto.mouseClick("INVALID");
236 | TimeUnit.SECONDS.sleep(2);
237 |
238 | actualX = MouseInfo.getPointerInfo().getLocation().x;
239 | actualY = MouseInfo.getPointerInfo().getLocation().y;
240 |
241 | assertThat(panel.getClickedButton()).isEqualToIgnoringCase("right");
242 | assertThat(x).isEqualTo(actualX);
243 | assertThat(y).isEqualTo(actualY);
244 | }
245 |
246 | @Test
247 | public void testMouseClickString() throws InterruptedException {
248 | Javauto javauto = new Javauto();
249 | int locationX = (javauto.SCREEN_HEIGHT / 2) - (600 / 2);
250 | int locationY = (javauto.SCREEN_WIDTH / 2) - (800 / 2);
251 |
252 | TestPanel panel = new TestPanel(800, 600, locationX, locationY);
253 | javauto.setSpeed(0.5D);
254 |
255 | // Left
256 | javauto.mouseMove(locationX + 120, locationY + 120);
257 | javauto.mouseClick("left");
258 | TimeUnit.SECONDS.sleep(2);
259 | assertThat(panel.getClickedButton()).isEqualToIgnoringCase("left");
260 |
261 | // middle
262 | javauto.mouseMove(locationX + 120, locationY + 120);
263 | javauto.mouseClick("middle");
264 | TimeUnit.SECONDS.sleep(2);
265 | assertThat(panel.getClickedButton()).isEqualToIgnoringCase("middle");
266 |
267 | // right
268 | javauto.mouseMove(locationX + 120, locationY + 120);
269 | javauto.mouseClick("right");
270 | TimeUnit.SECONDS.sleep(2);
271 | assertThat(panel.getClickedButton()).isEqualToIgnoringCase("right");
272 |
273 | // Nothing
274 | javauto.mouseMove(locationX + 120, locationY + 120);
275 | javauto.mouseClick("INVALID");
276 | TimeUnit.SECONDS.sleep(2);
277 | assertThat(panel.getClickedButton()).isEqualToIgnoringCase("right");
278 | }
279 |
280 | @Test
281 | public void testToDoubleString() {
282 | Javauto javauto = new Javauto();
283 | assertThat(javauto.toDouble("0.0")).isEqualTo(0.0D);
284 | }
285 |
286 | @Test
287 | public void testToDoubleChar() {
288 | Javauto javauto = new Javauto();
289 | char c = "0".charAt(0);
290 | assertThat(javauto.toDouble(c)).isEqualTo(0.0D);
291 | }
292 |
293 | @Test
294 | public void testToDoubleBoolean() {
295 | Javauto javauto = new Javauto();
296 | assertThat(javauto.toDouble(false)).isEqualTo(0.0D);
297 | }
298 |
299 | @Test
300 | public void testToDoubleInt() {
301 | Javauto javauto = new Javauto();
302 | assertThat(javauto.toDouble(1)).isEqualTo(1.0D);
303 | }
304 |
305 | @Test
306 | public void testToDoubleLong() {
307 | Javauto javauto = new Javauto();
308 | assertThat(javauto.toDouble(new Long(198546L))).isEqualTo(198546.0D);
309 | }
310 |
311 | @Test
312 | public void testToDoubleShort() {
313 | Javauto javauto = new Javauto();
314 | assertThat(javauto.toDouble(new Short("10"))).isEqualTo(10.0D);
315 | }
316 |
317 | @Test
318 | public void testToDoubleFloat() {
319 | Javauto javauto = new Javauto();
320 | float f = 1F;
321 | assertThat(javauto.toDouble(f)).isEqualTo(1.0D);
322 | }
323 |
324 | @Test
325 | public void testToDoubleByte() {
326 | Javauto javauto = new Javauto();
327 | byte b = 10;
328 | assertThat(javauto.toDouble(b)).isEqualTo(10.0D);
329 | }
330 |
331 | @Test
332 | public void testToFloatString() {
333 | Javauto javauto = new Javauto();
334 | assertThat(javauto.toFloat("10")).isEqualTo(10.0F);
335 | }
336 |
337 | @Test
338 | public void testToFloatChar() {
339 | Javauto javauto = new Javauto();
340 | char c = "0".charAt(0);
341 | assertThat(javauto.toFloat(c)).isEqualTo(0.0F);
342 | }
343 |
344 | @Test
345 | public void testToFloatBoolean() {
346 | Javauto javauto = new Javauto();
347 | assertThat(javauto.toFloat(true)).isEqualTo(1.0F);
348 | }
349 |
350 | @Test
351 | public void testToFloatInt() {
352 | Javauto javauto = new Javauto();
353 | assertThat(javauto.toFloat(1)).isEqualTo(1.0F);
354 | }
355 |
356 | @Test
357 | public void testToFloatLong() {
358 | Javauto javauto = new Javauto();
359 | assertThat(javauto.toFloat(new Long(198546L))).isEqualTo(198546.0F);
360 | }
361 |
362 | @Test
363 | public void testToFloatShort() {
364 | Javauto javauto = new Javauto();
365 | assertThat(javauto.toFloat(new Short("10"))).isEqualTo(10.0F);
366 | }
367 |
368 | @Test
369 | public void testToFloatDouble() {
370 | Javauto javauto = new Javauto();
371 | assertThat(javauto.toFloat(new Double(10D))).isEqualTo(10.0F);
372 | }
373 |
374 | @Test
375 | public void testToFloatByte() {
376 | Javauto javauto = new Javauto();
377 | byte b = 10;
378 | assertThat(javauto.toFloat(b)).isEqualTo(10.0F);
379 | }
380 |
381 | @Test
382 | public void testToIntString() {
383 | Javauto javauto = new Javauto();
384 | assertThat(javauto.toInt("1831")).isEqualTo(1831);
385 | }
386 |
387 | @Test
388 | public void testToIntChar() {
389 | Javauto javauto = new Javauto();
390 | char c = "1".charAt(0);
391 | assertThat(javauto.toInt(c)).isEqualTo(1);
392 | }
393 |
394 | @Test
395 | public void testToIntBoolean() {
396 | Javauto javauto = new Javauto();
397 | assertThat(javauto.toInt(true)).isEqualTo(1);
398 | }
399 |
400 | @Test
401 | public void testToIntLong() {
402 | Javauto javauto = new Javauto();
403 | assertThat(javauto.toInt(new Long(198546L))).isEqualTo(198546);
404 | }
405 |
406 | @Test
407 | public void testToIntShort() {
408 | Javauto javauto = new Javauto();
409 | assertThat(javauto.toInt(new Short("10"))).isEqualTo(10);
410 | }
411 |
412 | @Test
413 | public void testToIntFloat() {
414 | Javauto javauto = new Javauto();
415 | float f = 1F;
416 | assertThat(javauto.toInt(f)).isEqualTo(1);
417 | }
418 |
419 | @Test
420 | public void testToIntDouble() {
421 | Javauto javauto = new Javauto();
422 | assertThat(javauto.toInt(1.0D)).isEqualTo(1);
423 | }
424 |
425 | @Test
426 | public void testToIntByte() {
427 | Javauto javauto = new Javauto();
428 | byte b = 10;
429 | assertThat(javauto.toInt(b)).isEqualTo(10);
430 | }
431 |
432 | @Test
433 | public void testToCharString() {
434 | Javauto javauto = new Javauto();
435 | assertThat(javauto.toChar("Fermat")).isEqualTo('F');
436 | }
437 |
438 | @Test
439 | public void testToStringChar() {
440 | Javauto javauto = new Javauto();
441 | char c = "1".charAt(0);
442 | assertThat(javauto.toString(c)).isEqualTo("1");
443 | }
444 |
445 | @Test
446 | public void testToStringBoolean() {
447 | Javauto javauto = new Javauto();
448 | assertThat(javauto.toString(true)).isEqualTo("true");
449 | }
450 |
451 | @Test
452 | public void testToStringInt() {
453 | Javauto javauto = new Javauto();
454 | assertThat(javauto.toString(1)).isEqualTo("1");
455 | }
456 |
457 | @Test
458 | public void testToStringLong() {
459 | Javauto javauto = new Javauto();
460 | assertThat(javauto.toString(new Long(198546L))).isEqualTo("198546");
461 | }
462 |
463 | @Test
464 | public void testToStringShort() {
465 | Javauto javauto = new Javauto();
466 | assertThat(javauto.toString(new Short("10"))).isEqualTo("10");
467 | }
468 |
469 | @Test
470 | public void testToStringFloat() {
471 | Javauto javauto = new Javauto();
472 | float f = 1F;
473 | assertThat(javauto.toString(f)).isEqualTo("1.0");
474 | }
475 |
476 | @Test
477 | public void testToStringDouble() {
478 | Javauto javauto = new Javauto();
479 | assertThat(javauto.toString(1.0D)).isEqualTo("1.0");
480 | }
481 |
482 | @Test
483 | public void testToStringByte() {
484 | Javauto javauto = new Javauto();
485 | byte b = 10;
486 | assertThat(javauto.toString(b)).isEqualTo("10");
487 | }
488 |
489 | @Test
490 | public void testFileExists() {
491 | Javauto javauto = new Javauto();
492 | String file = TEST_RESOURCES_PATH + TEST_FILE;
493 | assertThat(javauto.fileExists(file)).isEqualTo(true);
494 | }
495 |
496 | @Test
497 | public void testIsFile() {
498 | Javauto javauto = new Javauto();
499 | String file = TEST_RESOURCES_PATH + TEST_FILE;
500 | assertThat(javauto.isFile(file)).isEqualTo(true);
501 | }
502 |
503 | @Test
504 | public void testFileDelete() throws FileNotFoundException,
505 | UnsupportedEncodingException {
506 | Javauto javauto = new Javauto();
507 |
508 | String file = TEST_RESOURCES_PATH + "lagrange";
509 | PrintWriter writer = new PrintWriter(file, "UTF-8");
510 | writer.println("The first line");
511 | writer.println("The second line");
512 | writer.close();
513 |
514 | javauto.fileDelete(file);
515 | assertThat(new File(file)).doesNotExist();
516 |
517 | }
518 |
519 | @Test
520 | public void testRmDir() {
521 | Javauto javauto = new Javauto();
522 | String dir = TEST_RESOURCES_PATH + "DIR";
523 | new File(dir).mkdirs();
524 |
525 | javauto.rmDir(dir);
526 | assertThat(new File(dir)).doesNotExist();
527 | }
528 |
529 | @Test
530 | public void testMkDir() {
531 | Javauto javauto = new Javauto();
532 | String dir = TEST_RESOURCES_PATH + "NEW";
533 | javauto.mkDir(dir);
534 |
535 | File theDir = new File(dir);
536 | assertThat(theDir).exists().isDirectory();
537 | theDir.delete();
538 | }
539 |
540 | @Test
541 | public void testFileCreate() {
542 | Javauto javauto = new Javauto();
543 | String filePath = TEST_RESOURCES_PATH + "evariste.txt";
544 | javauto.fileCreate(filePath);
545 |
546 | File file = new File(filePath);
547 | assertThat(file).exists().isFile();
548 | file.delete();
549 | }
550 |
551 | @Test
552 | public void testFileGetPath() {
553 | Javauto javauto = new Javauto();
554 | String filePath = TEST_RESOURCES_PATH + TEST_FILE;
555 | File file = new File(filePath);
556 | assertThat(javauto.fileGetPath(filePath)).isEqualToIgnoringCase(
557 | file.getAbsolutePath());
558 | }
559 |
560 | @Test
561 | public void testFileGetName() {
562 | Javauto javauto = new Javauto();
563 | String filePath = TEST_RESOURCES_PATH + TEST_FILE;
564 | File file = new File(filePath);
565 | assertThat(javauto.fileGetName(filePath)).isEqualToIgnoringCase(
566 | file.getName());
567 | }
568 |
569 | @Test
570 | public void testIsDirectory() {
571 | Javauto javauto = new Javauto();
572 | assertThat(javauto.isDirectory(TEST_RESOURCES_PATH)).isEqualTo(true);
573 | assertThat(javauto.isDirectory(TEST_RESOURCES_PATH + TEST_FILE))
574 | .isEqualTo(false);
575 | assertThat(javauto.isDirectory("NO")).isEqualTo(false);
576 | }
577 |
578 | @Test
579 | public void testFileRead() {
580 | Javauto javauto = new Javauto();
581 | String path = TEST_RESOURCES_PATH + TEST_FILE;
582 | assertThat(javauto.fileRead(path)).isEqualToIgnoringCase(
583 | "France Toulouse");
584 | }
585 |
586 | @Test
587 | public void testFileWrite() {
588 | Javauto javauto = new Javauto();
589 | String path = TEST_RESOURCES_PATH + "poincare.txt";
590 | String content = "France";
591 |
592 | javauto.fileWrite(path, content);
593 | File file = new File(path);
594 | assertThat(contentOf(file)).contains(content);
595 | file.delete();
596 | }
597 |
598 | @Test
599 | public void testFileAppend() throws FileNotFoundException,
600 | UnsupportedEncodingException {
601 | Javauto javauto = new Javauto();
602 |
603 | String filePath = TEST_RESOURCES_PATH + "massera.txt";
604 | String content = "2";
605 | PrintWriter writer = new PrintWriter(filePath, "UTF-8");
606 | writer.println("1");
607 | writer.close();
608 |
609 | javauto.fileAppend(filePath, content);
610 | File file = new File(filePath);
611 | assertThat(contentOf(file)).contains(content);
612 | file.delete();
613 | }
614 |
615 | @Test
616 | public void testFileList() {
617 | Javauto javauto = new Javauto();
618 | String[] files = javauto.fileList(TEST_RESOURCES_PATH);
619 | assertThat(files.length).isGreaterThan(0);
620 | }
621 |
622 | @Test
623 | public void testClipboardPutAndGet() {
624 | Javauto javauto = new Javauto();
625 | String content = "buttner";
626 | javauto.clipboardPut(content);
627 | assertThat(javauto.clipboardGet()).isEqualTo(content);
628 | }
629 |
630 | @Test
631 | public void testHttpGet() {
632 | Javauto javauto = new Javauto();
633 | String urlHttp = "https://en.wikipedia.org/wiki/Rudolf_Carnap";
634 | String urlHttps = "https://en.wikipedia.org/wiki/Alonzo_Church";
635 |
636 | assertThat(javauto.httpGet(urlHttp)).contains("Logical positivism");
637 | assertThat(javauto.httpGet(urlHttps)).contains("lambda");
638 | }
639 |
640 | @Test
641 | public void testHttpGetShouldBeReturnEmpty() {
642 | Javauto javauto = new Javauto();
643 | String url = "http://noerterfasdpeor.com";
644 | assertThat(javauto.httpGet(url)).isEmpty();
645 | }
646 |
647 | @Test
648 | public void testGetPage() {
649 | Javauto javauto = new Javauto();
650 | String urlHttp = "https://en.wikipedia.org/wiki/Gary_R._Mar";
651 | String urlHttps = "https://en.wikipedia.org/wiki/Raymond_Smullyan";
652 |
653 | assertThat(javauto.getPage(urlHttp)).contains(
654 | "Philosophy of Mathematics");
655 | assertThat(javauto.getPage(urlHttps))
656 | .contains("American mathematician");
657 | }
658 |
659 | @Test
660 | public void testGetPageShouldBeReturnError() {
661 | Javauto javauto = new Javauto();
662 | String urlHttp = "https://seguad/logical/positivism";
663 | assertThat(javauto.getPage(urlHttp)).contains("Error");
664 | }
665 |
666 | @Test
667 | public void testHttpPost() {
668 | Javauto javauto = new Javauto();
669 | String url = "https://posttestserver.com/post.php";
670 | String[][] parameters = new String[][] { { "a", "1" }, { "b", "2" },
671 | { "c", "3" } };
672 |
673 | assertThat(javauto.httpPost(url, parameters)).contains(
674 | "Successfully dumped 3 post variables.");
675 | }
676 |
677 | @Test
678 | public void testJoin() {
679 | Javauto javauto = new Javauto();
680 | String[] strArray = { "Jack Copeland", "Sebastian Guadagna" };
681 | String delimiter = "|";
682 |
683 | assertThat(javauto.join(delimiter, strArray)).isEqualToIgnoringCase(
684 | "Jack Copeland|Sebastian Guadagna");
685 | }
686 |
687 | @Test
688 | public void testArrayAsList() {
689 | Javauto javauto = new Javauto();
690 | String[] strArray = { "Jack Copeland", "Sebastian Gudagn" };
691 | List expected = Arrays.asList(strArray);
692 | List theList = javauto.arrayAsList(strArray);
693 |
694 | assertThat(theList).isEqualToComparingFieldByField(expected);
695 | }
696 |
697 | @Test
698 | public void testArrayBinarySearchByte() {
699 | Javauto javauto = new Javauto();
700 | byte searchVal = 35;
701 | byte arr[] = { 10, 12, 34, searchVal, 5 };
702 | int index = javauto.arrayBinarySearch(arr, searchVal);
703 |
704 | assertThat(index).isEqualTo(4);
705 | }
706 |
707 | @Test
708 | public void testArrayBinarySearchChar() {
709 | Javauto javauto = new Javauto();
710 | char searchVal = 'c';
711 | char arr[] = { 'a', 'c', 'b', 'e', 'd' };
712 | int index = javauto.arrayBinarySearch(arr, searchVal);
713 |
714 | assertThat(index).isEqualTo(2);
715 | }
716 |
717 | @Test
718 | public void testArrayBinarySearchDouble() {
719 | Javauto javauto = new Javauto();
720 | double searchVal = 4.6;
721 | double arr[] = { 5.4, 49.2, 9.2, 35.4, 4.6 };
722 | int index = javauto.arrayBinarySearch(arr, searchVal);
723 |
724 | assertThat(index).isEqualTo(0);
725 | }
726 |
727 | @Test
728 | public void testArrayBinarySearchFloat() {
729 | Javauto javauto = new Javauto();
730 | float searchVal = 42.9f;
731 | float arr[] = { 5.2f, 46.1f, 42.9f, 22.3f };
732 | int index = javauto.arrayBinarySearch(arr, searchVal);
733 |
734 | assertThat(index).isEqualTo(2);
735 | }
736 |
737 | @Test
738 | public void testArrayBinarySearchInt() {
739 | Javauto javauto = new Javauto();
740 | int searchVal = 5;
741 | int arr[] = { 30, 20, 5, 12, 55 };
742 | int index = javauto.arrayBinarySearch(arr, searchVal);
743 |
744 | assertThat(index).isEqualTo(0);
745 | }
746 |
747 | @Test
748 | public void testArrayBinarySearchLong() {
749 | Javauto javauto = new Javauto();
750 | long searchVal = 46464;
751 | long arr[] = { 56, 46464, 3342, 232, 3445 };
752 | int index = javauto.arrayBinarySearch(arr, searchVal);
753 |
754 | assertThat(index).isEqualTo(4);
755 | }
756 |
757 | @Test
758 | public void testArrayBinarySearchShort() {
759 | Javauto javauto = new Javauto();
760 | short searchVal = 52;
761 | short arr[] = { 5, 2, 15, 52, 10 };
762 | int index = javauto.arrayBinarySearch(arr, searchVal);
763 |
764 | assertThat(index).isEqualTo(4);
765 | }
766 |
767 | @Test
768 | public void testArrayCopyOfBoolean() {
769 | Javauto javauto = new Javauto();
770 | boolean[] a1 = new boolean[] { true, false };
771 | boolean[] a2 = javauto.arrayCopyOf(a1, 4);
772 |
773 | assertThat(a2).hasSize(4).contains(true, atIndex(0))
774 | .contains(false, atIndex(1)).contains(false, atIndex(2))
775 | .contains(false, atIndex(3));
776 | }
777 |
778 | @Test
779 | public void testArrayCopyOfBooleanShouldBeReturnRuntimeExceptionWithNegativeLength() {
780 | Javauto javauto = new Javauto();
781 | boolean[] a1 = new boolean[] { true, false };
782 |
783 | try {
784 | javauto.arrayCopyOf(a1, -1);
785 | fail("RuntimeException expected because the new length is negative.");
786 | } catch (RuntimeException e) {
787 | assertThat(e);
788 | }
789 | }
790 |
791 | @Test
792 | public void testArrayCopyOfBytes() {
793 | Javauto javauto = new Javauto();
794 | byte[] a1 = new byte[] { 5, 62, 15 };
795 | byte[] a2 = javauto.arrayCopyOf(a1, 4);
796 |
797 | assertThat(a2).hasSize(4).contains((byte) 5, atIndex(0))
798 | .contains((byte) 62, atIndex(1))
799 | .contains((byte) 15, atIndex(2)).contains((byte) 0, atIndex(3));
800 | }
801 |
802 | @Test
803 | public void testArrayCopyOfBytesShouldBeReturnRuntimeExceptionWithNegativeLength() {
804 | Javauto javauto = new Javauto();
805 | byte[] a1 = new byte[] { 5, 62, 15 };
806 |
807 | try {
808 | javauto.arrayCopyOf(a1, -1);
809 | fail("RuntimeException expected because the new length is nagative.");
810 | } catch (RuntimeException e) {
811 | assertThat(e);
812 | }
813 | }
814 |
815 | @Test
816 | public void testArrayCopyOfChar() {
817 | Javauto javauto = new Javauto();
818 | char[] a1 = new char[] { 'p', 's', 'r' };
819 | char[] a2 = javauto.arrayCopyOf(a1, 4);
820 |
821 | assertThat(a2).hasSize(4).contains('p', atIndex(0))
822 | .contains('s', atIndex(1)).contains('r', atIndex(2));
823 | }
824 |
825 | @Test
826 | public void testArrayCopyOfCharShouldBeReturnRuntimeExceptionWithNegativeLength() {
827 | Javauto javauto = new Javauto();
828 | char[] a1 = new char[] { 'p', 's', 'r' };
829 |
830 | try {
831 | javauto.arrayCopyOf(a1, -1);
832 | fail("RuntimeException expected because the new length is negative.");
833 | } catch (RuntimeException e) {
834 | assertThat(e);
835 | }
836 | }
837 |
838 | @Test
839 | public void testArrayCopyOfDouble() {
840 | Javauto javauto = new Javauto();
841 | double[] a1 = new double[] { 12.5, 3.2, 37.5 };
842 | double[] a2 = javauto.arrayCopyOf(a1, 4);
843 |
844 | assertThat(a2).hasSize(4).contains(12.5, atIndex(0))
845 | .contains(3.2, atIndex(1)).contains(37.5, atIndex(2))
846 | .contains(0, atIndex(3));
847 | }
848 |
849 | @Test
850 | public void testArrayCopyOfDoubleShouldBeReturnRuntimeExceptionWithNegativeLength() {
851 | Javauto javauto = new Javauto();
852 | double[] a1 = new double[] { 12.5, 3.2, 37.5 };
853 |
854 | try {
855 | javauto.arrayCopyOf(a1, -1);
856 | fail("RuntimeException expected because the new length is negative.");
857 | } catch (RuntimeException e) {
858 | assertThat(e);
859 | }
860 | }
861 |
862 | @Test
863 | public void testArrayCopyOfFloat() {
864 | Javauto javauto = new Javauto();
865 | float[] a1 = new float[] { 10f, 32f, 25f };
866 | float[] a2 = javauto.arrayCopyOf(a1, 4);
867 |
868 | assertThat(a2).hasSize(4).contains(10f, atIndex(0))
869 | .contains(32f, atIndex(1)).contains(25f, atIndex(2))
870 | .contains(0f, atIndex(3));
871 | }
872 |
873 | @Test
874 | public void testArrayCopyOfFloatShouldBeReturnRuntimeExceptionWithNegativeLength() {
875 | Javauto javauto = new Javauto();
876 | float[] a1 = new float[] { 10f, 32f, 25f };
877 |
878 | try {
879 | javauto.arrayCopyOf(a1, -1);
880 | fail("RuntimeException expected because the new length is negative.");
881 | } catch (RuntimeException e) {
882 | assertThat(e);
883 | }
884 | }
885 |
886 | @Test
887 | public void testArrayCopyOfInt() {
888 | Javauto javauto = new Javauto();
889 | int[] a1 = new int[] { 45, 32, 75 };
890 | int[] a2 = javauto.arrayCopyOf(a1, 4);
891 |
892 | assertThat(a2).hasSize(4).contains(45, atIndex(0))
893 | .contains(32, atIndex(1)).contains(75, atIndex(2))
894 | .contains(0, atIndex(3));
895 | }
896 |
897 | @Test
898 | public void testArrayCopyOfIntShouldBeReturnRuntimeExceptionWithNegativeLength() {
899 | Javauto javauto = new Javauto();
900 | int[] a1 = new int[] { 45, 32, 75 };
901 |
902 | try {
903 | javauto.arrayCopyOf(a1, -1);
904 | fail("RuntimeException expected because the new length is negative.");
905 | } catch (RuntimeException e) {
906 | assertThat(e);
907 | }
908 | }
909 |
910 | @Test
911 | public void testArrayCopyOfLong() {
912 | Javauto javauto = new Javauto();
913 | long[] a1 = new long[] { 15, 10, 45 };
914 | long[] a2 = javauto.arrayCopyOf(a1, 4);
915 |
916 | assertThat(a2).hasSize(4).contains(15, atIndex(0))
917 | .contains(10, atIndex(1)).contains(45, atIndex(2))
918 | .contains(0L, atIndex(3));
919 | }
920 |
921 | @Test
922 | public void testArrayCopyOfLongShouldBeReturnRuntimeExceptionWithNegativeLength() {
923 | Javauto javauto = new Javauto();
924 | long[] a1 = new long[] { 15, 10, 45 };
925 |
926 | try {
927 | javauto.arrayCopyOf(a1, -1);
928 | fail("RuntimeException expected because the new length is negative.");
929 | } catch (RuntimeException e) {
930 | assertThat(e);
931 | }
932 | }
933 |
934 | @Test
935 | public void testArrayCopyOfShort() {
936 | Javauto javauto = new Javauto();
937 | short[] a1 = new short[] { 15, 10, 45 };
938 | short[] a2 = javauto.arrayCopyOf(a1, 4);
939 |
940 | assertThat(a2).hasSize(4).contains((short) 15, atIndex(0))
941 | .contains((short) 10, atIndex(1))
942 | .contains((short) 45, atIndex(2))
943 | .contains((short) 0, atIndex(3));
944 | }
945 |
946 | @Test
947 | public void testArrayCopyOfShortShouldBeReturnRuntimeExceptionWithNegativeLength() {
948 | Javauto javauto = new Javauto();
949 | short[] a1 = new short[] { 15, 10, 45 };
950 |
951 | try {
952 | javauto.arrayCopyOf(a1, -1);
953 | fail("RuntimeException expected because the new length is negative.");
954 | } catch (RuntimeException e) {
955 | assertThat(e);
956 | }
957 | }
958 |
959 | @Test
960 | public void testArraySortByte() {
961 | Javauto javauto = new Javauto();
962 | byte[] a1 = { 10, 2, 7, 35 };
963 | byte[] a2 = javauto.arraySort(a1);
964 |
965 | assertThat(a2).hasSize(4).contains((byte) 2, atIndex(0))
966 | .contains((byte) 7, atIndex(1)).contains((byte) 10, atIndex(2))
967 | .contains((byte) 35, atIndex(3));
968 | }
969 |
970 | @Test
971 | public void testArraySortChar() {
972 | Javauto javauto = new Javauto();
973 | char[] a1 = { 'r', 'q', 's', 'p' };
974 | char[] a2 = javauto.arraySort(a1);
975 |
976 | assertThat(a2).hasSize(4).contains('p', atIndex(0))
977 | .contains('q', atIndex(1)).contains('r', atIndex(2))
978 | .contains('s', atIndex(3));
979 | }
980 |
981 | @Test
982 | public void testArraySortDouble() {
983 | Javauto javauto = new Javauto();
984 | double[] a1 = { 3.2, 1.2, 9.7 };
985 | double[] a2 = javauto.arraySort(a1);
986 |
987 | assertThat(a2).hasSize(3).contains(1.2, atIndex(0))
988 | .contains(3.2, atIndex(1)).contains(9.7, atIndex(2));
989 | }
990 |
991 | @Test
992 | public void testArraySortFloat() {
993 | Javauto javauto = new Javauto();
994 | float[] a1 = { 3.2f, 1.2f, 9.7f };
995 | float[] a2 = javauto.arraySort(a1);
996 |
997 | assertThat(a2).hasSize(3).contains(1.2f, atIndex(0))
998 | .contains(3.2f, atIndex(1)).contains(9.7f, atIndex(2));
999 | }
1000 |
1001 | @Test
1002 | public void testArraySortInt() {
1003 | Javauto javauto = new Javauto();
1004 | int[] a1 = { 2, 1, 9 };
1005 | int[] a2 = javauto.arraySort(a1);
1006 |
1007 | assertThat(a2).hasSize(3).contains(1, atIndex(0))
1008 | .contains(2, atIndex(1)).contains(9, atIndex(2));
1009 | }
1010 |
1011 | @Test
1012 | public void testArraySortLong() {
1013 | Javauto javauto = new Javauto();
1014 | long[] a1 = { 22, 10, 91 };
1015 | long[] a2 = javauto.arraySort(a1);
1016 |
1017 | assertThat(a2).hasSize(3).contains(10, atIndex(0))
1018 | .contains(22, atIndex(1)).contains(91, atIndex(2));
1019 | }
1020 |
1021 | @Test
1022 | public void testArraySortShort() {
1023 | Javauto javauto = new Javauto();
1024 | short[] a1 = { 22, 10, 91 };
1025 | short[] a2 = javauto.arraySort(a1);
1026 |
1027 | assertThat(a2).hasSize(3).contains((short) 10, atIndex(0))
1028 | .contains((short) 22, atIndex(1))
1029 | .contains((short) 91, atIndex(2));
1030 | }
1031 |
1032 | @Test
1033 | public void testArrayToStringBoolean() {
1034 | Javauto javauto = new Javauto();
1035 | boolean[] a1 = new boolean[] { true, false };
1036 |
1037 | assertThat(javauto.arrayToString(a1)).isEqualToIgnoringCase(
1038 | "[true, false]");
1039 | }
1040 |
1041 | @Test
1042 | public void testArrayToStringByte() {
1043 | Javauto javauto = new Javauto();
1044 | byte[] a1 = new byte[] { 5, 62 };
1045 |
1046 | assertThat(javauto.arrayToString(a1)).isEqualToIgnoringCase("[5, 62]");
1047 | }
1048 |
1049 | @Test
1050 | public void testArrayToStringChar() {
1051 | Javauto javauto = new Javauto();
1052 | char[] a1 = new char[] { 'p', 's' };
1053 |
1054 | assertThat(javauto.arrayToString(a1)).isEqualToIgnoringCase("[p, s]");
1055 | }
1056 |
1057 | @Test
1058 | public void testArrayToStringDouble() {
1059 | Javauto javauto = new Javauto();
1060 | double a1[] = { 5.4, 49.2 };
1061 |
1062 | assertThat(javauto.arrayToString(a1)).isEqualToIgnoringCase(
1063 | "[5.4, 49.2]");
1064 | }
1065 |
1066 | @Test
1067 | public void testArrayToStringFloat() {
1068 | Javauto javauto = new Javauto();
1069 | float a1[] = { 5.2f, 46.1f };
1070 |
1071 | assertThat(javauto.arrayToString(a1)).isEqualToIgnoringCase(
1072 | "[5.2, 46.1]");
1073 | }
1074 |
1075 | @Test
1076 | public void testArrayToStringInt() {
1077 | Javauto javauto = new Javauto();
1078 | int a1[] = { 5, 4 };
1079 |
1080 | assertThat(javauto.arrayToString(a1)).isEqualToIgnoringCase("[5, 4]");
1081 | }
1082 |
1083 | @Test
1084 | public void testArrayToStringLong() {
1085 | Javauto javauto = new Javauto();
1086 | long a1[] = { 56, 46464 };
1087 |
1088 | assertThat(javauto.arrayToString(a1)).isEqualToIgnoringCase(
1089 | "[56, 46464]");
1090 | }
1091 |
1092 | @Test
1093 | public void testArrayToStringShort() {
1094 | Javauto javauto = new Javauto();
1095 | short a1[] = { 5, 2 };
1096 |
1097 | assertThat(javauto.arrayToString(a1)).isEqualToIgnoringCase("[5, 2]");
1098 | }
1099 |
1100 | @Test
1101 | public void testArrayToStringString() {
1102 | Javauto javauto = new Javauto();
1103 | String[] a1 = { "Julio", "Rey", "Pastor" };
1104 |
1105 | assertThat(javauto.arrayToString(a1)).isEqualToIgnoringCase(
1106 | "[Julio, Rey, Pastor]");
1107 | }
1108 |
1109 | @Test
1110 | public void testArrayEqualsBoolean() {
1111 | Javauto javauto = new Javauto();
1112 | boolean[] a1 = new boolean[] { true, false };
1113 | boolean[] a2 = new boolean[] { true, false };
1114 | boolean[] a3 = new boolean[] { true, true };
1115 |
1116 | assertThat(javauto.arrayEquals(a1, a2)).isTrue();
1117 | assertThat(javauto.arrayEquals(a1, a3)).isFalse();
1118 | }
1119 |
1120 | @Test
1121 | public void testArrayEqualsByte() {
1122 | Javauto javauto = new Javauto();
1123 | byte[] a1 = new byte[] { 5, 62 };
1124 | byte[] a2 = new byte[] { 5, 62 };
1125 | byte[] a3 = new byte[] { 5 };
1126 |
1127 | assertThat(javauto.arrayEquals(a1, a2)).isTrue();
1128 | assertThat(javauto.arrayEquals(a1, a3)).isFalse();
1129 | }
1130 |
1131 | @Test
1132 | public void testArrayEqualsChar() {
1133 | Javauto javauto = new Javauto();
1134 | char[] a1 = new char[] { 'p', 's' };
1135 | char[] a2 = new char[] { 'p', 's' };
1136 | char[] a3 = new char[] { 'p', 'p' };
1137 |
1138 | assertThat(javauto.arrayEquals(a1, a2)).isTrue();
1139 | assertThat(javauto.arrayEquals(a1, a3)).isFalse();
1140 | }
1141 |
1142 | @Test
1143 | public void testArrayEqualsDouble() {
1144 | Javauto javauto = new Javauto();
1145 | double[] a1 = { 5.4, 49.2 };
1146 | double[] a2 = { 5.4, 49.2 };
1147 | double[] a3 = { 5.4, 2.1 };
1148 |
1149 | assertThat(javauto.arrayEquals(a1, a2)).isTrue();
1150 | assertThat(javauto.arrayEquals(a1, a3)).isFalse();
1151 | }
1152 |
1153 | @Test
1154 | public void testArrayEqualsFloat() {
1155 | Javauto javauto = new Javauto();
1156 | float[] a1 = { 5.2f, 46.1f };
1157 | float[] a2 = { 5.2f, 46.1f };
1158 | float[] a3 = { 5.2f, 6.1f };
1159 |
1160 | assertThat(javauto.arrayEquals(a1, a2)).isTrue();
1161 | assertThat(javauto.arrayEquals(a1, a3)).isFalse();
1162 | }
1163 |
1164 | @Test
1165 | public void testArrayEqualsInt() {
1166 | Javauto javauto = new Javauto();
1167 | int[] a1 = { 1, 2 };
1168 | int[] a2 = { 1, 2 };
1169 | int[] a3 = { 0, 2 };
1170 |
1171 | assertThat(javauto.arrayEquals(a1, a2)).isTrue();
1172 | assertThat(javauto.arrayEquals(a1, a3)).isFalse();
1173 | }
1174 |
1175 | @Test
1176 | public void testArrayEqualsLong() {
1177 | Javauto javauto = new Javauto();
1178 | long[] a1 = { 56, 46464 };
1179 | long[] a2 = { 56, 46464 };
1180 | long[] a3 = { 56, 46 };
1181 |
1182 | assertThat(javauto.arrayEquals(a1, a2)).isTrue();
1183 | assertThat(javauto.arrayEquals(a1, a3)).isFalse();
1184 | }
1185 |
1186 | @Test
1187 | public void testArrayEqualsShort() {
1188 | Javauto javauto = new Javauto();
1189 | short[] a1 = { 5, 2 };
1190 | short[] a2 = { 5, 2 };
1191 | short[] a3 = { 5, 5 };
1192 |
1193 | assertThat(javauto.arrayEquals(a1, a2)).isTrue();
1194 | assertThat(javauto.arrayEquals(a1, a3)).isFalse();
1195 | }
1196 |
1197 | @Test
1198 | public void testArrayEqualsString() {
1199 | Javauto javauto = new Javauto();
1200 | String[] a1 = { "Pierre", "Fermat" };
1201 | String[] a2 = { "Pierre", "Fermat" };
1202 | String[] a3 = { "Evariste", "Galois" };
1203 |
1204 | assertThat(javauto.arrayEquals(a1, a2)).isTrue();
1205 | assertThat(javauto.arrayEquals(a1, a3)).isFalse();
1206 | }
1207 |
1208 | @Test
1209 | public void testGetEnvWithParameter() {
1210 | Javauto javauto = new Javauto();
1211 | assertThat(javauto.getEnv("PATH")).isNotEmpty();
1212 | }
1213 |
1214 | @Test
1215 | public void testGetEnvWithEmptyParameterShouldBeReturnAnEmptyString() {
1216 | Javauto javauto = new Javauto();
1217 | assertThat(javauto.getEnv("")).isEmpty();
1218 | }
1219 |
1220 | @Test
1221 | public void testGetEnvWithoutParameter() {
1222 | Javauto javauto = new Javauto();
1223 | assertThat(javauto.getEnv()).isNotEmpty();
1224 | }
1225 |
1226 | @Test
1227 | public void testArrayToClipString() {
1228 | Javauto javauto = new Javauto();
1229 | String[] a1 = { "Pierre", "Fermat" };
1230 | javauto.arrayToClip(a1);
1231 | assertThat(javauto.clipboardGet()).isEqualToIgnoringCase(
1232 | "[Pierre, Fermat]");
1233 | }
1234 |
1235 | @Test
1236 | public void testArrayToClipByte() {
1237 | Javauto javauto = new Javauto();
1238 | byte[] a1 = new byte[] { 5, 62 };
1239 | javauto.arrayToClip(a1);
1240 |
1241 | assertThat(javauto.clipboardGet()).isEqualToIgnoringCase("[5, 62]");
1242 | }
1243 |
1244 | @Test
1245 | public void testArrayToClipBoolean() {
1246 | Javauto javauto = new Javauto();
1247 | boolean[] a1 = new boolean[] { true, false };
1248 | javauto.arrayToClip(a1);
1249 |
1250 | assertThat(javauto.clipboardGet()).isEqualToIgnoringCase(
1251 | "[true, false]");
1252 | }
1253 |
1254 | @Test
1255 | public void testArrayToClipChart() {
1256 | Javauto javauto = new Javauto();
1257 | char[] a1 = new char[] { 'p', 's' };
1258 | javauto.arrayToClip(a1);
1259 |
1260 | assertThat(javauto.clipboardGet()).isEqualToIgnoringCase("[p, s]");
1261 | }
1262 |
1263 | @Test
1264 | public void testArrayToClipFloat() {
1265 | Javauto javauto = new Javauto();
1266 | float[] a1 = { 5.2f, 46.1f };
1267 | javauto.arrayToClip(a1);
1268 |
1269 | assertThat(javauto.clipboardGet()).isEqualToIgnoringCase("[5.2, 46.1]");
1270 | }
1271 |
1272 | @Test
1273 | public void testArrayToClipInt() {
1274 | Javauto javauto = new Javauto();
1275 | int[] a1 = { 5, 4 };
1276 | javauto.arrayToClip(a1);
1277 |
1278 | assertThat(javauto.clipboardGet()).isEqualToIgnoringCase("[5, 4]");
1279 | }
1280 |
1281 | @Test
1282 | public void testArrayToClipLong() {
1283 | Javauto javauto = new Javauto();
1284 | long[] a1 = { 56, 46464 };
1285 | javauto.arrayToClip(a1);
1286 |
1287 | assertThat(javauto.clipboardGet()).isEqualToIgnoringCase("[56, 46464]");
1288 | }
1289 |
1290 | @Test
1291 | public void testArrayToClipShort() {
1292 | Javauto javauto = new Javauto();
1293 | short[] a1 = { 5, 2 };
1294 | javauto.arrayToClip(a1);
1295 |
1296 | assertThat(javauto.clipboardGet()).isEqualToIgnoringCase("[5, 2]");
1297 | }
1298 |
1299 | }
1300 |
--------------------------------------------------------------------------------
/src/test/java/com/automation/javauto/test/TestPanel.java:
--------------------------------------------------------------------------------
1 | package com.automation.javauto.test;
2 |
3 | import java.awt.event.InputEvent;
4 | import java.awt.event.MouseAdapter;
5 | import java.awt.event.MouseEvent;
6 |
7 | import javax.swing.JFrame;
8 | import javax.swing.JTextArea;
9 |
10 | /**
11 | * Creates a simple panel for testing purposes.
12 | *
13 | * @author henry.tejera
14 | *
15 | */
16 | public class TestPanel extends JFrame {
17 |
18 | private static final long serialVersionUID = 1L;
19 | private String clickedButton;
20 | private int clickCount;
21 |
22 | /**
23 | * Create a new TestPanel instance.
24 | *
25 | * @param width
26 | * - The Width of the panel.
27 | * @param height
28 | * - The Height of the panel.
29 | * @param x
30 | * - x location.
31 | * @param y
32 | * - y location.
33 | */
34 | public TestPanel(int width, int height, int x, int y) {
35 | setSize(width, height);
36 | setLocation(x, y);
37 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
38 |
39 | final JTextArea textArea = new JTextArea();
40 |
41 | textArea.addMouseListener(new MouseAdapter() {
42 | public void mouseClicked(MouseEvent e) {
43 | if (e.getButton() == MouseEvent.NOBUTTON) {
44 | textArea.setText("No button clicked...");
45 | setClickedButton("NoButton");
46 | } else if (e.getButton() == MouseEvent.BUTTON1) {
47 | textArea.setText("Button left clicked...");
48 | setClickedButton("left");
49 | } else if (e.getButton() == MouseEvent.BUTTON2) {
50 | textArea.setText("Button left middle...");
51 | setClickedButton("middle");
52 | } else if (e.getButton() == MouseEvent.BUTTON3) {
53 | textArea.setText("Button left right...");
54 | setClickedButton("right");
55 | }
56 | setClickCount(getClickCount());
57 | }
58 | });
59 |
60 | getContentPane().add(textArea);
61 | setVisible(true);
62 | }
63 |
64 | /**
65 | * @return the clickedButton
66 | */
67 | public String getClickedButton() {
68 | return clickedButton;
69 | }
70 |
71 | /**
72 | * @param clickedButton
73 | * the clickedButton to set
74 | */
75 | public void setClickedButton(String clickedButton) {
76 | this.clickedButton = clickedButton;
77 | }
78 |
79 | /**
80 | * @return the clickCount
81 | */
82 | public int getClickCount() {
83 | return clickCount;
84 | }
85 |
86 | /**
87 | * @param clickCount
88 | * the clickCount to set
89 | */
90 | public void setClickCount(int clickCount) {
91 | this.clickCount = clickCount;
92 | }
93 | }
--------------------------------------------------------------------------------
/src/test/resources/fermat.txt:
--------------------------------------------------------------------------------
1 | France Toulouse
--------------------------------------------------------------------------------
/src/test/resources/script/tests.javauto:
--------------------------------------------------------------------------------
1 | global boolean ok;
2 | global int errCount;
3 | ok = true;
4 | errCount = 0;
5 |
6 | //#START PSEUDO-ASSERTS
7 |
8 | //Print an error and exit.
9 | //@param method - The method name in which the error occurred.
10 | //@para desscription - The error description.
11 | func void setError(String method, String description){
12 | print("Error on [%s]. Description [%s]." % (method, description));
13 | ok = false;
14 | errCount = errCount + 1;
15 | }
16 |
17 | //Assert that the given condition is true
18 | //@param condition
19 | //@param method - Method name.
20 | //@param message - Custom error message.
21 | func void assertThatIsTrue(boolean condition, String method, String message){
22 | String msg = "Expected [true] but was [%s]" %(toString(condition));
23 |
24 | if(!condition){
25 | if(!message.isEmpty()){
26 | msg = message;
27 | }
28 | setError(method, msg);
29 | }
30 | }
31 |
32 | //Assert that the given condition is false
33 | //@param condition
34 | //@param method - Method name.
35 | //@param message - Custom error message.
36 | func void assertThatIsFalse(boolean condition, String method, String message){
37 | String msg = "Expected [false] but was [%s]" %(toString(condition));
38 |
39 | if(condition){
40 | if(!message.isEmpty()){
41 | msg = message;
42 | }
43 | setError(method, msg);
44 | }
45 | }
46 |
47 | //Assert that two int values numerically are equals.
48 | //@param a - The first int.
49 | //@para b - The second int.
50 | //@param method - Method name.
51 | //@param message - Custom error message.
52 | func void assertThatIntEquals(int a, int b, String method, String message){
53 | String msg = "Expected [%s] but was [%s]" %(toString(b), toString(a));
54 |
55 | if(Integer.compare(a, b) != 0){
56 | if(!message.isEmpty()){
57 | msg = message;
58 | }
59 | setError(method, msg);
60 | }
61 | }
62 |
63 | //Assert that two strings lexicographically (ignoring case differences) are equals.s.
64 | //@param a - The first String.
65 | //@para b - The second String.
66 | //@param method - Method name.
67 | //@param message - Custom error message.
68 | func void assertThatStringEquals(String a, String b, String method, String message){
69 | String msg = "Expected [%s] but was [%s]" %(b, a);
70 |
71 | if(!a.equals(b)){
72 | if(!message.isEmpty()){
73 | msg = message;
74 | }
75 | setError(method, msg);
76 | }
77 | }
78 |
79 |
80 | //#END PSEUDO-ASSERTS
81 |
82 | //#START TESTS
83 | func void testArrayAsListFunc(){
84 | String method = "arrayAsList";
85 | String[] a1 = {"a","b","c"};
86 | List theList = arrayAsList(a1);
87 | assertThatIsTrue((theList.size() == 3), method,"");
88 | };
89 |
90 | func void testArrayBinarySearchByte() {
91 | String method = "arrayBinarySearch (Byte)";
92 | byte searchVal = 35;
93 | byte[] arr = { 10, 12, 34, searchVal, 5 };
94 | assertThatIntEquals(arrayBinarySearch(arr, searchVal), 4, method, "");
95 | }
96 |
97 | func void testArrayBinarySearchChart() {
98 | String method = "arrayBinarySearch (Chart)";
99 | char searchVal = 'c';
100 | char[] arr = {'a', 'c', 'b', 'e','d'};
101 | assertThatIntEquals(arrayBinarySearch(arr, searchVal), 2, method, "");
102 | }
103 |
104 | func void testArrayBinarySearchDouble() {
105 | String method = "arrayBinarySearch (Double)";
106 | double searchVal = 4.6;
107 | double[] arr = {5.4,49.2,9.2,35.4,4.6};
108 | assertThatIntEquals(arrayBinarySearch(arr, searchVal), 0, method, "");
109 | }
110 |
111 | func void testArrayBinarySearchFloat() {
112 | String method = "arrayBinarySearch (Float)";
113 | float searchVal = 42.9f;
114 | float[] arr = {5.2f,46.1f,42.9f,22.3f};
115 | assertThatIntEquals(arrayBinarySearch(arr, searchVal), 2, method, "");
116 | }
117 |
118 | func void testArrayBinarySearchInt() {
119 | String method = "arrayBinarySearch (Int)";
120 | int searchVal = 5;
121 | int[] arr = {30,20,5,12,55};
122 | assertThatIntEquals(arrayBinarySearch(arr, searchVal), 0, method, "");
123 | }
124 |
125 | func void testArrayBinarySearchLong() {
126 | String method = "arrayBinarySearch (Long)";
127 | long searchVal = 46464;
128 | long[] arr = {56,46464,3342,232,3445};
129 | assertThatIntEquals(arrayBinarySearch(arr, searchVal), 4, method, "");
130 | }
131 |
132 | func void testArrayBinarySearchShort() {
133 | String method = "arrayBinarySearch (Short)";
134 | short searchVal = 52;
135 | short[] arr = {5,2,15,52,10};
136 | assertThatIntEquals(arrayBinarySearch(arr, searchVal), 4, method, "");
137 | }
138 |
139 | func void testArrayCopyOfBoolean() {
140 | String method = "arrayCopyOf (Boolean)";
141 | boolean[] a1 = new boolean[] {true, false};
142 | boolean[] a2 = arrayCopyOf(a1, 4);
143 | assertThatIntEquals(a2.length, 4, method, "");
144 | }
145 |
146 | func void testArrayCopyOfBytes() {
147 | String method = "arrayCopyOf (Bytes)";
148 | byte[] a1 = new byte[] { 5, 62, 15 };
149 | byte[] a2 = arrayCopyOf(a1, 4);
150 | assertThatIntEquals(a2.length, 4, method, "");
151 | }
152 |
153 | func void testArrayCopyOfChar() {
154 | String method = "arrayCopyOf (Char)";
155 | char[] a1 = new char[] { 'p', 's', 'r' };
156 | char[] a2 = arrayCopyOf(a1, 4);
157 | assertThatIntEquals(a2.length, 4, method, "");
158 | }
159 |
160 | func void testArrayToStringBoolean() {
161 | String method = "arrayToString (Boolean)";
162 | boolean[] a1 = new boolean[] { true, false };
163 | assertThatStringEquals(arrayToString(a1),"[true, false]", method, "");
164 | }
165 |
166 | func void testArrayToStringByte() {
167 | String method = "arrayToString (Byte)";
168 | byte[] a1 = new byte[] { 5, 62 };
169 | assertThatStringEquals(arrayToString(a1),"[5, 62]", method, "");
170 | }
171 |
172 | func void testArrayToStringChar() {
173 | String method = "arrayToString (Char)";
174 | char[] a1 = new char[] { 'p', 's' };
175 | assertThatStringEquals(arrayToString(a1),"[p, s]", method, "");
176 | }
177 |
178 | func void testArrayToStringDouble() {
179 | String method = "arrayToString (Double)";
180 | double a1[] = { 5.4, 49.2 };
181 | assertThatStringEquals(arrayToString(a1),"[5.4, 49.2]", method, "");
182 | }
183 |
184 | func void testArrayToStringFloat() {
185 | String method = "arrayToString (Double)";
186 | float a1[] = { 5.2f, 46.1f };
187 | assertThatStringEquals(arrayToString(a1),"[5.2, 46.1]", method, "");
188 | }
189 |
190 | func void testArrayToStringInt() {
191 | String method = "arrayToString (Int)";
192 | int a1[] = { 5, 4 };
193 | assertThatStringEquals(arrayToString(a1),"[5, 4]", method, "");
194 | }
195 |
196 | func void testArrayToStringLong() {
197 | String method = "arrayToString (Long)";
198 | long a1[] = { 56, 46464 };
199 | assertThatStringEquals(arrayToString(a1),"[56, 46464]", method, "");
200 | }
201 |
202 | func void testArrayToStringShort() {
203 | String method = "arrayToString (Short)";
204 | short a1[] = { 5, 2 };
205 | assertThatStringEquals(arrayToString(a1),"[5, 2]", method, "");
206 | }
207 |
208 | func void testArrayToStringString() {
209 | String method = "arrayToString (String)";
210 | String[] a1 = { "Julio", "Rey", "Pastor" };
211 | String result = arrayToString(a1);
212 | assertThatStringEquals(arrayToString(a1),"[Julio, Rey, Pastor]", method, "");
213 | }
214 |
215 | func void testArrayEqualsBoolean() {
216 | String method = "arrayEquals (Boolean)";
217 | boolean[] a1 = new boolean[] { true, false };
218 | boolean[] a2 = new boolean[] { true, false };
219 | boolean[] a3 = new boolean[] { true, true };
220 | assertThatIsTrue((arrayEquals(a1, a2)), method, "");
221 | assertThatIsFalse((arrayEquals(a1, a3)), method, "");
222 | }
223 |
224 | func void testArrayEqualsByte() {
225 | String method = "arrayEquals (Byte)";
226 | byte[] a1 = new byte[] { 5, 62 };
227 | byte[] a2 = new byte[] { 5, 62 };
228 | byte[] a3 = new byte[] { 5 };
229 | assertThatIsTrue((arrayEquals(a1, a2)), method, "");
230 | assertThatIsFalse((arrayEquals(a1, a3)), method, "");
231 | }
232 |
233 | func void testArrayEqualsChar() {
234 | String method = "arrayEquals (Char)";
235 | char[] a1 = new char[] { 'p', 's' };
236 | char[] a2 = new char[] { 'p', 's' };
237 | char[] a3 = new char[] { 'p', 'p' };
238 | assertThatIsTrue((arrayEquals(a1, a2)), method, "");
239 | assertThatIsFalse((arrayEquals(a1, a3)), method, "");
240 | }
241 |
242 | func void testArrayEqualsDouble() {
243 | String method = "arrayEquals (Double)";
244 | double[] a1 = { 5.4, 49.2 };
245 | double[] a2 = { 5.4, 49.2 };
246 | double[] a3 = { 5.4, 2.1 };
247 | assertThatIsTrue((arrayEquals(a1, a2)), method, "");
248 | assertThatIsFalse((arrayEquals(a1, a3)), method, "");
249 | }
250 |
251 | func void testArrayEqualsFloat() {
252 | String method = "arrayEquals (Float)";
253 | float[] a1 = { 5.2f, 46.1f };
254 | float[] a2 = { 5.2f, 46.1f };
255 | float[] a3 = { 5.2f, 6.1f };
256 | assertThatIsTrue((arrayEquals(a1, a2)), method, "");
257 | assertThatIsFalse((arrayEquals(a1, a3)), method, "");
258 | }
259 |
260 | func void testArrayEqualsInt() {
261 | String method = "arrayEquals (Int)";
262 | int[] a1 = { 1, 2 };
263 | int[] a2 = { 1, 2 };
264 | int[] a3 = { 0, 2 };
265 | assertThatIsTrue((arrayEquals(a1, a2)), method, "");
266 | assertThatIsFalse((arrayEquals(a1, a3)), method, "");
267 | }
268 |
269 | func void testArrayEqualsLong() {
270 | String method = "arrayEquals (Long)";
271 | long[] a1 = { 56, 46464 };
272 | long[] a2 = { 56, 46464 };
273 | long[] a3 = { 56, 46 };
274 | assertThatIsTrue((arrayEquals(a1, a2)), method, "");
275 | assertThatIsFalse((arrayEquals(a1, a3)), method, "");
276 | }
277 |
278 | func void testArrayEqualsShort() {
279 | String method = "arrayEquals (Short)";
280 | short[] a1 = { 5, 2 };
281 | short[] a2 = { 5, 2 };
282 | short[] a3 = { 5, 5 };
283 | assertThatIsTrue((arrayEquals(a1, a2)), method, "");
284 | assertThatIsFalse((arrayEquals(a1, a3)), method, "");
285 | }
286 |
287 | func void testArrayEqualsString() {
288 | String method = "arrayEquals (String)";
289 | String[] a1 = { "Pierre", "Fermat" };
290 | String[] a2 = { "Pierre", "Fermat" };
291 | String[] a3 = { "Evariste", "Galois" };
292 | assertThatIsTrue((arrayEquals(a1, a2)), method, "");
293 | assertThatIsFalse((arrayEquals(a1, a3)), method, "");
294 | }
295 |
296 | func void testClipboardPutAndGet(){
297 | String method = "clipboardPut & clipboardGet";
298 | String clip = "put me in the clipboard!";
299 | clipboardPut(clip);
300 | assertThatStringEquals(clip,clipboardGet(), method, "");
301 | }
302 |
303 | func void testSetAndGetSpeed(){
304 | String method = "setSpeed & getSpeed";
305 | double spd = 0.5;
306 | setSpeed(spd);
307 | assertThatStringEquals(toString(spd), toString(getSpeed()), method, "");
308 | }
309 |
310 | func void testGetEnvWithParameter(){
311 | String method = "envGet (String)";
312 | String value = getEnv("PATH");
313 | assertThatIsFalse(value.isEmpty(), method, "");
314 | }
315 |
316 | func void testGetEnvWithEmptyParameter(){
317 | String method = "envGet";
318 | String value = getEnv("");
319 | assertThatIsTrue(value.isEmpty(), method, "");
320 | }
321 |
322 | func void testGetEnvWithoutParameter(){
323 | String method = "envGet";
324 | String value = getEnv();
325 | assertThatIsFalse(value.isEmpty(), method, "");
326 | }
327 |
328 | func void testArrayToClipString() {
329 | String method = "arrayToClip (String)";
330 | String[] a1 = { "Pierre", "Fermat" };
331 | arrayToClip(a1);
332 | assertThatStringEquals(clipboardGet(), "[Pierre, Fermat]", method, "");
333 | }
334 |
335 | func void testArrayToClipByte() {
336 | String method = "arrayToClip (Byte)";
337 | byte[] a1 = new byte[] { 5, 62 };
338 | arrayToClip(a1);
339 | assertThatStringEquals(clipboardGet(), "[5, 62]", method, "");
340 | }
341 |
342 | func void testArrayToClipBoolean() {
343 | String method = "arrayToClip (Boolean)";
344 | boolean[] a1 = new boolean[] { true, false };
345 | arrayToClip(a1);
346 | assertThatStringEquals(clipboardGet(), "[true, false]", method, "");
347 | }
348 |
349 | func void testArrayToClipChart() {
350 | String method = "arrayToClip (Chart)";
351 | char[] a1 = new char[] { 'p', 's' };
352 | arrayToClip(a1);
353 | assertThatStringEquals(clipboardGet(), "[p, s]", method, "");
354 | }
355 |
356 | func void testArrayToClipFloat() {
357 | String method = "arrayToClip (Float)";
358 | float[] a1 = { 5.2f, 46.1f };
359 | arrayToClip(a1);
360 | assertThatStringEquals(clipboardGet(), "[5.2, 46.1]", method, "");
361 | }
362 |
363 | func void testArrayToClipInt() {
364 | String method = "arrayToClip (Int)";
365 | int[] a1 = { 5, 4 };
366 | arrayToClip(a1);
367 | assertThatStringEquals(clipboardGet(), "[5, 4]", method, "");
368 | }
369 |
370 | func void testArrayToClipLong() {
371 | String method = "arrayToClip (Long)";
372 | long[] a1 = { 56, 46464 };
373 | arrayToClip(a1);
374 | assertThatStringEquals(clipboardGet(), "[56, 46464]", method, "");
375 | }
376 |
377 | func void testArrayToClipShort() {
378 | String method = "arrayToClip (Short)";
379 | short[] a1 = { 5, 2 };
380 | arrayToClip(a1);
381 | assertThatStringEquals(clipboardGet(), "[5, 2]", method, "");
382 | }
383 | //#END TESTS
384 |
385 |
386 | //Test suite.
387 | func void suite(){
388 | testArrayAsListFunc();
389 | testArrayBinarySearchByte();
390 | testArrayBinarySearchChart();
391 | testArrayBinarySearchDouble();
392 | testArrayBinarySearchFloat();
393 | testArrayBinarySearchInt();
394 | testArrayBinarySearchLong();
395 | testArrayBinarySearchShort();
396 | testArrayCopyOfBoolean();
397 | testArrayCopyOfBytes();
398 | testArrayToStringBoolean();
399 | testArrayToStringChar();
400 | testArrayToStringDouble();
401 | testArrayToStringFloat();
402 | testArrayToStringInt();
403 | testArrayToStringLong();
404 | testArrayToStringShort();
405 | testArrayToStringString();
406 | testArrayEqualsBoolean();
407 | testArrayEqualsByte();
408 | testArrayEqualsChar();
409 | testArrayEqualsDouble();
410 | testArrayEqualsFloat();
411 | testArrayEqualsInt();
412 | testArrayEqualsLong();
413 | testArrayEqualsShort();
414 | testArrayEqualsString();
415 | testClipboardPutAndGet();
416 | testSetAndGetSpeed();
417 | testGetEnvWithParameter();
418 | testGetEnvWithEmptyParameter();
419 | testGetEnvWithoutParameter();
420 | testArrayToClipString();
421 | testArrayToClipByte();
422 | testArrayToClipBoolean();
423 | testArrayToClipChart();
424 | testArrayToClipFloat();
425 | testArrayToClipInt();
426 | testArrayToClipLong();
427 | testArrayToClipShort();
428 | }
429 |
430 | suite();
431 |
432 | if(ok){
433 | print("Far out! Everything passed!");
434 | exit();
435 | } else {
436 | print("Bummer! You have failing tests!. Errors count [%s]" % (toString(errCount)));
437 | exit(1);
438 | }
439 |
--------------------------------------------------------------------------------