/* * Copyright 2003-2013 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.classloading; import jetbrains.mps.CoreMpsTest; import jetbrains.mps.lang.typesystem.runtime.IHelginsDescriptor; import jetbrains.mps.module.ReloadableModule; import jetbrains.mps.openapi.editor.descriptor.EditorAspectDescriptor; import jetbrains.mps.project.Project; import jetbrains.mps.smodel.Language; import jetbrains.mps.smodel.language.LanguageRegistry; import jetbrains.mps.smodel.language.LanguageRuntime; import jetbrains.mps.smodel.runtime.BehaviorAspectDescriptor; import jetbrains.mps.smodel.runtime.ConstraintsAspectDescriptor; import jetbrains.mps.smodel.runtime.ILanguageAspect; import jetbrains.mps.smodel.runtime.MakeAspectDescriptor; import jetbrains.mps.smodel.runtime.StructureAspectDescriptor; import jetbrains.mps.util.PathManager; import org.jetbrains.mps.openapi.module.SModule; import org.junit.Test; import java.io.File; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.TreeMap; import static org.junit.Assert.fail; public class ProjectMPSClassLoadingTest extends CoreMpsTest { private static final Set<String> IGNORE_LIST = new LinkedHashSet<String>(Arrays.asList("jetbrains.mps.samples.xmlPersistence [solution]", "TestBehaviorReflective [solution]")); private Map<String, String> myModuleNamesToErrors = new TreeMap<String, String>(); private Project project; @Test public void classesAreLoaded() { project = openProject(new File(PathManager.getHomePath())); doTest(); project.dispose(); } @Test public void classesAreLoadedStress() { project = openProject(new File(PathManager.getHomePath())); project.getRepository().addRepositoryListener(ModulesReloadTestStress.CRAZY_LISTENER); doTest(); project.getRepository().removeRepositoryListener(ModulesReloadTestStress.CRAZY_LISTENER); project.dispose(); } private void doTest() { project.getModelAccess().runReadAction(new Runnable() { @Override public void run() { for (SModule module : project.getRepository().getModules()) { checkModule(module); } if (!myModuleNamesToErrors.isEmpty()) { System.err.println("Some class loading problems for modules:"); for (String moduleName : myModuleNamesToErrors.keySet()) { System.err.println(moduleName + " ::: " + myModuleNamesToErrors.get(moduleName)); } fail(); } } }); } private boolean checkModule(SModule module) { if (isIgnored(module.toString())) return true; ClassLoaderManager classLoaderManager = ClassLoaderManager.getInstance(); if (classLoaderManager.canLoad(module)) { ReloadableModule reloadableModule = (ReloadableModule) module; if (reloadableModule.willLoad() && reloadableModule.getClassLoader() == null) { myModuleNamesToErrors.put(module.toString(), "No class loader for the module"); return false; } } if (module instanceof Language) try { Language language = (Language) module; checkIsRegistered(language); tryLoadDescriptors(language); } catch (AssertionFailedException e) { myModuleNamesToErrors.put(module.toString(), e.getMsg()); return false; } return true; } private boolean isIgnored(String module) { for (String ignored : IGNORE_LIST) { if (module.equals(ignored)) return true; } return false; } private void checkIsRegistered(Language language) throws AssertionFailedException { if (null == LanguageRegistry.getInstance().getLanguage(language)) throw new AssertionFailedException("The language is not registered in the LanguageRegistry"); } private void tryLoadDescriptors(Language language) throws AssertionFailedException { LanguageRuntime languageRuntime = LanguageRegistry.getInstance().getLanguage(language); assert languageRuntime != null; reachStructure(languageRuntime); reachBehaviour(languageRuntime); reachMake(languageRuntime); reachTypeSystem(languageRuntime); reachConstraints(languageRuntime); reachEditor(languageRuntime); languageRuntime.getAspect(ConstraintsAspectDescriptor.class); } private void reachStructure(LanguageRuntime languageRuntime) throws AssertionFailedException { reachAspect(languageRuntime, StructureAspectDescriptor.class); } private void reachBehaviour(LanguageRuntime languageRuntime) throws AssertionFailedException { reachAspect(languageRuntime, BehaviorAspectDescriptor.class); } private void reachMake(LanguageRuntime languageRuntime) throws AssertionFailedException { reachAspect(languageRuntime, MakeAspectDescriptor.class); } private void reachTypeSystem(LanguageRuntime languageRuntime) throws AssertionFailedException { reachAspect(languageRuntime, IHelginsDescriptor.class); } private void reachConstraints(LanguageRuntime languageRuntime) throws AssertionFailedException { reachAspect(languageRuntime, ConstraintsAspectDescriptor.class); } private void reachEditor(LanguageRuntime languageRuntime) throws AssertionFailedException { reachAspect(languageRuntime, EditorAspectDescriptor.class); } private void reachAspect(LanguageRuntime languageRuntime, Class<? extends ILanguageAspect> aspect) throws AssertionFailedException { try { languageRuntime.getAspect(aspect); } catch (Throwable t) { throw new AssertionFailedException("Exception while getting the aspect descriptor : " + aspect); } } private static class AssertionFailedException extends Exception { private final String myMsg; public AssertionFailedException(String msg) { super(msg); myMsg = msg; } public String getMsg() { return myMsg; } } }