cleanup(testing): clean up public api spec

Change the old public api spec to check only the exported top-level symbols. This will make sure that Dart and JS do not diverge. The new public api spec verifies the TS api.

Closes #7447
This commit is contained in:
vsavkin 2016-03-11 09:00:18 -08:00 committed by Victor Savkin
parent c25b9fcf97
commit 201475e8d8
5 changed files with 120 additions and 1641 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,68 +0,0 @@
import {StringWrapper, RegExpWrapper, isJsObject} from 'angular2/src/facade/lang';
var IS_FIELD = RegExpWrapper.create('^\\w+[\\.|\\#]\\w+=?$');
var IS_INTERFACE = RegExpWrapper.create('^\\{.+\\}');
var IS_DART = RegExpWrapper.create('\\:dart$');
var IS_JS = RegExpWrapper.create('\\:js$');
var IS_OPTIONAL = RegExpWrapper.create('\\:optional$');
var JS = 'JS';
var DART = 'Dart';
var MODE = isJsObject({}) ? JS : DART;
export class SymbolsDiff {
missing: string[] = [];
extra: string[] = [];
errors: string[] = [];
constructor(public actual: string[], public expected: string[]) {
this.actual.sort(compareIgnoreLang);
this.expected.sort(compareIgnoreLang);
this.computeDiff();
}
computeDiff(): void {
for (var i = 0, j = 0, length = this.expected.length + this.actual.length; i + j < length;) {
var expectedName: string = i < this.expected.length ? this.expected[i] : '~';
var actualName: string = j < this.actual.length ? this.actual[j] : '~';
if (stripLang(expectedName) == stripLang(actualName)) {
i++;
j++;
} else if (StringWrapper.compare(stripLang(expectedName), stripLang(actualName)) > 0) {
// JS does not see fields so ignore none method symbols
if (!this.shouldIgnore(expectedName)) {
this.extra.push(actualName);
this.errors.push('+ ' + actualName);
}
j++;
} else {
if (!this.shouldIgnore(expectedName)) {
this.missing.push(expectedName);
this.errors.push('- ' + expectedName);
}
i++;
}
}
}
shouldIgnore(expected: string): boolean {
var ignore = false;
if (MODE == JS) {
ignore = RegExpWrapper.test(IS_FIELD, expected) ||
RegExpWrapper.test(IS_INTERFACE, expected) ||
RegExpWrapper.test(IS_DART, expected) || RegExpWrapper.test(IS_OPTIONAL, expected)
} else {
ignore = RegExpWrapper.test(IS_JS, expected) || RegExpWrapper.test(IS_OPTIONAL, expected)
}
return ignore;
}
}
function stripLang(text: string): string {
var index = text.indexOf(':');
if (index >= 0) text = text.substring(0, index);
return text;
}
function compareIgnoreLang(a: string, b: string): number {
return StringWrapper.compare(stripLang(a), stripLang(b));
}

View File

@ -57,13 +57,11 @@ class ExportedSymbol {
addTo(List<String> names) {
var name = unwrapSymbol(symbol);
if (declaration is MethodMirror) {
names.add('$name()');
names.add(name);
} else if (declaration is ClassMirror) {
var classMirror = declaration as ClassMirror;
if (classMirror.isAbstract) name = '$name';
names.add(name);
classMirror.staticMembers.forEach(members('$name#', names));
classMirror.instanceMembers.forEach(members('$name.', names));
} else if (declaration is TypedefMirror) {
names.add(name);
} else if (declaration is VariableMirror) {
@ -76,15 +74,6 @@ class ExportedSymbol {
toString() => unwrapSymbol(symbol);
}
members(String prefix, List<String> names) {
return (Symbol symbol, MethodMirror method) {
var name = unwrapSymbol(symbol);
if (method.isOperator || method.isPrivate || IGNORE[name] == true) return;
var suffix = (method.isSetter || method.isGetter) ? '' : '()';
names.add('$prefix$name$suffix');
};
}
class LibraryInfo {
List<ExportedSymbol> names;
Map<Symbol, List<Symbol>> symbolsUsedForName;
@ -135,19 +124,6 @@ Iterable<Symbol> _getUsedSymbols(
}
});
}
if (decl is MethodMirror) {
MethodMirror mdecl = decl;
if (mdecl.parameters != null) mdecl.parameters.forEach((p) {
used.addAll(_getUsedSymbols(p.type, seenDecls, path, true));
});
used.addAll(_getUsedSymbols(mdecl.returnType, seenDecls, path, true));
}
if (decl is VariableMirror) {
VariableMirror vdecl = decl;
used.addAll(_getUsedSymbols(vdecl.type, seenDecls, path, true));
}
}
// Strip out type variables.

