// 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 java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; /** Create 4 types of Java project, or modify existing ones. */ public class JavaCodeGenerator extends CodeGenerator { private static final int SIZE_A_FEW_FILES = 10; private static final int SIZE_MANY_FILES = 1000; private static final int SIZE_LONG_CHAINED_DEPS = 20; private static final int SIZE_PARALLEL_DEPS = 20; private static final String DIR_SUFFIX = "/java"; @Override public String getDirSuffix() { return DIR_SUFFIX; } @Override public int getSizeAFewFiles() { return SIZE_A_FEW_FILES; } @Override public int getSizeManyFiles() { return SIZE_MANY_FILES; } @Override public int getSizeLongChainedDeps() { return SIZE_LONG_CHAINED_DEPS; } @Override public int getSizeParallelDeps() { return SIZE_PARALLEL_DEPS; } /** Target type 1/2: Create targets with some files */ @Override 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(projectPath.getFileName().toString(), "", projectPath); } catch (IOException e) { System.err.println("Error creating target with some files: " + e.getMessage()); } } /** Target type 1/2: Modify targets with some files */ @Override void modifyTargetWithSomeFiles(Path projectPath) { File dir = projectPath.toFile(); if (directoryNotExists(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) */ @Override 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) */ @Override void modifyTargetWithLongChainedDeps(Path projectPath) { File dir = projectPath.toFile(); if (directoryNotExists(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) */ @Override 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) */ @Override void modifyTargetWithParallelDeps(Path projectPath) { File dir = projectPath.toFile(); if (directoryNotExists(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 directoryNotExists(File file) { return !(file.exists() && file.isDirectory()); } }