| /* |
| * 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'); |
| } |
| } |
| } |