/* * Copyright 2016 The Closure Compiler Authors. * * 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 com.google.javascript.jscomp.deps; import static com.google.common.truth.Truth.assertThat; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.javascript.jscomp.CompilerInput; import com.google.javascript.jscomp.SourceFile; import junit.framework.TestCase; /** Tests for {@link ModuleLoader}. */ public final class ModuleLoaderTest extends TestCase { private final ImmutableMap<String, String> packageJsonMainEntries = ImmutableMap.of( "/B/package.json", "/B/lib/b", "/node_modules/B/package.json", "/node_modules/B/lib/b.js"); public void testWindowsAddresses() { ModuleLoader loader = new ModuleLoader( null, ImmutableList.of("."), inputs("js\\a.js", "js\\b.js"), ModuleLoader.ResolutionMode.LEGACY); assertUri("js/a.js", loader.resolve("js\\a.js")); assertUri("js/b.js", loader.resolve("js\\a.js").resolveJsModule("./b")); } public void testJsExtensionLegacy() { ModuleLoader loader = new ModuleLoader( null, ImmutableList.of("."), inputs("js/a.js", "js/b.js"), ModuleLoader.ResolutionMode.LEGACY); assertUri("js/a.js", loader.resolve("js/a.js")); assertUri("js/b.js", loader.resolve("js/a.js").resolveJsModule("./b")); assertUri("js/b.js", loader.resolve("js/a.js").resolveJsModule("./b.js")); } public void testLocateJsLegacy() throws Exception { ModuleLoader loader = new ModuleLoader( null, ImmutableList.of("."), inputs("A/index.js", "B/index.js", "app.js"), ModuleLoader.ResolutionMode.LEGACY); input("A/index.js"); input("B/index.js"); input("app.js"); assertUri("A/index.js", loader.resolve("A/index.js")); assertUri("A.js", loader.resolve("B/index.js").resolveJsModule("../A")); assertUri("A/index.js", loader.resolve("B/index.js").resolveJsModule("../A/index")); assertUri("A/index.js", loader.resolve("app.js").resolveJsModule("./A/index")); assertUri("A/index.js", loader.resolve("app.js").resolveJsModule("A/index")); assertUri("A/index.js", loader.resolve("folder/app.js").resolveJsModule("A/index")); assertUri("index.js", loader.resolve("folder/app.js").resolveJsModule("index")); } public void testLocateNodeModuleLegacy() throws Exception { ImmutableList<CompilerInput> compilerInputs = inputs( "/A/index.js", "/A/index.json", "/node_modules/A/index.js", "/node_modules/A/foo.js", "/node_modules/A/node_modules/A/index.json", "/B/package.json", "/B/lib/b.js", "/node_modules/B/package.json", "/node_modules/B/lib/b.js"); ModuleLoader loader = new ModuleLoader( null, (new ImmutableList.Builder<String>()).build(), compilerInputs, ModuleLoader.ResolutionMode.LEGACY); assertUri("/A.js", loader.resolve("/foo.js").resolveJsModule("/A")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("/A/index.js")); assertUri("/A.js", loader.resolve("/foo.js").resolveJsModule("./A")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("./A/index.js")); assertUri("/A.js", loader.resolve("/foo.js").resolveJsModule("/A")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("/A/index")); assertUri("/A/index.json.js", loader.resolve("/foo.js").resolveJsModule("/A/index.json")); assertUri("A.js", loader.resolve("/foo.js").resolveJsModule("A")); assertUri("A.js", loader.resolve("/node_modules/A/foo.js").resolveJsModule("A")); assertUri( "/node_modules/A/foo.js", loader.resolve("/node_modules/A/index.js").resolveJsModule("./foo")); assertUri("/B.js", loader.resolve("/app.js").resolveJsModule("/B")); assertUri("B.js", loader.resolve("/app.js").resolveJsModule("B")); } public void testJsExtensionNode() { ModuleLoader loader = new ModuleLoader( null, ImmutableList.of("."), inputs("js/a.js", "js/b.js"), ModuleLoader.PathResolver.RELATIVE, ModuleLoader.ResolutionMode.NODE, packageJsonMainEntries); assertUri("js/a.js", loader.resolve("js/a.js")); assertUri("js/b.js", loader.resolve("js/a.js").resolveJsModule("./b")); assertUri("js/b.js", loader.resolve("js/a.js").resolveJsModule("./b.js")); } public void testLocateJsNode() throws Exception { ModuleLoader loader = new ModuleLoader( null, ImmutableList.of("."), inputs("A/index.js", "B/index.js", "app.js"), ModuleLoader.PathResolver.RELATIVE, ModuleLoader.ResolutionMode.NODE, packageJsonMainEntries); input("A/index.js"); input("B/index.js"); input("app.js"); assertUri("A/index.js", loader.resolve("A/index.js")); assertUri("A/index.js", loader.resolve("B/index.js").resolveJsModule("../A")); assertUri("A/index.js", loader.resolve("B/index.js").resolveJsModule("../A/")); assertUri("A/index.js", loader.resolve("B/index.js").resolveJsModule("../A/index")); assertUri("A/index.js", loader.resolve("app.js").resolveJsModule("./A/index")); assertNull(loader.resolve("app.js").resolveJsModule("A/index")); assertNull(loader.resolve("folder/app.js").resolveJsModule("A/index")); assertNull(loader.resolve("folder/app.js").resolveJsModule("index")); } public void testLocateNodeModuleNode() throws Exception { ImmutableList<CompilerInput> compilerInputs = inputs( "/A/index.js", "/A/index.json", "/node_modules/A/index.js", "/node_modules/A/foo.js", "/node_modules/A/node_modules/A/index.json", "/B/package.json", "/B/lib/b.js", "/node_modules/B/package.json", "/node_modules/B/lib/b.js"); ModuleLoader loader = new ModuleLoader( null, (new ImmutableList.Builder<String>()).build(), compilerInputs, ModuleLoader.PathResolver.RELATIVE, ModuleLoader.ResolutionMode.NODE, packageJsonMainEntries); assertUri("/A/index.js", loader.resolve(" /foo.js").resolveJsModule("/A")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("/A/index.js")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("./A")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("./A/index.js")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("/A")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("/A/index")); assertUri("/A/index.json", loader.resolve("/foo.js").resolveJsModule("/A/index.json")); assertUri("/node_modules/A/index.js", loader.resolve("/foo.js").resolveJsModule("A")); assertUri( "/node_modules/A/node_modules/A/index.json", loader.resolve("/node_modules/A/foo.js").resolveJsModule("A")); assertUri( "/node_modules/A/foo.js", loader.resolve("/node_modules/A/index.js").resolveJsModule("./foo")); assertUri("/B/lib/b.js", loader.resolve("/app.js").resolveJsModule("/B")); assertUri("/B/lib/b.js", loader.resolve("/app.js").resolveJsModule("/B/")); assertUri("/node_modules/B/lib/b.js", loader.resolve("/app.js").resolveJsModule("B")); } public void testJsExtensionBrowser() { ModuleLoader loader = new ModuleLoader( null, ImmutableList.of("."), inputs("js/a.js", "js/b.js"), ModuleLoader.ResolutionMode.BROWSER); assertUri("js/a.js", loader.resolve("js/a.js")); assertNull(loader.resolve("js/a.js").resolveJsModule("./b")); assertUri("js/b.js", loader.resolve("js/a.js").resolveJsModule("./b.js")); } public void testLocateJsBrowser() throws Exception { ModuleLoader loader = new ModuleLoader( null, ImmutableList.of("."), inputs("A/index.js", "B/index.js", "app.js"), ModuleLoader.ResolutionMode.BROWSER); input("A/index.js"); input("B/index.js"); input("app.js"); assertUri("A/index.js", loader.resolve("A/index.js")); assertNull(loader.resolve("B/index.js").resolveJsModule("../A")); assertNull(loader.resolve("B/index.js").resolveJsModule("../A/index")); assertNull(loader.resolve("app.js").resolveJsModule("./A/index")); assertNull(loader.resolve("app.js").resolveJsModule("A/index")); assertNull(loader.resolve("folder/app.js").resolveJsModule("A/index")); assertNull(loader.resolve("folder/app.js").resolveJsModule("index")); assertNull(loader.resolve("B/index.js").resolveJsModule("../A")); assertUri("A/index.js", loader.resolve("B/index.js").resolveJsModule("../A/index.js")); assertUri("A/index.js", loader.resolve("app.js").resolveJsModule("./A/index.js")); assertUri("A/index.js", loader.resolve("folder/app.js").resolveJsModule("../A/index.js")); assertNull(loader.resolve("folder/app.js").resolveJsModule("index")); } public void testLocateNodeModuleBrowser() throws Exception { ImmutableList<CompilerInput> compilerInputs = inputs( "/A/index.js", "/A/index.json", "/node_modules/A/index.js", "/node_modules/A/foo.js", "/node_modules/A/node_modules/A/index.json", "/B/package.json", "/B/lib/b.js", "/node_modules/B/package.json", "/node_modules/B/lib/b.js"); ModuleLoader loader = new ModuleLoader( null, (new ImmutableList.Builder<String>()).build(), compilerInputs, ModuleLoader.ResolutionMode.BROWSER); assertNull(loader.resolve("/foo.js").resolveJsModule("/A")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("/A/index.js")); assertNull(loader.resolve("/foo.js").resolveJsModule("./A")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("./A/index.js")); assertNull(loader.resolve("/foo.js").resolveJsModule("/A")); assertNull(loader.resolve("/foo.js").resolveJsModule("/A/index")); assertUri("/A/index.json", loader.resolve("/foo.js").resolveJsModule("/A/index.json")); assertNull(loader.resolve("/foo.js").resolveJsModule("A")); assertNull(loader.resolve("/node_modules/A/foo.js").resolveJsModule("A")); assertNull(loader.resolve("/node_modules/A/index.js").resolveJsModule("./foo")); assertUri( "/node_modules/A/foo.js", loader.resolve("/node_modules/A/index.js").resolveJsModule("./foo.js")); assertNull(loader.resolve("/app.js").resolveJsModule("/B")); assertNull(loader.resolve("/app.js").resolveJsModule("B")); } public void testNormalizeUris() throws Exception { ModuleLoader loader = new ModuleLoader( null, ImmutableList.of("a", "b", "/c"), inputs(), ModuleLoader.ResolutionMode.LEGACY); assertUri("a.js", loader.resolve("a/a.js")); assertUri("a.js", loader.resolve("a.js")); assertUri("some.js", loader.resolve("some.js")); assertUri("/x.js", loader.resolve("/x.js")); assertUri("x-y.js", loader.resolve("x:y.js")); assertUri("foo%20bar.js", loader.resolve("foo bar.js")); } public void testDuplicateUris() throws Exception { try { new ModuleLoader( null, ImmutableList.of("a", "b"), inputs("a/f.js", "b/f.js"), ModuleLoader.ResolutionMode.LEGACY); fail("Expected error"); } catch (IllegalArgumentException e) { assertThat(e.getMessage()).contains("Duplicate module path"); } } public void testCanonicalizePath() throws Exception { assertEquals("a/b/c", ModuleNames.canonicalizePath("a/b/c")); assertEquals("a/c", ModuleNames.canonicalizePath("a/b/../c")); assertEquals("b/c", ModuleNames.canonicalizePath("a/b/../../b/c")); assertEquals("c", ModuleNames.canonicalizePath("a/b/../../c")); assertEquals("../a", ModuleNames.canonicalizePath("../a/b/..")); assertEquals("/", ModuleNames.canonicalizePath("/a/b/../../..")); assertEquals("/b", ModuleNames.canonicalizePath("/a/../../../b")); assertEquals("/", ModuleNames.canonicalizePath("/a/..")); } ImmutableList<CompilerInput> inputs(String... names) { ImmutableList.Builder<CompilerInput> builder = ImmutableList.builder(); for (String name : names) { builder.add(input(name)); } return builder.build(); } public void testLocateNodeModulesNoLeadingSlash() throws Exception { ImmutableList<CompilerInput> compilerInputs = inputs( "/A/index.js", "/A/index.json", "node_modules/A/index.js", "node_modules/A/foo.js", "node_modules/A/node_modules/A/index.json", "/B/package.json", "/B/lib/b.js", "node_modules/B/package.json", "node_modules/B/lib/b.js"); ModuleLoader loader = new ModuleLoader( null, (new ImmutableList.Builder<String>()).build(), compilerInputs, ModuleLoader.PathResolver.RELATIVE, ModuleLoader.ResolutionMode.NODE, packageJsonMainEntries); assertUri("/A/index.js", loader.resolve(" /foo.js").resolveJsModule("/A")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("/A/index.js")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("./A")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("./A/index.js")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("/A")); assertUri("/A/index.js", loader.resolve("/foo.js").resolveJsModule("/A/index")); assertUri("/A/index.json", loader.resolve("/foo.js").resolveJsModule("/A/index.json")); assertUri("/node_modules/A/index.js", loader.resolve("/foo.js").resolveJsModule("A")); assertUri( "/node_modules/A/node_modules/A/index.json", loader.resolve("node_modules/A/foo.js").resolveJsModule("A")); assertUri( "node_modules/A/foo.js", loader.resolve("node_modules/A/index.js").resolveJsModule("./foo")); assertUri("/B/lib/b.js", loader.resolve("/app.js").resolveJsModule("/B")); assertUri("/node_modules/B/lib/b.js", loader.resolve("/app.js").resolveJsModule("B")); } CompilerInput input(String name) { return new CompilerInput(SourceFile.fromCode(name, ""), false); } private static void assertUri(String expected, ModuleLoader.ModulePath actual) { assertEquals(expected, actual.toString()); } }