aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Yue Gan <yueg@google.com>2017-01-25 10:14:52 +0000
committerGravatar Laszlo Csomor <laszlocsomor@google.com>2017-01-25 13:05:26 +0000
commit81ea54e5545803da0e8c0f7402305d5619765f0e (patch)
tree6df6c01d4141495d6a9a60e3739800b7c0d04cec /src
parentc4e92b1ba06fba48121e4db8050a69b6d998e2e9 (diff)
Benchmark part 1: generate java code for build
-- PiperOrigin-RevId: 145524911 MOS_MIGRATED_REVID=145524911
Diffstat (limited to 'src')
-rw-r--r--src/BUILD1
-rw-r--r--src/tools/benchmark/BUILD8
-rw-r--r--src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/BUILD28
-rw-r--r--src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/GeneratorOptions.java71
-rw-r--r--src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/JavaCodeGenerator.java230
-rw-r--r--src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/JavaCodeGeneratorHelper.java225
-rw-r--r--src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/Main.java71
-rw-r--r--src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/BUILD36
-rw-r--r--src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/JavaCodeGeneratorHelperTest.java255
-rw-r--r--src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/JavaCodeGeneratorTest.java124
-rw-r--r--src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/MainTest.java92
11 files changed, 1141 insertions, 0 deletions
diff --git a/src/BUILD b/src/BUILD
index 2739232951..bca7c98a15 100644
--- a/src/BUILD
+++ b/src/BUILD
@@ -321,6 +321,7 @@ filegroup(
"//src/test/java/com/google/devtools/common/options:srcs",
"//src/test/shell:srcs",
"//src/tools/android/java/com/google/devtools/build/android:srcs",
+ "//src/tools/benchmark:srcs",
"//src/tools/generate_workspace:srcs",
"//src/tools/xcode/actoolwrapper:srcs",
"//src/tools/xcode/environment:srcs",
diff --git a/src/tools/benchmark/BUILD b/src/tools/benchmark/BUILD
new file mode 100644
index 0000000000..c2678f81ce
--- /dev/null
+++ b/src/tools/benchmark/BUILD
@@ -0,0 +1,8 @@
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]) + [
+ "//src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator:srcs",
+ "//src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator:srcs",
+ ],
+ visibility = ["//src:__pkg__"],
+)
diff --git a/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/BUILD b/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/BUILD
new file mode 100644
index 0000000000..4285252bd8
--- /dev/null
+++ b/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/BUILD
@@ -0,0 +1,28 @@
+package(default_visibility = ["//src/tools/benchmark:__subpackages__"])
+
+java_binary(
+ name = "codegenerator",
+ srcs = glob(["*.java"]),
+ main_class = "com.google.devtools.build.benchmark.codegenerator.Main",
+ deps = [
+ "//src/main/java/com/google/devtools/common/options",
+ "//third_party:guava",
+ "//third_party/java/javapoet",
+ ],
+)
+
+java_library(
+ name = "codegenerator_lib",
+ srcs = glob(["*.java"]),
+ deps = [
+ "//src/main/java/com/google/devtools/common/options",
+ "//third_party:guava",
+ "//third_party/java/javapoet",
+ ],
+)
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+ visibility = ["//src:__pkg__"],
+)
diff --git a/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/GeneratorOptions.java b/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/GeneratorOptions.java
new file mode 100644
index 0000000000..dd3d79346b
--- /dev/null
+++ b/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/GeneratorOptions.java
@@ -0,0 +1,71 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.benchmark.codegenerator;
+
+import com.google.devtools.common.options.Option;
+import com.google.devtools.common.options.OptionsBase;
+
+/** Class that contains arguments for the java files generator. */
+public class GeneratorOptions extends OptionsBase {
+
+ @Option(
+ name = "modify",
+ defaultValue = "false",
+ category = "generator",
+ help = "if we modify the existing code (or generate new code)."
+ )
+ public boolean modificationMode;
+
+ @Option(
+ name = "output_dir",
+ defaultValue = "",
+ category = "generator",
+ valueHelp = "path",
+ help = "directory where we put generated code or modify the existing code."
+ )
+ public String outputDir;
+
+ @Option(
+ name = "a_few_files",
+ defaultValue = "false",
+ category = "generator",
+ help = "if we generate a package with a few files."
+ )
+ public boolean aFewFiles;
+
+ @Option(
+ name = "many_files",
+ defaultValue = "false",
+ category = "generator",
+ help = "if we generate a package with many files."
+ )
+ public boolean manyFiles;
+
+ @Option(
+ name = "long_chained_deps",
+ defaultValue = "false",
+ category = "generator",
+ help = "if we generate a package with long chained dependencies."
+ )
+ public boolean longChainedDeps;
+
+ @Option(
+ name = "parallel_deps",
+ defaultValue = "false",
+ category = "generator",
+ help = "if we generate a package with parallel dependencies."
+ )
+ public boolean parallelDeps;
+}
diff --git a/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/JavaCodeGenerator.java b/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/JavaCodeGenerator.java
new file mode 100644
index 0000000000..f1ba3a6eed
--- /dev/null
+++ b/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/JavaCodeGenerator.java
@@ -0,0 +1,230 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.benchmark.codegenerator;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/** Create 4 types of Java project, or modify existing ones. */
+public class JavaCodeGenerator {
+
+ @VisibleForTesting static final String TARGET_A_FEW_FILES = "AFewFiles";
+ @VisibleForTesting static final int SIZE_A_FEW_FILES = 10;
+
+ @VisibleForTesting static final String TARGET_MANY_FILES = "ManyFiles";
+ @VisibleForTesting static final int SIZE_MANY_FILES = 1000;
+
+ @VisibleForTesting static final String TARGET_LONG_CHAINED_DEPS = "LongChainedDeps";
+ @VisibleForTesting static final int SIZE_LONG_CHAINED_DEPS = 20;
+
+ @VisibleForTesting static final String TARGET_PARALLEL_DEPS = "ParallelDeps";
+ @VisibleForTesting static final int SIZE_PARALLEL_DEPS = 20;
+
+ public static void generateNewProject(
+ String outputDir,
+ boolean aFewFiles,
+ boolean manyFiles,
+ boolean longChainedDeps,
+ boolean parallelDeps) {
+ Path dir = Paths.get(outputDir);
+ if (aFewFiles) {
+ createTargetWithSomeFiles(dir.resolve(TARGET_A_FEW_FILES), SIZE_A_FEW_FILES);
+ }
+ if (manyFiles) {
+ createTargetWithSomeFiles(dir.resolve(TARGET_MANY_FILES), SIZE_MANY_FILES);
+ }
+ if (longChainedDeps) {
+ createTargetWithLongChainedDeps(dir.resolve(TARGET_LONG_CHAINED_DEPS));
+ }
+ if (parallelDeps) {
+ createTargetWithParallelDeps(dir.resolve(TARGET_PARALLEL_DEPS));
+ }
+ }
+
+ public static void modifyExistingProject(
+ String outputDir,
+ boolean aFewFiles,
+ boolean manyFiles,
+ boolean longChainedDeps,
+ boolean parallelDeps) {
+ Path dir = Paths.get(outputDir);
+ if (aFewFiles) {
+ modifyTargetWithSomeFiles(dir.resolve(TARGET_A_FEW_FILES));
+ }
+ if (manyFiles) {
+ modifyTargetWithSomeFiles(dir.resolve(TARGET_MANY_FILES));
+ }
+ if (longChainedDeps) {
+ modifyTargetWithLongChainedDeps(dir.resolve(TARGET_LONG_CHAINED_DEPS));
+ }
+ if (parallelDeps) {
+ modifyTargetWithParallelDeps(dir.resolve(TARGET_PARALLEL_DEPS));
+ }
+ }
+
+ /** Target type 1/2: Create targets with some files */
+ private static void createTargetWithSomeFiles(Path projectPath, int numberOfFiles) {
+ if (pathExists(projectPath)) {
+ return;
+ }
+
+ try {
+ Files.createDirectories(projectPath);
+
+ for (int i = 0; i < numberOfFiles; ++i) {
+ JavaCodeGeneratorHelper.writeRandomClassToDir(
+ /* addExtraMethod = */ false, "RandomClass" + i, "com.example.generated", projectPath);
+ }
+
+ JavaCodeGeneratorHelper.writeMainClassToDir("com.example.generated", projectPath);
+ JavaCodeGeneratorHelper.buildFileWithMainClass(TARGET_A_FEW_FILES, "", projectPath);
+ } catch (IOException e) {
+ System.err.println("Error creating target with some files: " + e.getMessage());
+ }
+ }
+
+ /** Target type 1/2: Modify targets with some files */
+ private static void modifyTargetWithSomeFiles(Path projectPath) {
+ File dir = projectPath.toFile();
+ if (directoryExists(dir)) {
+ System.err.format(
+ "Project dir (%s) does not contain code for modification.\n", projectPath.toString());
+ return;
+ }
+ try {
+ JavaCodeGeneratorHelper.writeRandomClassToDir(
+ /* addExtraMethod = */ true, "RandomClass0", "com.example.generated", projectPath);
+ } catch (IOException e) {
+ System.err.println("Error modifying targets some files: " + e.getMessage());
+ }
+ }
+
+ /** Target type 3: Create targets with a few long chained dependencies (A -> B -> C -> … -> Z) */
+ private static void createTargetWithLongChainedDeps(Path projectPath) {
+ if (pathExists(projectPath)) {
+ return;
+ }
+
+ try {
+ Files.createDirectories(projectPath);
+
+ int count = SIZE_LONG_CHAINED_DEPS;
+
+ // Call next one for 0..(count-2)
+ for (int i = 0; i < count - 1; ++i) {
+ JavaCodeGeneratorHelper.targetWithNextHelper(i, true, projectPath);
+ JavaCodeGeneratorHelper.buildFileWithNextDeps(
+ i, " deps=[ \":Deps" + (i + 1) + "\" ],\n", projectPath);
+ }
+ // Don't call next one for (count-1)
+ JavaCodeGeneratorHelper.targetWithNextHelper(count - 1, false, projectPath);
+ JavaCodeGeneratorHelper.buildFileWithNextDeps(count - 1, "", projectPath);
+
+ JavaCodeGeneratorHelper.writeMainClassToDir("com.example.generated", projectPath);
+
+ String deps = " deps=[ \":Deps0\" ],\n";
+ JavaCodeGeneratorHelper.buildFileWithMainClass(TARGET_LONG_CHAINED_DEPS, deps, projectPath);
+ } catch (IOException e) {
+ System.err.println(
+ "Error creating targets with a few long chained dependencies: " + e.getMessage());
+ }
+ }
+
+ /** Target type 3: Modify targets with a few long chained dependencies (A -> B -> C -> … -> Z) */
+ private static void modifyTargetWithLongChainedDeps(Path projectPath) {
+ File dir = projectPath.toFile();
+ if (directoryExists(dir)) {
+ System.err.format(
+ "Project dir (%s) does not contain code for modification.\n", projectPath.toString());
+ return;
+ }
+ try {
+ JavaCodeGeneratorHelper.targetWithNextExtraHelper(
+ (SIZE_LONG_CHAINED_DEPS + 1) >> 1, true, projectPath);
+ } catch (IOException e) {
+ System.err.println(
+ "Error modifying targets with a few long chained dependencies: " + e.getMessage());
+ }
+ }
+
+ /** Target type 4: Create targets with lots of parallel dependencies (A -> B, C, D, E, F, G, H) */
+ private static void createTargetWithParallelDeps(Path projectPath) {
+ if (pathExists(projectPath)) {
+ return;
+ }
+
+ try {
+ Files.createDirectories(projectPath);
+
+ int count = SIZE_PARALLEL_DEPS;
+
+ // parallel dependencies B~Z
+ for (int i = 1; i < count; ++i) {
+ JavaCodeGeneratorHelper.writeRandomClassToDir(
+ false, "Deps" + i, "com.example.deps" + i, projectPath);
+ JavaCodeGeneratorHelper.buildFileWithNextDeps(i, "", projectPath);
+ }
+
+ // A(Main)
+ JavaCodeGeneratorHelper.parallelDepsMainClassHelper(count, projectPath);
+
+ String deps = " deps=[ ";
+ for (int i = 1; i < count; ++i) {
+ deps += "\":Deps" + i + "\", ";
+ }
+ deps += "], \n";
+ JavaCodeGeneratorHelper.buildFileWithMainClass(TARGET_PARALLEL_DEPS, deps, projectPath);
+ } catch (IOException e) {
+ System.err.println(
+ "Error creating targets with lots of parallel dependencies: " + e.getMessage());
+ }
+ }
+
+ /** Target type 4: Modify targets with lots of parallel dependencies (A -> B, C, D, E, F, G, H) */
+ private static void modifyTargetWithParallelDeps(Path projectPath) {
+ File dir = projectPath.toFile();
+ if (directoryExists(dir)) {
+ System.err.format(
+ "Project dir (%s) does not contain code for modification.\n", projectPath.toString());
+ return;
+ }
+ try {
+ JavaCodeGeneratorHelper.writeRandomClassToDir(
+ true, "Deps1", "com.example.deps1", projectPath);
+ } catch (IOException e) {
+ System.err.println(
+ "Error creating targets with lots of parallel dependencies: " + e.getMessage());
+ }
+ }
+
+ private static boolean pathExists(Path path) {
+ File dir = path.toFile();
+ if (dir.exists()) {
+ System.err.println("File or directory exists, not rewriting it: " + path);
+ return true;
+ }
+
+ return false;
+ }
+
+ private static boolean directoryExists(File file) {
+ return !(file.exists() && file.isDirectory());
+ }
+}
diff --git a/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/JavaCodeGeneratorHelper.java b/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/JavaCodeGeneratorHelper.java
new file mode 100644
index 0000000000..82a0c48c1a
--- /dev/null
+++ b/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/JavaCodeGeneratorHelper.java
@@ -0,0 +1,225 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.benchmark.codegenerator;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.base.Joiner;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.JavaFile;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeSpec;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.Random;
+import javax.lang.model.element.Modifier;
+
+/** Helper class of {@link JavaCodeGenerator} */
+class JavaCodeGeneratorHelper {
+
+ private static final Joiner JOINER = Joiner.on("\n");
+ private static final MethodSpec randomMethod = genRandomMethod("PrintSth");
+ private static final MethodSpec somethingElseMethod = genRandomMethod("PrintSthElse");
+
+ /**
+ * Writes a class file {@code Deps(index).java} to the directory
+ * {@code projectPath/com/example/deps(index)}
+ *
+ * @param callNext if we should call the method from {@code Deps(index+1).java}
+ */
+ static void targetWithNextHelper(int index, boolean callNext, Path projectPath)
+ throws IOException {
+ ClassName nextClass = ClassName.get("com.example.deps" + (index + 1), "Deps" + (index + 1));
+
+ MethodSpec callNextMethod =
+ MethodSpec.methodBuilder("CallNext")
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+ .returns(void.class)
+ .addStatement("$T.PrintSth()", nextClass)
+ .build();
+
+ TypeSpec.Builder klassBuilder =
+ TypeSpec.classBuilder("Deps" + index)
+ .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
+ .addMethod(randomMethod);
+ if (callNext) {
+ klassBuilder.addMethod(callNextMethod);
+ }
+ TypeSpec klass = klassBuilder.build();
+
+ writeClassToDir(klass, "com.example.deps" + index, projectPath);
+ }
+
+ /**
+ * Writes a class file {@code Deps(index).java} with extra method {@code printSthElse()}
+ * to the directory {@code projectPath/com/example/deps(index)}
+ *
+ * @param callNext if we should call the method from {@code Deps(index+1).java}
+ */
+ static void targetWithNextExtraHelper(int index, boolean callNext, Path projectPath)
+ throws IOException {
+ ClassName nextClass = ClassName.get("com.example.deps" + (index + 1), "Deps" + (index + 1));
+
+ MethodSpec callNextMethod =
+ MethodSpec.methodBuilder("CallNext")
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+ .returns(void.class)
+ .addStatement("$T.PrintSth()", nextClass)
+ .build();
+
+ TypeSpec.Builder klassBuilder =
+ TypeSpec.classBuilder("Deps" + index)
+ .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
+ .addMethod(randomMethod)
+ .addMethod(somethingElseMethod);
+ if (callNext) {
+ klassBuilder.addMethod(callNextMethod);
+ }
+ TypeSpec klass = klassBuilder.build();
+
+ writeClassToDir(klass, "com.example.deps" + index, projectPath);
+ }
+
+ /**
+ * Writes {@code count-1} class files to the directory {@code projectPath/com/example/deps(index)}
+ * and one main class.
+ */
+ static void parallelDepsMainClassHelper(int count, Path projectPath) throws IOException {
+ MethodSpec.Builder callDepsBuilder =
+ MethodSpec.methodBuilder("main")
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+ .addParameter(String[].class, "args")
+ .returns(void.class);
+ for (int i = 1; i < count; ++i) {
+ ClassName callingClass = ClassName.get("com.example.deps" + i, "Deps" + i);
+ callDepsBuilder.addStatement("$T.PrintSth()", callingClass);
+ }
+ MethodSpec callDeps = callDepsBuilder.build();
+ TypeSpec klass =
+ TypeSpec.classBuilder("Main")
+ .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
+ .addMethod(callDeps)
+ .build();
+ writeClassToDir(klass, "com.example.generated", projectPath);
+ }
+
+ static void writeRandomClassToDir(
+ boolean addExtraMethod, String className, String packageName, Path projectPath)
+ throws IOException {
+ TypeSpec klass = genRandomClass(addExtraMethod, className);
+ writeClassToDir(klass, packageName, projectPath);
+ }
+
+ static void writeMainClassToDir(String packageName, Path projectPath) throws IOException {
+ TypeSpec main = genMainClass();
+ writeClassToDir(main, packageName, projectPath);
+ }
+
+ static void buildFileWithNextDeps(int index, String deps, Path projectPath) throws IOException {
+ Path buildFilePath = projectPath.resolve("BUILD");
+
+ String buildFileContent =
+ String.format(
+ JOINER
+ .join(
+ "java_library(",
+ " name = 'Deps%d',",
+ " srcs = glob([ 'com/example/deps%d/*.java' ]),",
+ "%s",
+ " visibility = [ '//visibility:public' ],",
+ ")"),
+ index,
+ index,
+ deps);
+
+ createAndAppendFile(buildFilePath, buildFileContent);
+ }
+
+ static void buildFileWithMainClass(String targetName, String deps, Path projectPath)
+ throws IOException {
+ Path buildFilePath = projectPath.resolve("BUILD");
+
+ String buildFileContent =
+ String.format(
+ JOINER
+ .join(
+ "java_binary(",
+ " name = '%s',",
+ " srcs = glob([ 'com/example/generated/*.java' ]),",
+ " main_class = 'com.example.generated.Main',",
+ "%s",
+ ")"),
+ targetName,
+ deps);
+
+ createAndAppendFile(buildFilePath, buildFileContent);
+ }
+
+ private static MethodSpec genRandomMethod(String methodName) {
+ return MethodSpec.methodBuilder(methodName)
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+ .returns(void.class)
+ .addStatement("$T rand = new Random()", Random.class)
+ .addStatement("int n = rand.nextInt(100)")
+ .addStatement(
+ "$T.out.format($S, $S, $L)",
+ System.class,
+ "This is method(%s) with random number(%d)\n",
+ methodName,
+ "n")
+ .build();
+ }
+
+ private static TypeSpec genRandomClass(boolean addExtraMethod, String className) {
+
+ TypeSpec.Builder klassBuilder =
+ TypeSpec.classBuilder(className)
+ .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
+ .addMethod(randomMethod);
+
+ if (addExtraMethod) {
+ klassBuilder.addMethod(somethingElseMethod);
+ }
+
+ return klassBuilder.build();
+ }
+
+ private static TypeSpec genMainClass() {
+ MethodSpec method =
+ MethodSpec.methodBuilder("main")
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+ .returns(void.class)
+ .addParameter(String[].class, "args")
+ .build();
+
+ return TypeSpec.classBuilder("Main").addModifiers(Modifier.PUBLIC).addMethod(method).build();
+ }
+
+ private static void writeClassToDir(TypeSpec klass, String packageName, Path path)
+ throws IOException {
+ JavaFile javaFile = JavaFile.builder(packageName, klass).build();
+ javaFile.writeTo(path);
+ }
+
+ private static void createAndAppendFile(Path path, String content) throws IOException {
+ if (!Files.exists(path)) {
+ Files.createFile(path);
+ }
+ Files.write(path, content.getBytes(UTF_8), StandardOpenOption.APPEND);
+ }
+
+}
diff --git a/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/Main.java b/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/Main.java
new file mode 100644
index 0000000000..f251701545
--- /dev/null
+++ b/src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator/Main.java
@@ -0,0 +1,71 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.benchmark.codegenerator;
+
+import com.google.devtools.common.options.Options;
+import com.google.devtools.common.options.OptionsParsingException;
+import java.io.File;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/** Main class for generating code. */
+public class Main {
+
+ private static final Logger logger = Logger.getLogger(Main.class.getName());
+
+ public static void main(String[] args) {
+ GeneratorOptions opt = null;
+ try {
+ opt = parseArgs(args);
+ } catch (Exception e) {
+ if (!e.getMessage().isEmpty()) {
+ logger.log(Level.SEVERE, e.getMessage());
+ }
+ System.exit(1);
+ }
+
+ // Generate or modify Java code
+ if (opt.modificationMode) {
+ JavaCodeGenerator.modifyExistingProject(
+ opt.outputDir, opt.aFewFiles, opt.manyFiles, opt.longChainedDeps, opt.parallelDeps);
+ } else {
+ JavaCodeGenerator.generateNewProject(
+ opt.outputDir, opt.aFewFiles, opt.manyFiles, opt.longChainedDeps, opt.parallelDeps);
+ }
+ }
+
+ public static GeneratorOptions parseArgs(String[] args) throws OptionsParsingException {
+ GeneratorOptions opt = Options.parse(GeneratorOptions.class, args).getOptions();
+
+ // Check output_dir argument
+ if (opt.outputDir.isEmpty()) {
+ throw new IllegalArgumentException("--output_dir should not be empty.");
+ }
+ if (opt.modificationMode) {
+ File dir = new File(opt.outputDir);
+ if (!(dir.exists() && dir.isDirectory())) {
+ throw new IllegalArgumentException(
+ "--output_dir (" + opt.outputDir + ") does not contain code for modification.");
+ }
+ }
+ // Check at least one type of package will be generated
+ if (!(opt.aFewFiles || opt.manyFiles || opt.longChainedDeps || opt.parallelDeps)) {
+ System.err.println(Options.getUsage(GeneratorOptions.class));
+ throw new IllegalArgumentException("No type of package is specified.");
+ }
+
+ return opt;
+ }
+}
diff --git a/src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/BUILD b/src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/BUILD
new file mode 100644
index 0000000000..6982009058
--- /dev/null
+++ b/src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/BUILD
@@ -0,0 +1,36 @@
+java_test(
+ name = "JavaCodeGeneratorHelperTest",
+ srcs = ["JavaCodeGeneratorHelperTest.java"],
+ deps = [
+ "//src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator:codegenerator_lib",
+ "//third_party:guava",
+ "//third_party:junit4",
+ ],
+)
+
+java_test(
+ name = "JavaCodeGeneratorTest",
+ srcs = ["JavaCodeGeneratorTest.java"],
+ deps = [
+ "//src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator:codegenerator_lib",
+ "//third_party:guava",
+ "//third_party:junit4",
+ "//third_party:truth",
+ ],
+)
+
+java_test(
+ name = "MainTest",
+ srcs = ["MainTest.java"],
+ deps = [
+ "//src/main/java/com/google/devtools/common/options",
+ "//src/tools/benchmark/java/com/google/devtools/build/benchmark/codegenerator:codegenerator_lib",
+ "//third_party:junit4",
+ ],
+)
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+ visibility = ["//src:__pkg__"],
+)
diff --git a/src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/JavaCodeGeneratorHelperTest.java b/src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/JavaCodeGeneratorHelperTest.java
new file mode 100644
index 0000000000..15f41b30a5
--- /dev/null
+++ b/src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/JavaCodeGeneratorHelperTest.java
@@ -0,0 +1,255 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.benchmark.codegenerator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.base.Joiner;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Scanner;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test for {@link JavaCodeGeneratorHelper}. */
+@RunWith(JUnit4.class)
+public class JavaCodeGeneratorHelperTest {
+
+ private static final String RANDOM_CLASS_CONTENT = joinLines(
+ "package com.package.name;",
+ "",
+ "import java.lang.System;",
+ "import java.util.Random;",
+ "",
+ "public final class ClassName {",
+ " public static void PrintSth() {",
+ " Random rand = new Random();",
+ " int n = rand.nextInt(100);",
+ " System.out.format(\"This is method(%s) with random number(%d)\\n\", \"PrintSth\", n);",
+ " }",
+ "}");
+
+ private static final String RANDOM_CLASS_EXTRA_CONTENT = joinLines(
+ "package com.package.name;",
+ "",
+ "import java.lang.System;",
+ "import java.util.Random;",
+ "",
+ "public final class ClassNameExtra {",
+ " public static void PrintSth() {",
+ " Random rand = new Random();",
+ " int n = rand.nextInt(100);",
+ " System.out.format(\"This is method(%s) with random number(%d)\\n\", \"PrintSth\", n);",
+ " }",
+ "",
+ " public static void PrintSthElse() {",
+ " Random rand = new Random();",
+ " int n = rand.nextInt(100);",
+ " System.out.format(\"This is method(%s) with random number(%d)\\n\","
+ + " \"PrintSthElse\", n);",
+ " }",
+ "}");
+
+ private static final String MAIN_CLASS_CONTENT = joinLines(
+ "package com.package.name;",
+ "",
+ "import java.lang.String;",
+ "",
+ "public class Main {",
+ " public static void main(String[] args) {",
+ " }",
+ "}");
+
+ private static final String DEPS_BUILD_FILE_CONTENT = joinLines(
+ "java_library(",
+ " name = 'Deps42',",
+ " srcs = glob([ 'com/example/deps42/*.java' ]),",
+ "<this is deps>",
+ " visibility = [ '//visibility:public' ],",
+ ")");
+
+ private static final String TARGET_BUILD_FILE_CONTENT = joinLines(
+ "java_binary(",
+ " name = 'Target',",
+ " srcs = glob([ 'com/example/generated/*.java' ]),",
+ " main_class = 'com.example.generated.Main',",
+ "<this is deps>",
+ ")");
+
+ private static final String DEPS_CLASS_CONTENT = joinLines(
+ "package com.example.deps42;",
+ "",
+ "import com.example.deps43.Deps43;",
+ "import java.lang.System;",
+ "import java.util.Random;",
+ "",
+ "public final class Deps42 {",
+ " public static void PrintSth() {",
+ " Random rand = new Random();",
+ " int n = rand.nextInt(100);",
+ " System.out.format(\"This is method(%s) with random number(%d)\\n\", \"PrintSth\", n);",
+ " }",
+ "",
+ " public static void CallNext() {",
+ " Deps43.PrintSth();",
+ " }",
+ "}");
+
+ private static final String DEPS_CLASS_EXTRA_CONTENT = joinLines(
+ "package com.example.deps42;",
+ "",
+ "import java.lang.System;",
+ "import java.util.Random;",
+ "",
+ "public final class Deps42 {",
+ " public static void PrintSth() {",
+ " Random rand = new Random();",
+ " int n = rand.nextInt(100);",
+ " System.out.format(\"This is method(%s) with random number(%d)\\n\", \"PrintSth\", n);",
+ " }",
+ "",
+ " public static void PrintSthElse() {",
+ " Random rand = new Random();",
+ " int n = rand.nextInt(100);",
+ " System.out.format(\"This is method(%s) with random number(%d)\\n\","
+ + " \"PrintSthElse\", n);",
+ " }",
+ "}");
+
+ private static final String MAIN_CLASS_WITH_DEPS_CONTENT = joinLines(
+ "package com.example.generated;",
+ "",
+ "import com.example.deps1.Deps1;",
+ "import com.example.deps2.Deps2;",
+ "import com.example.deps3.Deps3;",
+ "import java.lang.String;",
+ "",
+ "public final class Main {",
+ " public static void main(String[] args) {",
+ " Deps1.PrintSth();",
+ " Deps2.PrintSth();",
+ " Deps3.PrintSth();",
+ " }",
+ "}");
+
+ @Rule public TemporaryFolder folder = new TemporaryFolder();
+
+ @Test
+ public void testWriteRandomClassToDir() throws IOException {
+ Path dir = folder.newFolder("WriteRandomClassToDir").toPath();
+ JavaCodeGeneratorHelper.writeRandomClassToDir(false, "ClassName", "com.package.name", dir);
+
+ Path javaFile = dir.resolve("com/package/name/ClassName.java");
+ assertTrue(javaFile.toFile().exists());
+
+ String content = new Scanner(javaFile).useDelimiter("\\Z").next();
+ assertEquals(RANDOM_CLASS_CONTENT, content);
+ }
+
+ @Test
+ public void testWriteRandomClassToDirExtraMethod() throws IOException {
+ Path dir = folder.newFolder("WriteRandomClassToDirExtraMethod").toPath();
+ JavaCodeGeneratorHelper.writeRandomClassToDir(true, "ClassNameExtra", "com.package.name", dir);
+
+ Path javaFile = dir.resolve("com/package/name/ClassNameExtra.java");
+ assertTrue(javaFile.toFile().exists());
+
+ String content = new Scanner(javaFile).useDelimiter("\\Z").next();
+ assertEquals(RANDOM_CLASS_EXTRA_CONTENT, content);
+ }
+
+ @Test
+ public void testWriteMainClassToDir() throws IOException {
+ Path dir = folder.newFolder("WriteMainClassToDir").toPath();
+ JavaCodeGeneratorHelper.writeMainClassToDir("com.package.name", dir);
+
+ Path javaFile = dir.resolve("com/package/name/Main.java");
+ assertTrue(javaFile.toFile().exists());
+
+ String content = new Scanner(javaFile).useDelimiter("\\Z").next();
+ assertEquals(MAIN_CLASS_CONTENT, content);
+ }
+
+ @Test
+ public void testBuildFileWithNextDeps() throws IOException {
+ Path dir = folder.newFolder("BuildFileWithNextDeps").toPath();
+ Files.createDirectories(dir);
+ JavaCodeGeneratorHelper.buildFileWithNextDeps(42, "<this is deps>", dir);
+
+ Path buildFile = dir.resolve("BUILD");
+ assertTrue(buildFile.toFile().exists());
+
+ String content = new Scanner(buildFile).useDelimiter("\\Z").next();
+ assertEquals(DEPS_BUILD_FILE_CONTENT, content);
+ }
+
+ @Test
+ public void testBuildFileWithMainClass() throws IOException {
+ Path dir = folder.newFolder("BuildFileWithMainClass").toPath();
+ Files.createDirectories(dir);
+ JavaCodeGeneratorHelper.buildFileWithMainClass("Target", "<this is deps>", dir);
+
+ Path buildFile = dir.resolve("BUILD");
+ assertTrue(buildFile.toFile().exists());
+
+ String content = new Scanner(buildFile).useDelimiter("\\Z").next();
+ assertEquals(TARGET_BUILD_FILE_CONTENT, content);
+ }
+
+ @Test
+ public void testTargetWithNextHelper() throws IOException {
+ Path dir = folder.newFolder("TargetWithNextHelper").toPath();
+ JavaCodeGeneratorHelper.targetWithNextHelper(42, true, dir);
+
+ Path javaFile = dir.resolve("com/example/deps42/Deps42.java");
+ assertTrue(javaFile.toFile().exists());
+
+ String content = new Scanner(javaFile).useDelimiter("\\Z").next();
+ assertEquals(DEPS_CLASS_CONTENT, content);
+ }
+
+ @Test
+ public void testTargetWithNextExtraHelper() throws IOException {
+ Path dir = folder.newFolder("TargetWithNextHelperExtra").toPath();
+ JavaCodeGeneratorHelper.targetWithNextExtraHelper(42, false, dir);
+
+ Path javaFile = dir.resolve("com/example/deps42/Deps42.java");
+ assertTrue(javaFile.toFile().exists());
+
+ String content = new Scanner(javaFile).useDelimiter("\\Z").next();
+ assertEquals(DEPS_CLASS_EXTRA_CONTENT, content);
+ }
+
+ @Test
+ public void testParallelDepsMainClassHelper() throws IOException {
+ Path dir = folder.newFolder("ParallelDepsMainClassHelper").toPath();
+ JavaCodeGeneratorHelper.parallelDepsMainClassHelper(4, dir);
+
+ Path javaFile = dir.resolve("com/example/generated/Main.java");
+ assertTrue(javaFile.toFile().exists());
+
+ String content = new Scanner(javaFile).useDelimiter("\\Z").next();
+ assertEquals(MAIN_CLASS_WITH_DEPS_CONTENT, content);
+ }
+
+ private static String joinLines(String... lines) {
+ return Joiner.on("\n").join(lines);
+ }
+}
diff --git a/src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/JavaCodeGeneratorTest.java b/src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/JavaCodeGeneratorTest.java
new file mode 100644
index 0000000000..f135b1fb77
--- /dev/null
+++ b/src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/JavaCodeGeneratorTest.java
@@ -0,0 +1,124 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.benchmark.codegenerator;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertNotNull;
+
+import com.google.common.collect.ImmutableSet;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test for {@link JavaCodeGenerator}. */
+@RunWith(JUnit4.class)
+public class JavaCodeGeneratorTest {
+
+ @Rule public TemporaryFolder folder = new TemporaryFolder();
+
+ @Test
+ public void testGenerateNewProject() throws IOException {
+ File createdFolder = folder.newFolder("GenerateNewProject");
+ Path dir = createdFolder.toPath();
+ JavaCodeGenerator.generateNewProject(dir.toString(), true, true, true, true);
+
+ // Check dir contains 4 project directories
+ File[] filesList = dir.toFile().listFiles();
+ assertNotNull(filesList);
+ ImmutableSet<String> filenames = fileArrayToImmutableSet(filesList);
+ assertThat(filenames).containsExactly(
+ JavaCodeGenerator.TARGET_A_FEW_FILES,
+ JavaCodeGenerator.TARGET_LONG_CHAINED_DEPS,
+ JavaCodeGenerator.TARGET_MANY_FILES,
+ JavaCodeGenerator.TARGET_PARALLEL_DEPS);
+
+ // Target 1: a few files
+ checkProjectPathContains(dir, JavaCodeGenerator.TARGET_A_FEW_FILES);
+ checkSimpleTarget(
+ dir, JavaCodeGenerator.TARGET_A_FEW_FILES, JavaCodeGenerator.SIZE_A_FEW_FILES);
+
+ // Target 2: many files
+ checkProjectPathContains(dir, JavaCodeGenerator.TARGET_MANY_FILES);
+ checkSimpleTarget(dir, JavaCodeGenerator.TARGET_MANY_FILES, JavaCodeGenerator.SIZE_MANY_FILES);
+
+ // Target 3: long chained deps
+ checkProjectPathContains(dir, JavaCodeGenerator.TARGET_LONG_CHAINED_DEPS);
+ checkDepsTarget(
+ dir, JavaCodeGenerator.TARGET_LONG_CHAINED_DEPS, JavaCodeGenerator.SIZE_LONG_CHAINED_DEPS);
+
+ // Target 4: parallel deps
+ checkProjectPathContains(dir, JavaCodeGenerator.TARGET_PARALLEL_DEPS);
+ checkDepsTarget(
+ dir, JavaCodeGenerator.TARGET_PARALLEL_DEPS, JavaCodeGenerator.SIZE_PARALLEL_DEPS);
+ }
+
+ private static ImmutableSet<String> fileArrayToImmutableSet(File[] files) {
+ ImmutableSet.Builder<String> builder = ImmutableSet.builder();
+ for (File file : files) {
+ builder.add(file.getName());
+ }
+ return builder.build();
+ }
+
+ private static void checkProjectPathContains(Path root, String targetName) {
+ // Check project dir contains BUILD and com
+ File[] filesList = root.resolve(targetName).toFile().listFiles();
+ assertNotNull(filesList);
+ ImmutableSet<String> filenames = fileArrayToImmutableSet(filesList);
+ assertThat(filenames).containsExactly("BUILD", "com");
+
+ // Check project dir contains com/example
+ filesList = root.resolve(targetName).resolve("com").toFile().listFiles();
+ assertNotNull(filesList);
+ filenames = fileArrayToImmutableSet(filesList);
+ assertThat(filenames).containsExactly("example");
+ }
+
+ private static void checkSimpleTarget(Path root, String targetName, int targetSize) {
+ // Check Java files
+ File[] filesList =
+ root.resolve(targetName).resolve("com/example/generated").toFile().listFiles();
+ assertNotNull(filesList);
+ ImmutableSet<String> filenames = fileArrayToImmutableSet(filesList);
+ ImmutableSet.Builder<String> randomClassNames = ImmutableSet.builder();
+ randomClassNames.add("Main.java");
+ for (int i = 0; i < targetSize; ++i) {
+ randomClassNames.add("RandomClass" + i + ".java");
+ }
+ assertThat(filenames).containsExactlyElementsIn(randomClassNames.build());
+ }
+
+ private static void checkDepsTarget(Path root, String targetName, int targetSize) {
+ // Check Java files
+ for (int i = 1; i < targetSize; ++i) {
+ File[] filesList =
+ root.resolve(targetName).resolve("com/example/deps" + i).toFile().listFiles();
+ assertNotNull(filesList);
+ ImmutableSet<String> filenames = fileArrayToImmutableSet(filesList);
+ assertThat(filenames).containsExactly("Deps" + i + ".java");
+ }
+ File[] filesList =
+ root.resolve(targetName).resolve("com/example/generated").toFile().listFiles();
+ assertNotNull(filesList);
+ ImmutableSet<String> filenames = fileArrayToImmutableSet(filesList);
+ assertThat(filenames).containsExactly("Main.java");
+ }
+}
diff --git a/src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/MainTest.java b/src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/MainTest.java
new file mode 100644
index 0000000000..ef47492dbb
--- /dev/null
+++ b/src/tools/benchmark/javatests/com/google/devtools/build/benchmark/codegenerator/MainTest.java
@@ -0,0 +1,92 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.benchmark.codegenerator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import com.google.devtools.common.options.OptionsParsingException;
+import java.io.IOException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test for {@link Main}. */
+@RunWith(JUnit4.class)
+public class MainTest {
+
+ @Test
+ public void testParseArgsEmpty() throws OptionsParsingException, IOException {
+ try {
+ Main.parseArgs(new String[]{});
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertEquals("--output_dir should not be empty.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testParseArgsWrongMode() throws IOException {
+ try {
+ Main.parseArgs(new String[]{"--modify=mango"});
+ fail("Should throw OptionsParsingException");
+ } catch (OptionsParsingException e) {
+ assertEquals(
+ "While parsing option --modify=mango: 'mango' is not a boolean", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testParseArgsNoOutputDir() throws OptionsParsingException, IOException {
+ try {
+ Main.parseArgs(new String[]{"--modify"});
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertEquals("--output_dir should not be empty.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testParseArgsOutputDirNonExists() throws OptionsParsingException, IOException {
+ try {
+ Main.parseArgs(new String[]{"--modify", "--output_dir=mango"});
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertEquals("--output_dir (mango) does not contain code for modification.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testParseArgsNoType() throws OptionsParsingException, IOException {
+ try {
+ Main.parseArgs(new String[]{"--output_dir=mango"});
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertEquals("No type of package is specified.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testParseArgsCorrect() throws OptionsParsingException, IOException {
+ GeneratorOptions opt = Main.parseArgs(
+ new String[]{"--modify=false", "--output_dir=mango", "--a_few_files", "--parallel_deps"});
+ assertEquals(opt.modificationMode, false);
+ assertEquals(opt.outputDir, "mango");
+ assertEquals(opt.aFewFiles, true);
+ assertEquals(opt.manyFiles, false);
+ assertEquals(opt.longChainedDeps, false);
+ assertEquals(opt.parallelDeps, true);
+ }
+}