Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci(compiler): run compiler tests in bazel #22900

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 16 additions & 5 deletions packages/compiler/test/BUILD.bazel
@@ -1,18 +1,24 @@
load("//tools:defaults.bzl", "ts_library", "ts_web_test")
load("@build_bazel_rules_nodejs//:defs.bzl", "jasmine_node_test")

# Test that should only be run in node
NODE_ONLY = [
"**/*_node_only_spec.ts",
"aot/**/*.ts",
"render3/**/*.ts",
]

ts_library(
name = "test_lib",
testonly = 1,
srcs = glob(
["**/*.ts"],
exclude = ["**/*_node_only_spec.ts"],
exclude = NODE_ONLY,
),
deps = [
"//packages:types",
"//packages/common",
"//packages/compiler",
"//packages/compiler-cli",
"//packages/compiler/testing",
"//packages/core",
"//packages/core/testing",
Expand All @@ -25,19 +31,25 @@ ts_library(
ts_library(
name = "test_node_only_lib",
testonly = 1,
srcs = glob(["**/*_node_only_spec.ts"]),
srcs = glob(NODE_ONLY),
deps = [
":test_lib",
"//packages/compiler",
"//packages/compiler-cli",
"//packages/compiler/testing",
"//packages/core",
],
)

jasmine_node_test(
name = "test",
bootstrap = ["angular/tools/testing/init_node_spec.js"],
data = [
"//packages/animations:npm_package",
"//packages/common:npm_package",
"//packages/core:npm_package",
],
# dissable since tests are running but not yet passing
tags = ["manual"],
deps = [
":test_lib",
":test_node_only_lib",
Expand All @@ -49,7 +61,6 @@ jasmine_node_test(
ts_web_test(
name = "test_web",
# disable since tests are running but not yet passing
tags = ["manual"],
deps = [
":test_lib",
],
Expand Down
52 changes: 29 additions & 23 deletions packages/compiler/test/aot/compiler_spec.ts
Expand Up @@ -13,7 +13,7 @@ import {extractSourceMap, originalPositionFor} from '@angular/compiler/testing/s
import {NodeFlags} from '@angular/core/src/view/index';
import * as ts from 'typescript';

import {EmittingCompilerHost, MockAotCompilerHost, MockCompilerHost, MockDirectory, MockMetadataBundlerHost, arrayToMockDir, compile, expectNoDiagnostics, settings, setup, toMockFileArray} from './test_util';
import {EmittingCompilerHost, MockAotCompilerHost, MockCompilerHost, MockDirectory, MockMetadataBundlerHost, arrayToMockDir, compile, expectNoDiagnostics, isInBazel, settings, setup, toMockFileArray} from './test_util';

describe('compiler (unbundled Angular)', () => {
let angularFiles = setup();
Expand Down Expand Up @@ -872,30 +872,31 @@ describe('compiler (unbundled Angular)', () => {
});

describe('compiler (bundled Angular)', () => {
setup({compileAngular: false, compileAnimations: false});

let angularFiles: Map<string, string>;
let angularFiles: Map<string, string> = setup();

beforeAll(() => {
const emittingHost = new EmittingCompilerHost(['@angular/core/index'], {emitMetadata: false});

// Create the metadata bundled
const indexModule = emittingHost.effectiveName('@angular/core/index');
const bundler = new MetadataBundler(
indexModule, '@angular/core', new MockMetadataBundlerHost(emittingHost));
const bundle = bundler.getMetadataBundle();
const metadata = JSON.stringify(bundle.metadata, null, ' ');
const bundleIndexSource = privateEntriesToIndex('./index', bundle.privates);
emittingHost.override('@angular/core/bundle_index.ts', bundleIndexSource);
emittingHost.addWrittenFile(
'@angular/core/package.json', JSON.stringify({typings: 'bundle_index.d.ts'}));
emittingHost.addWrittenFile('@angular/core/bundle_index.metadata.json', metadata);

// Emit the sources
const bundleIndexName = emittingHost.effectiveName('@angular/core/bundle_index.ts');
const emittingProgram = ts.createProgram([bundleIndexName], settings, emittingHost);
emittingProgram.emit();
angularFiles = emittingHost.writtenAngularFiles();
if (!isInBazel()) {
// If we are not using Bazel then we need to build these files explicitly
const emittingHost = new EmittingCompilerHost(['@angular/core/index'], {emitMetadata: false});

// Create the metadata bundled
const indexModule = emittingHost.effectiveName('@angular/core/index');
const bundler = new MetadataBundler(
indexModule, '@angular/core', new MockMetadataBundlerHost(emittingHost));
const bundle = bundler.getMetadataBundle();
const metadata = JSON.stringify(bundle.metadata, null, ' ');
const bundleIndexSource = privateEntriesToIndex('./index', bundle.privates);
emittingHost.override('@angular/core/bundle_index.ts', bundleIndexSource);
emittingHost.addWrittenFile(
'@angular/core/package.json', JSON.stringify({typings: 'bundle_index.d.ts'}));
emittingHost.addWrittenFile('@angular/core/bundle_index.metadata.json', metadata);

// Emit the sources
const bundleIndexName = emittingHost.effectiveName('@angular/core/bundle_index.ts');
const emittingProgram = ts.createProgram([bundleIndexName], settings, emittingHost);
emittingProgram.emit();
angularFiles = emittingHost.writtenAngularFiles();
}
});

describe('Quickstart', () => {
Expand All @@ -922,6 +923,11 @@ describe('compiler (bundled Angular)', () => {
const emittingHost =
new EmittingCompilerHost(['/bolder/index.ts'], {emitMetadata: false, mockData: LIBRARY});

if (isInBazel()) {
// In bazel we can just add the angular files from the ones read during setup.
emittingHost.addFiles(angularFiles);
}

// Create the metadata bundled
const indexModule = '/bolder/public-api';
const bundler =
Expand Down
74 changes: 70 additions & 4 deletions packages/compiler/test/aot/test_util.ts
Expand Up @@ -60,8 +60,6 @@ export interface EmitterOptions {

function calcPathsOnDisc() {
const moduleFilename = module.filename.replace(/\\/g, '/');
// TODO(i): this is suspicious because it relies on build.sh output
// which is problematic when we are running tests under bazel - review with Chuck
const distIndex = moduleFilename.indexOf('/dist/all');
if (distIndex >= 0) {
rootPath = moduleFilename.substr(0, distIndex);
Expand All @@ -83,7 +81,7 @@ export class EmittingCompilerHost implements ts.CompilerHost {
// Rewrite references to scripts with '@angular' to its corresponding location in
// the source tree.
this.scriptNames = scriptNames.map(f => this.effectiveName(f));
this.root = rootPath;
this.root = rootPath || this.root;
if (options.context) {
this.addedFiles = mergeMaps(options.context);
}
Expand All @@ -110,6 +108,12 @@ export class EmittingCompilerHost implements ts.CompilerHost {
this.cachedAddedDirectories = undefined;
}

public addFiles(map: Map<string, string>) {
for (const [name, content] of Array.from(map.entries())) {
this.addedFiles.set(name, content);
}
}

public addWrittenFile(fileName: string, content: string) {
this.writtenFiles.set(this.effectiveName(fileName), content);
}
Expand All @@ -124,7 +128,7 @@ export class EmittingCompilerHost implements ts.CompilerHost {

public effectiveName(fileName: string): string {
const prefix = '@angular/';
return fileName.startsWith('@angular/') ?
return angularSourcePath && fileName.startsWith(prefix) ?
path.join(angularSourcePath, fileName.substr(prefix.length)) :
fileName;
}
Expand Down Expand Up @@ -566,6 +570,38 @@ const minCoreIndex = `
export * from './src/codegen_private_exports';
`;

function readBazelWrittenFilesFrom(
bazelPackageRoot: string, packageName: string, map: Map<string, string>,
skip: (name: string, fullName: string) => boolean = () => false) {
function processDirectory(dir: string, dest: string) {
const entries = fs.readdirSync(dir);
for (const name of entries) {
const fullName = path.join(dir, name);
const destName = path.join(dest, name);
const stat = fs.statSync(fullName);
if (!skip(name, fullName)) {
if (stat.isDirectory()) {
processDirectory(fullName, destName);
} else {
const content = fs.readFileSync(fullName, 'utf8');
map.set(destName, content);
}
}
}
}
try {
processDirectory(bazelPackageRoot, path.join('/node_modules/@angular', packageName));
} catch (e) {
console.error(
`Consider adding //packages/${packageName} as a data dependency in the BUILD.bazel rule for the failing test`);
throw e;
}
}

export function isInBazel(): boolean {
return process.env.TEST_SRCDIR != null;
}

export function setup(
options: {compileAngular: boolean, compileAnimations: boolean, compileCommon?: boolean} = {
compileAngular: true,
Expand All @@ -575,6 +611,36 @@ export function setup(
let angularFiles = new Map<string, string>();

beforeAll(() => {
const sources = process.env.TEST_SRCDIR;
if (sources) {
// If running under bazel then we get the compiled version of the files from the bazel package
// output.
const bundles = new Set([
'bundles', 'esm2015', 'esm5', 'testing', 'testing.d.ts', 'testing.metadata.json', 'browser',
'browser.d.ts'
]);
const skipDirs = (name: string) => bundles.has(name);
if (options.compileAngular) {
// If this fails please add //packages/core:npm_package as a test data dependency.
readBazelWrittenFilesFrom(
path.join(sources, 'angular/packages/core/npm_package'), 'core', angularFiles,
skipDirs);
}
if (options.compileAnimations) {
// If this fails please add //packages/animations:npm_package as a test data dependency.
readBazelWrittenFilesFrom(
path.join(sources, 'angular/packages/animations/npm_package'), 'animations',
angularFiles, skipDirs);
}
if (options.compileCommon) {
// If this fails please add //packages/common:npm_package as a test data dependency.
readBazelWrittenFilesFrom(
path.join(sources, 'angular/packages/common/npm_package'), 'common', angularFiles,
skipDirs);
}
return;
}

if (options.compileAngular) {
const emittingHost = new EmittingCompilerHost([], {emitMetadata: true});
emittingHost.addScript('@angular/core/index.ts', minCoreIndex);
Expand Down