/******************************************************************************* * Copyright (c) 2014 Bruno Medeiros and other Contributors. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bruno Medeiros - initial API and implementation *******************************************************************************/ package dtool.engine; import static dtool.tests.MockCompilerInstalls.DEFAULT_DMD_INSTALL_BaseLocation; import static dtool.tests.MockCompilerInstalls.DEFAULT_DMD_INSTALL_EXE_PATH; import static melnorme.utilbox.core.Assert.AssertNamespace.assertFail; import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue; import java.util.HashMap; import java.util.HashSet; import melnorme.lang.tooling.BundlePath; import melnorme.lang.tooling.context.ModuleFullName; import melnorme.lang.tooling.context.ModuleSourceException; import melnorme.utilbox.core.CommonException; import melnorme.utilbox.misc.Location; import melnorme.utilbox.misc.PathUtil; import org.junit.Test; import dtool.engine.StandardLibraryResolution.MissingStandardLibraryResolution; import dtool.engine.compiler_installs.CompilerInstall.ECompilerType; public class BundleResolution_ModuleListTest extends CommonSemanticManagerTest { public static class BundleFilesChecker { protected final BundleResolution bundleRes; protected final HashMap<ModuleFullName, Location> modules; protected final HashSet<Location> moduleFiles; public BundleFilesChecker(BundleResolution bundleRes) { modules = new HashMap<>(bundleRes.getBundleModulesMap()); moduleFiles = new HashSet<>(bundleRes.getBundleModuleFiles()); this.bundleRes = bundleRes; } protected void checkEntry(String moduleFullName, String relFilePath) { checkEntry(moduleFullName, relFilePath, false); } protected void checkEntry(String moduleFullName, String relFilePath, boolean duplicateNameEntry) { Location filePath = loc(bundleRes.getBundlePath(), relFilePath); ModuleFullName key = new ModuleFullName(moduleFullName); assertAreEqual(modules.get(key), filePath); if(!duplicateNameEntry) { assertTrue(moduleFiles.contains(findResolvedModule(filePath).getModulePath())); } assertTrue(moduleFiles.remove(filePath) == !duplicateNameEntry); modules.remove(key); } public ResolvedModule findResolvedModule(Location filePath) { try { return bundleRes.findResolvedModule(filePath); } catch (ModuleSourceException e) { throw melnorme.utilbox.core.ExceptionAdapter.unchecked(e); } } protected void finalCheck() { assertTrue(modules.isEmpty()); assertTrue(moduleFiles.isEmpty()); } } public static final Location DEFAULT_DMD_INSTALL_LOCATION__StdStdio_Path = DEFAULT_DMD_INSTALL_BaseLocation.resolve_fromValid("src/phobos/std/stdio.d"); public static final Location DEFAULT_DMD_INSTALL_LOCATION__Object_Path = DEFAULT_DMD_INSTALL_BaseLocation.resolve_fromValid("src/druntime/import/object.di"); @Test public void testModuleResolving() throws Exception { testModuleResolving$(); } public void testModuleResolving$() throws Exception { ___initSemanticManager(); BundleResolution sr = sm.getUpdatedResolution(BASIC_LIB); new BundleFilesChecker(sr) { { checkEntry("basic_lib_foo", "source/basic_lib_foo.d"); checkEntry("basic_lib_pack.foo", "source/basic_lib_pack/foo.d"); finalCheck(); } }; sm.getUpdatedResolution(COMPLEX_BUNDLE); // Tests optimization, run describe only once. BundleResolution smtestSR = sm.getUpdatedResolution(SMTEST); new BundleFilesChecker(smtestSR) { { checkEntry("sm_test_foo", "src/sm_test_foo.d"); checkEntry("pack.import_pack_test", "src/pack/import_pack_test/package.d"); // Test package rule checkEntry("pack.import_pack_test.foo", "src/pack/import_pack_test/foo.d"); checkEntry("test.fooLib", "src2/test/fooLib.d"); checkEntry("modA_import_only", "src-import/modA_import_only.d"); checkEntry("nested.mod_nested_import_only", "src-import/nested/mod_nested_import_only.d"); checkEntry("mod_nested_import_only", "src-import/nested/mod_nested_import_only.d", true); finalCheck(); } }; // Test Module resolver testFindResolvedModule(SMTEST, "sm_test_foo", loc(SMTEST, "src/sm_test_foo.d")); testFindResolvedModule(SMTEST, "non_existing", (Location) null); assertEqualSet(smtestSR.findModules("test."), hashSet( "test.fooLib" )); // Test dependency bundles module resolution testFindResolvedModule(SMTEST, "basic_lib_foo", loc(BASIC_LIB, "source/basic_lib_foo.d")); assertEqualSet(smtestSR.findModules("basic_lib"), hashSet( "basic_lib_pack.foo", "basic_lib_foo" )); BundleResolution complexLibSR = sm.getUpdatedResolution(COMPLEX_LIB); assertEqualSet(complexLibSR.findModules("b"), hashSet( "basic_lib_pack.foo", "basic_lib_foo", "basic_lib2_pack.bar", "basic_lib2_foo" )); BundleResolution complexBundleSR = sm.getUpdatedResolution(COMPLEX_BUNDLE); assertEqualSet(complexBundleSR.findModules("basic_lib_pack"), hashSet( "basic_lib_pack.foo" )); testFindResolvedModule(COMPLEX_BUNDLE, "basic_lib_foo", loc(BASIC_LIB, "source/basic_lib_foo.d")); } @Test public void testStdLibResolve() throws Exception { testStdLibResolve$(); } public void testStdLibResolve$() throws Exception { ___initSemanticManager(); BundleResolution sr = sm.getUpdatedResolution(BASIC_LIB); assertTrue(sr.stdLibResolution.getCompilerType() == ECompilerType.DMD); assertTrue(sr.stdLibResolution.getLibrarySourceFolders().get(0).path.startsWith( DEFAULT_DMD_INSTALL_BaseLocation.path)); testFindResolvedModule(BASIC_LIB, "object", DEFAULT_DMD_INSTALL_LOCATION__Object_Path); testFindResolvedModule(BASIC_LIB, "std.stdio", DEFAULT_DMD_INSTALL_LOCATION__StdStdio_Path); // Test when no StdLib install is found ___initSemanticManager(new Tests_DToolServer().getSemanticManager()); ResolutionKey BASIC_LIB_NullCompilerInstall = resolutionKey(BASIC_LIB, MissingStandardLibraryResolution.NULL_COMPILER_INSTALL); sr = sm.getUpdatedResolution(BASIC_LIB_NullCompilerInstall); StandardLibraryResolution fallBackStdLibResolution = sr.stdLibResolution; assertTrue(fallBackStdLibResolution.getLibrarySourceFolders().size() == 0); assertTrue(fallBackStdLibResolution.checkIsModuleContentsStale() == false); assertTrue(fallBackStdLibResolution.checkIsModuleListStale() == false); ResolvedModule objectModule = testFindResolvedModule(sr, "object", null); assertAreEqual(objectModule.getModuleNode().compilationUnitPath, null); assertTrue(sr == sm.getStoredResolution(BASIC_LIB_NullCompilerInstall)); assertEqualSet(sr.findModules(""), hashSet( "basic_lib_pack.foo", "basic_lib_foo", "object" )); assertEqualSet(fallBackStdLibResolution.findModules(""), hashSet( "object" )); } /* ----------------- ----------------- */ public final BundlePath NOT_A_BUNDLE = bundlePath(getDubRepositoryDir(), "not_a_bundle"); @Test public void testGetResolvedModule() throws Exception { testGetResolvedModule$(); } public void testGetResolvedModule$() throws Exception { prepSMTestsWorkingDir(); sm = ___initSemanticManager(); sm.getUpdatedResolution(CommonSemanticManagerTest.resolutionKey(COMPLEX_LIB)); ResolvedModule rm = getUpdatedResolvedModule(BASIC_LIB_FOO_MODULE); assertTrue(rm.semanticContext == sm.getStoredResolution(resKey(BASIC_LIB))); BundleResolution complexLibSR = sm.getUpdatedResolution(COMPLEX_LIB); assertTrue(rm == complexLibSR.findResolvedModule(new ModuleFullName(BASIC_LIB_FOO_MODULE_Name))); assertTrue(complexLibSR.getCompilerPath().equals(DEFAULT_DMD_INSTALL_EXE_PATH)); // Test getResolvedModule for module that is not in bundle import folders. Location NOT_IN_SOURCE__MODULE = loc(BASIC_LIB, "not_source/not_source_foo.d"); rm = getUpdatedResolvedModule(NOT_IN_SOURCE__MODULE); assertTrue(rm.semanticContext != sm.getStoredResolution(resKey(BASIC_LIB))); assertEqualSet(rm.semanticContext.getBundleModuleFiles(), hashSet(NOT_IN_SOURCE__MODULE)); assertEqualSet(rm.semanticContext.findModules("o"), hashSet("object")); assertEqualSet(rm.semanticContext.findModules("basic_lib"), hashSet()); // Test not find basic lib files assertEqualSet(rm.semanticContext.findModules("not"), hashSet("not_source_foo")); // Test find self // Test getResolvedModule for module that is not in a bundle at all. rm = getUpdatedResolvedModule(loc(NOT_A_BUNDLE, "not_a_bundle_foo.d")); assertEqualSet(rm.semanticContext.findModules("o"), hashSet("object")); assertEqualSet(rm.semanticContext.findModules("not"), hashSet("not_a_bundle_foo")); testFindResolvedModule(rm.semanticContext, "object", DEFAULT_DMD_INSTALL_LOCATION__Object_Path); // Test getResolvedModule for module in StandardLibrary rm = getUpdatedResolvedModule(DEFAULT_DMD_INSTALL_LOCATION__Object_Path); assertEqualSet(rm.semanticContext.findModules("o"), hashSet("object")); assertTrue(rm.semanticContext instanceof StandardLibraryResolution); // Test getResolvedModule for missing file - must throw try { rm = getUpdatedResolvedModule(loc(NOT_A_BUNDLE, "_does_not_exist.d")); assertFail(); } catch (CommonException e) { } boolean SUPPORT_RELATIVE_PATHS = false; // Disabled because relative paths are no long supported. if(SUPPORT_RELATIVE_PATHS) { // Test getResolvedModule for a relative path. Location specialPath = loc(PathUtil.createValidPath(("###special/relative_bundle.d"))); sm.parseCache.setSourceAndParseModule(specialPath.path, "module relative_bundle;"); rm = getUpdatedResolvedModule(specialPath); assertEqualSet(rm.semanticContext.findModules("o"), hashSet( "object" )); testFindResolvedModule(rm.semanticContext, "object", DEFAULT_DMD_INSTALL_LOCATION__Object_Path); // Test same, when no parse source exists for that relative path try { rm = getUpdatedResolvedModule(loc(PathUtil.createValidPath(("###special/non_existent.d")))); assertFail(); } catch (CommonException ce) { assertTrue(ce.getCause() instanceof ModuleSourceException); } } } }