/*
* 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.classloading;
import jetbrains.mps.CoreMpsTest;
import jetbrains.mps.core.tool.environment.util.SetLibraryContributor;
import jetbrains.mps.library.LibraryInitializer;
import jetbrains.mps.library.contributor.LibDescriptor;
import jetbrains.mps.library.contributor.LibraryContributor;
import jetbrains.mps.smodel.MPSModuleRepository;
import jetbrains.mps.smodel.ModelAccessHelper;
import jetbrains.mps.tool.environment.EnvironmentConfig;
import jetbrains.mps.tool.environment.MpsEnvironment;
import jetbrains.mps.util.IterableUtil;
import jetbrains.mps.util.PathManager;
import jetbrains.mps.vfs.impl.IoFileSystem;
import org.apache.log4j.LogManager;
import org.jetbrains.mps.openapi.module.SModuleReference;
import org.jetbrains.mps.openapi.module.SRepository;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
/**
* Internal consistency check of module dependencies between different layers of MPS hierarchy:
* core, workbench and plugin
*
*
* TODO rewrite using the standard way to collect multiple errors
*/
public class ProjectMPSDependenciesTest extends CoreMpsTest {
private static final org.apache.log4j.Logger LOG = LogManager.getLogger(ProjectMPSDependenciesTest.class);
@Rule
public final ErrorCollector myErrors = new ErrorCollector();
@BeforeClass
public static void beforeTest(){
MpsEnvironment.getOrCreate(EnvironmentConfig.defaultConfig());
}
@Test
public void depsAreValid() {
LOG.info("ADDING CORE CONTRIBUTORS : currently " + getModulesCount() + " modules");
addContributorWithPaths(getCorePaths());
checkDeps("CORE");
LOG.info("ADDING WORKBENCH CONTRIBUTORS : currently " + getModulesCount() + " modules");
addContributorWithPaths(Collections.singletonList(PathManager.getWorkbenchPath()));
checkDeps("WORKBENCH");
LOG.info("ADDING PLUGINS CONTRIBUTORS : currently " + getModulesCount() + " modules");
addContributorWithPaths(Collections.singletonList(PathManager.getPreInstalledPluginsPath()));
LOG.info("FINISHED : currently " + getModulesCount() + " modules");
checkDeps("PLUGIN");
}
private int getModulesCount() {
final SRepository repository = getRepository();
return new ModelAccessHelper(repository).runReadAction(() -> IterableUtil.asCollection(repository.getModules()).size());
}
private Collection<String> getCorePaths() {
Collection<String> bootstrapPaths = new ArrayList<String>(PathManager.getBootstrapPaths());
bootstrapPaths.add(PathManager.getLanguagesPath());
return Collections.unmodifiableCollection(bootstrapPaths);
}
private void addContributorWithPaths(Iterable<? extends String> paths) {
Set<LibDescriptor> libraryPaths = new LinkedHashSet<LibDescriptor>();
for (String path : paths) {
libraryPaths.add(new LibDescriptor(IoFileSystem.INSTANCE.getFile(path)));
}
addContributor(SetLibraryContributor.fromSet("Library paths", libraryPaths));
}
private void addContributor(LibraryContributor contributor) {
LibraryInitializer.getInstance().load(Collections.singletonList(contributor));
}
private void checkDeps(final String levelIndicator) {
final ModulesWatcher modulesWatcher = getModulesWatcher();
final SRepository repository = getRepository();
repository.getModelAccess().runWriteAction(() -> {
Map<SModuleReference, String> invalidModules2Problems = modulesWatcher.findInvalidModulesProblems();
for (SModuleReference mRef : invalidModules2Problems.keySet()) {
final String msg = String.format("Invalid dependencies (%s) for module %s: %s", levelIndicator, mRef.getModuleName(), invalidModules2Problems.get(mRef));
myErrors.addError(new AssertionError(msg));
}
});
}
private ModulesWatcher getModulesWatcher() {
return ClassLoaderManager.getInstance().getModulesWatcher();
}
private SRepository getRepository() {
return ENV.getPlatform().findComponent(MPSModuleRepository.class);
}
}