/*
* 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());
}
}