View File

@ -27,47 +27,12 @@ const IGNORE =
wrapperStack: true, '@@observable': true
}
function collectClassSymbols(symbols: string[], prefix: String, type: Function):
void {
// static
for (var name in type) {
if (IGNORE[name] || name.charAt(0) == '_') continue;
var suf = type[name] instanceof Function ? '()' : '';
var symbol = `${prefix}#${name}${suf}`;
symbols.push(symbol);
}
// instance
for (var name in type.prototype) {
if (IGNORE[name] || name.charAt(0) == '_') continue;
if (name == 'constructor') continue;
var suf = '';
try {
if (type.prototype[name] instanceof Function) suf = '()';
} catch (e) {
}
var symbol = `${prefix}.${name}${suf}`;
symbols.push(symbol);
}
}
function collectTopLevelSymbols(prefix: string, lib: any):
string[] {
var symbols: string[] = [];
for (var name in lib) {
var symbol = `${name}`;
var ref = lib[name];
if (ref instanceof Function) {
if (symbol.charAt(0) == symbol.charAt(0).toLowerCase()) {
// assume it is top level function
symbols.push(symbol + '()');
} else {
symbols.push(symbol);
collectClassSymbols(symbols, symbol, ref);
}
} else {
symbols.push(symbol);
}
}
return symbols;
}

View File

@ -11,49 +11,48 @@ import {
xit
} from 'angular2/testing_internal';
import {IS_DART} from 'angular2/src/facade/lang';
import {getSymbolsFromLibrary} from './symbol_inspector';
import {SymbolsDiff} from './symbol_differ';
export function main() {
describe('symbol inspector', () => {
it('should extract symbols', () => {
if (IS_DART) {
it('should extract symbols (dart)', () => {
var symbols = getSymbolsFromLibrary("simple_library");
expect(new SymbolsDiff(symbols,
[
expect(symbols).toEqual([
'A',
'ClosureParam',
'ClosureReturn',
'ConsParamType',
'FieldType',
'Generic',
'GetterType',
'MethodReturnType',
'ParamType',
'SomeInterface',
'StaticFieldType',
'TypedefParam',
'TypedefReturnType'
]);
});
} else {
it('should extract symbols (js)', () => {
var symbols = getSymbolsFromLibrary("simple_library");
expect(symbols).toEqual([
'A',
'A#staticField',
'A#staticField=',
'A#staticMethod()',
'A.field',
'A.field=',
'A.getter',
'A.method()',
'A.methodWithFunc()',
'ClosureParam',
'ClosureReturn',
'ConsParamType',
'FieldType',
'Generic',
'Generic.getter',
'GetterType',
'MethodReturnType',
'ParamType',
'StaticFieldType',
'TypedefParam',
'TypedefReturnType',
'SomeInterface:dart',
])
.errors)
.toEqual([]);
});
describe('assert', () => {
it('should assert symbol names are correct', () => {
var diffs = new SymbolsDiff(['a()', 'c()', 'd()'], ['a()', 'b()', 'd()']);
expect(diffs.errors).toEqual(['- b()', '+ c()']);
});
});
'TypedefReturnType'
]);
});
}
});
}