blob: 24d3deddbd321845da1eeb77c784f77401be9079 [file] [log] [blame]
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* 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 org.jetbrains.ether;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.util.io.FileSystemUtil;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Processor;
import org.jetbrains.jps.builders.BuildResult;
import org.jetbrains.jps.builders.CompileScopeTestBuilder;
import org.jetbrains.jps.builders.JpsBuildTestCase;
import org.jetbrains.jps.builders.impl.logging.ProjectBuilderLoggerBase;
import org.jetbrains.jps.builders.logging.BuildLoggingManager;
import org.jetbrains.jps.cmdline.ProjectDescriptor;
import org.jetbrains.jps.model.JpsDummyElement;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
import org.jetbrains.jps.model.java.JpsJavaLibraryType;
import org.jetbrains.jps.model.library.JpsLibrary;
import org.jetbrains.jps.model.library.JpsOrderRootType;
import org.jetbrains.jps.model.library.sdk.JpsSdk;
import org.jetbrains.jps.model.module.JpsModule;
import org.jetbrains.jps.model.serialization.PathMacroUtil;
import org.jetbrains.jps.util.JpsPathUtil;
import java.io.*;
/**
* @author db
* @since 26.07.11
*/
public abstract class IncrementalTestCase extends JpsBuildTestCase {
private final String groupName;
private File baseDir;
private File workDir;
private JpsSdk<JpsDummyElement> myJdk;
@SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
protected IncrementalTestCase(final String name) {
setName(name);
groupName = name;
}
@Override
protected void setUp() throws Exception {
super.setUp();
baseDir = new File(PathManagerEx.getTestDataPath(getClass()) + File.separator + "compileServer" + File.separator + "incremental" + File.separator + groupName + File.separator + getProjectName());
workDir = FileUtil.createTempDirectory("jps-build", null);
FileUtil.copyDir(baseDir, workDir, new FileFilter() {
@Override
public boolean accept(File file) {
String name = file.getName();
return !name.endsWith(".new") && !name.endsWith(".delete");
}
});
String outputPath = getAbsolutePath("out");
JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myProject).setOutputUrl(JpsPathUtil.pathToUrl(outputPath));
}
@Override
protected File doGetProjectDir() throws IOException {
return workDir;
}
protected String getUrl(String pathRelativeToProjectRoot) {
return JpsPathUtil.pathToUrl(getAbsolutePath(pathRelativeToProjectRoot));
}
@Override
public String getAbsolutePath(final String pathRelativeToProjectRoot) {
return FileUtil.toSystemIndependentName(workDir.getAbsolutePath()) + "/" + pathRelativeToProjectRoot;
}
@Override
protected void tearDown() throws Exception {
try {
super.tearDown();
}
finally {
FileUtil.delete(workDir);
}
}
private void modify(int stage) {
final String removedSuffix = stage == 0? ".remove" : ".remove" + stage;
final String newSuffix = stage == 0? ".new" : ".new" + stage;
FileUtil.processFilesRecursively(baseDir, new Processor<File>() {
@Override
public boolean process(File file) {
if (file.getName().endsWith(removedSuffix)) {
FileUtil.delete(getTargetFile(file, removedSuffix));
}
return true;
}
});
final long[] timestamp = {0};
FileUtil.processFilesRecursively(baseDir, new Processor<File>() {
@Override
public boolean process(File file) {
try {
if (file.getName().endsWith(newSuffix)) {
File targetFile = getTargetFile(file, newSuffix);
FileUtil.copyContent(file, targetFile);
timestamp[0] = Math.max(timestamp[0], FileSystemUtil.lastModified(targetFile));
}
}
catch (IOException e) {
throw new RuntimeException(e);
}
return true;
}
});
sleepUntil(timestamp[0]);
}
private File getTargetFile(File sourceFile, final String suffix) {
String path = FileUtil.getRelativePath(baseDir, sourceFile);
assertNotNull(path);
if (!path.contains(File.separator)) {
path = "src" + File.separator + path;
}
return new File(workDir, StringUtil.trimEnd(path, suffix));
}
public BuildResult doTest() {
setupInitialProject();
return doTestBuild(1);
}
protected void setupInitialProject() {
if (new File(workDir, PathMacroUtil.DIRECTORY_STORE_NAME).exists()) {
getOrCreateJdk();
loadProject(workDir.getAbsolutePath());
}
else {
addModule();
}
}
protected JpsModule addModule() {
return addModule(StringUtil.capitalize(getProjectName()), "src");
}
protected JpsModule addModule(final String moduleName, final String srcRootRelativePath) {
String srcPath = getAbsolutePath(srcRootRelativePath);
return addModule(moduleName, new String[]{srcPath}, null, null, getOrCreateJdk());
}
protected BuildResult doTestBuild(int makesCount) {
StringBuilder log = new StringBuilder();
String rootPath = FileUtil.toSystemIndependentName(workDir.getAbsolutePath()) + "/";
final ProjectDescriptor pd = createProjectDescriptor(new BuildLoggingManager(new StringProjectBuilderLogger(rootPath, log)));
try {
doBuild(pd, CompileScopeTestBuilder.rebuild().allModules()).assertSuccessful();
BuildResult result = null;
for (int idx = 0; idx < makesCount; idx++) {
modify(idx);
result = doBuild(pd, CompileScopeTestBuilder.make().allModules());
}
assertNotNull(result);
final ByteArrayOutputStream makeDump = new ByteArrayOutputStream();
if (result.isSuccessful()) {
final PrintStream stream = new PrintStream(makeDump);
try {
pd.dataManager.getMappings().toStream(stream);
}
finally {
stream.close();
}
}
makeDump.close();
File logFile = new File(baseDir.getAbsolutePath() + ".log");
if (!logFile.exists()) {
logFile = new File(baseDir, "build.log");
}
final String expected = StringUtil.convertLineSeparators(FileUtil.loadFile(logFile));
final String actual = log.toString();
assertEquals(expected, actual);
if (result.isSuccessful()) {
doBuild(pd, CompileScopeTestBuilder.rebuild().allModules()).assertSuccessful();
final ByteArrayOutputStream rebuildDump = new ByteArrayOutputStream();
final PrintStream stream = new PrintStream(rebuildDump);
try {
pd.dataManager.getMappings().toStream(stream);
}
finally {
stream.close();
}
rebuildDump.close();
assertEquals(rebuildDump.toString(), makeDump.toString());
}
return result;
}
catch (IOException e) {
throw new RuntimeException(e);
}
finally {
pd.release();
}
}
protected JpsSdk<JpsDummyElement> getOrCreateJdk() {
if (myJdk == null) {
myJdk = addJdk("IDEA jdk");
}
return myJdk;
}
protected JpsLibrary addLibrary(final String jarPath) {
JpsLibrary library = myProject.addLibrary("l", JpsJavaLibraryType.INSTANCE);
library.addRoot(new File(getAbsolutePath(jarPath)), JpsOrderRootType.COMPILED);
return library;
}
protected void addTestRoot(JpsModule module, final String testRootRelativePath) {
module.addSourceRoot(getUrl(testRootRelativePath), JavaSourceRootType.TEST_SOURCE);
}
private static class StringProjectBuilderLogger extends ProjectBuilderLoggerBase {
private final String myRoot;
private StringBuilder myLog;
private StringProjectBuilderLogger(String root, StringBuilder log) {
myRoot = root;
myLog = log;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
protected void logLine(String line) {
myLog.append(StringUtil.trimStart(line, myRoot)).append('\n');
}
}
}