/*
* Copyright 2003-2015 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 jetbrains.mps.jps.make.tests.inc;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testFramework.TestDataFile;
import jetbrains.mps.jps.make.tests.MpsJpsModelsEnvironmentTestCase;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildResult;
import org.jetbrains.jps.builders.CompileScopeTestBuilder;
import org.jetbrains.jps.builders.impl.logging.ProjectBuilderLoggerBase;
import org.jetbrains.jps.builders.logging.BuildLoggingManager;
import org.jetbrains.jps.cmdline.ProjectDescriptor;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.List;
/**
* Intended to check the incremental make in idea+mps build procedure.
* Uses a special logger to validate the make procedure
*/
public abstract class MpsIncrementalMakeTestCase extends MpsJpsModelsEnvironmentTestCase {
private ProjectDescriptor myProjectDescriptor;
@NotNull
protected abstract BuildResult doTestIncrementalBuild(@NotNull ProjectDescriptor projectDescriptor);
@NonNls
@NotNull
protected abstract String getLogFileName();
/**
* please implement the {@link #doTestIncrementalBuild} and {@link #getLogFileName}
*/
@Override
protected void doTest(@TestDataFile @NonNls @NotNull String inputTestFileName) {
setUpEnvironment(inputTestFileName);
doTestIncremental(getTestName(inputTestFileName));
}
private BuildResult doTestIncremental(String testName) {
final String testDataFilePath = getTestLogFilePath(testName);
final StringProjectBuilderLogger projectLogger = createProjectLogger();
myProjectDescriptor = createProjectDescriptor(new BuildLoggingManager(projectLogger));
try {
BuildResult result = doTestIncrementalBuild(myProjectDescriptor);
final String expectedLog = loadExpectedFileContent(testDataFilePath);
assertLogAsExpected(projectLogger.getLog(), expectedLog);
if (result.isSuccessful()) {
assertMakeDumpIsValid();
}
return result;
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
myProjectDescriptor.release();
myProjectDescriptor = null;
}
}
private String getTestLogFilePath(String testName) {
return getTestDataFilePath(testName, getLogFileName());
}
private File getProjectDir() {
return getOrCreateProjectDir();
}
private StringProjectBuilderLogger createProjectLogger() {
final File outputDir = getProjectDir();
return new StringProjectBuilderLogger(Arrays.asList(outputDir, myDataStorageRoot));
}
private void assertMakeDumpIsValid() throws IOException {
String makeDumpStr = getMappings().toString();
rebuildAll();
String rebuildDumpStr = getMappings().toString();
// FIXME enable, some problems with touch model test
// assertEquals(rebuildDumpStr, makeDumpStr);
}
private void assertLogAsExpected(final String actual, final String expected) throws IOException {
assertEquals(expected, actual);
}
private String loadExpectedFileContent(final String pathToExpectedFile) throws IOException {
File expectedFile = new File(pathToExpectedFile);
assertExists(expectedFile);
return StringUtil.convertLineSeparators(FileUtil.loadFile(expectedFile));
}
private ByteArrayOutputStream getMappings() throws IOException {
final ByteArrayOutputStream makeDump = new ByteArrayOutputStream();
final PrintStream stream = new PrintStream(makeDump);
try {
myProjectDescriptor.dataManager.getMappings().toStream(stream);
}
finally {
stream.close();
}
makeDump.close();
return makeDump;
}
@Override
protected BuildResult doBuild(CompileScopeTestBuilder scope) {
return doBuild(myProjectDescriptor, scope);
}
private static class StringProjectBuilderLogger extends ProjectBuilderLoggerBase {
private final List<File> myRoots;
private final StringBuilder myLog = new StringBuilder();
public StringProjectBuilderLogger(List<File> roots) {
myRoots = roots;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
protected void logLine(String line) {
myLog.append(tryToTrim(line)).append('\n');
}
/**
* @return trimmed path if it is a path indeed
*/
@NotNull
private String tryToTrim(String path) {
for (File root : myRoots) {
String rootPrefix = convertPartToPrefix(root.getAbsolutePath());
if (FileUtil.startsWith(path, rootPrefix)) {
return StringUtil.trimStart(path, rootPrefix);
}
}
return path;
}
private String convertPartToPrefix(String absolutePath) {
return FileUtil.toSystemIndependentName(absolutePath) + "/";
}
public String getLog() {
return myLog.toString();
}
}
}