/* * Copyright 2003-2016 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.generator.test; import jetbrains.mps.generator.GenerationOptions; import jetbrains.mps.generator.GenerationStatus; import jetbrains.mps.generator.generationTypes.StreamHandler; import jetbrains.mps.generator.impl.IncrementalGenerationHandler; import jetbrains.mps.generator.impl.IncrementalGenerationHandler.IncrementalReporter; import jetbrains.mps.generator.impl.cache.IntermediateCacheHelper; import jetbrains.mps.generator.impl.dependencies.GenerationDependencies; import jetbrains.mps.generator.impl.plan.GenerationPlan; import jetbrains.mps.generator.impl.plan.PlanSignature; import jetbrains.mps.messages.LogHandler; import jetbrains.mps.project.facets.JavaModuleFacet; import jetbrains.mps.text.TextGenResult; import jetbrains.mps.text.TextGeneratorEngine; import jetbrains.mps.textgen.trace.TraceInfoCache; import jetbrains.mps.util.FileUtil; import jetbrains.mps.util.IStatus; import jetbrains.mps.util.JDOMUtil; import jetbrains.mps.util.Status; import jetbrains.mps.util.annotation.ToRemove; import jetbrains.mps.util.performance.IPerformanceTracer.NullPerformanceTracer; import jetbrains.mps.vfs.IFile; import org.apache.log4j.Logger; import org.jdom.Document; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.module.SRepository; import org.junit.Assert; import java.io.IOException; import java.io.InputStreamReader; import java.io.StringWriter; import java.util.HashMap; import java.util.Map; /** * Records generation results as Map<String,String> * <p/> * Evgeny Gryaznov, Oct 4, 2010 */ @ToRemove(version = 3.2) public class IncrementalTestGenerationHandler { private final Map<String, String> generatedContent = new HashMap<String, String>(); private final SRepository myRepository; private Map<String, String> existingContent; private IFile myFilesDir; private int timesCalled = 0; private boolean myCheckIncremental = false; private GenerationDependencies myLastDependencies; private GenerationOptions myGenOptions; public IncrementalTestGenerationHandler(SRepository repository) { myRepository = repository; } public IncrementalTestGenerationHandler(SRepository repository, Map<String, String> existingContent) { myRepository = repository; this.existingContent = existingContent; } public void checkIncremental(GenerationOptions op) { myGenOptions = op; myCheckIncremental = true; } public GenerationDependencies getLastDependencies() { return myLastDependencies; } public Map<String, String> getGeneratedContent() { return generatedContent; } public Map<String, String> getExistingContent() { if (existingContent == null) { existingContent = new HashMap<String, String>(); collectExistingContent(existingContent); } return existingContent; } private void collectExistingContent(Map<String, String> existingContent) { if (myFilesDir != null) { for (IFile f : myFilesDir.getChildren()) { try { if (f.isDirectory() || f.getName().equals(TraceInfoCache.TRACE_FILE_NAME)) continue; if (f.getName().endsWith(".png")) continue; // temp fix: icons are generated in another facet String s = FileUtil.read(new InputStreamReader(f.openInputStream(), FileUtil.DEFAULT_CHARSET)); existingContent.put(f.getName(), s); } catch (IOException e) { throw new RuntimeException(e); } } } } public boolean handleOutput(SModel inputModel, GenerationStatus status) { myLastDependencies = null; IFile targetDir = inputModel.getModule().getFacet(JavaModuleFacet.class).getOutputLocation(inputModel); Assert.assertTrue(status.isOk()); Assert.assertTrue("should be called once", timesCalled++ == 0); if (myCheckIncremental) { GenerationDependencies dep = status.getDependencies(); if (dep.getFromCacheCount() + dep.getSkippedCount() == 0) { final StringBuilder sb = new StringBuilder("Not optimized:\n"); IntermediateCacheHelper cacheHelper = new IntermediateCacheHelper(myGenOptions.getIncrementalStrategy(), new PlanSignature(inputModel, new GenerationPlan(inputModel)), new NullPerformanceTracer()); new IncrementalGenerationHandler(inputModel, myRepository, myGenOptions, cacheHelper, new IncrementalReporter() { @Override public void report(String message) { sb.append(message); sb.append('\n'); } }); sb.append('\n'); Assert.fail(sb.toString()); } } if (status.isOk()) { myLastDependencies = status.getDependencies(); myFilesDir = targetDir; CollectingStreamHandler toStringHandler = new CollectingStreamHandler(generatedContent, getExistingContent()); TextGeneratorEngine tgEngine = new TextGeneratorEngine(new LogHandler(Logger.getLogger(getClass()))); IStatus textGenStatus = new Status.ERROR(""); try { final TextGenResult tgr = tgEngine.generateText(status.getOutputModel()).get(); TextFacility2 tf = new TextFacility2(status, tgr); tf.prepare(); textGenStatus = tf.serializeOutcome(toStringHandler); } catch (Exception ex) { ex.printStackTrace(); Assert.fail(ex.toString()); } finally { tgEngine.shutdown(); } Assert.assertFalse(textGenStatus.isError()); } return true; } static class CollectingStreamHandler implements StreamHandler { private final Map<String, String> myCollectedContent; private final Map<String, String> myExistingContent; public CollectingStreamHandler(@NotNull Map<String, String> content, @NotNull Map<String, String> existingContent) { myCollectedContent = content; myExistingContent = existingContent; } @Override public void saveStream(String name, String content) { myCollectedContent.put(name, content); } @Override public void saveStream(String name, Element content) { try { StringWriter writer = new StringWriter(); JDOMUtil.writeDocument(new Document(content), writer); saveStream(name, writer.toString()); } catch (IOException e) { Assert.fail(e.toString()); } } @Override public void saveStream(String name, byte[] content) { Assert.fail("byte stream is not expected"); } @Override public boolean touch(String name) { String value = myExistingContent.get(name); Assert.assertNotNull("non-existing file touched: " + value); myCollectedContent.put(name, value); return true; } } }