mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 11:58:13 +00:00
Add a script which generates a testing package
This script has a decent description at the top, and decent comments throughout. Change-Id: I455c0e7b5354563750636e31a53db2caacdbf687 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/286700 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
parent
6e16dad3c0
commit
3c633384d3
|
@ -35,4 +35,5 @@ dev_dependencies:
|
|||
lints: any
|
||||
logging: any
|
||||
matcher: any
|
||||
test_descriptor: any
|
||||
test_reflective_loader: any
|
||||
|
|
203
pkg/analysis_server/tool/generate_testing_package.dart
Normal file
203
pkg/analysis_server/tool/generate_testing_package.dart
Normal file
|
@ -0,0 +1,203 @@
|
|||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
/// This script generates a test package with a specified number of libraries,
|
||||
/// classes, methods, and doc comment references, in order to test analyzer's
|
||||
/// performance, scalability, and stability characteristics.
|
||||
///
|
||||
/// Call with `--help` to see all of the args.
|
||||
library generate_testing_package;
|
||||
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:args/args.dart';
|
||||
import 'package:test_descriptor/test_descriptor.dart' as d;
|
||||
|
||||
void main(List<String> args) async {
|
||||
// TODO(srawlins): Support multiple packages which depend on each other, in a
|
||||
// DAG similar to the import graph.
|
||||
var argParser = ArgParser()
|
||||
..addOption(
|
||||
'library-count',
|
||||
defaultsTo: '1',
|
||||
help: 'the number of libraries',
|
||||
)
|
||||
..addOption(
|
||||
'class-count',
|
||||
defaultsTo: '1',
|
||||
help: 'the number of classes per library',
|
||||
)
|
||||
..addOption(
|
||||
'method-count',
|
||||
defaultsTo: '1',
|
||||
help: 'the number of methods per class',
|
||||
)
|
||||
..addOption(
|
||||
'parameter-count',
|
||||
defaultsTo: '1',
|
||||
help: 'the number of parameters per method',
|
||||
)
|
||||
..addFlag('use-barrel-file',
|
||||
defaultsTo: false, help: 'Whether to add a barrel import')
|
||||
..addFlag('use-json-serializable',
|
||||
defaultsTo: false,
|
||||
help: 'Whether to declare @JsonSerializable classes');
|
||||
var argResults = argParser.parse(args);
|
||||
var libraryCount = int.parse(argResults['library-count'] as String);
|
||||
var classCount = int.parse(argResults['class-count'] as String);
|
||||
var methodCount = int.parse(argResults['method-count'] as String);
|
||||
var parameterCount = int.parse(argResults['parameter-count'] as String);
|
||||
var useBarrelFile = argResults['use-barrel-file'] as bool;
|
||||
var useJsonSerializable = argResults['use-json-serializable'] as bool;
|
||||
var testDataDir = Directory('test_data')..createSync();
|
||||
var libFiles = <d.Descriptor>[];
|
||||
var classCounter = 1;
|
||||
var methodCounter = 1;
|
||||
var middleImportIndex = libraryCount ~/ 2;
|
||||
// We need a global index for the names of top-level variables, to avoid
|
||||
// ambiguous elements from imports.
|
||||
var topLevelVariableIndex = 1;
|
||||
for (var lIndex = 1; lIndex <= libraryCount; lIndex++) {
|
||||
var libraryName = 'lib$lIndex'.padLeft(3, '0');
|
||||
// Each library has an index, starting at 1. The libraries depend on each
|
||||
// other in tiers. The "tier" of a library is the base-2 logarithm of its
|
||||
// index. Libraries in higher tiers depend on libraries in lower tiers.
|
||||
// Libraries in higher tiers depend on more libraries than those in lower
|
||||
// tiers.
|
||||
//
|
||||
// In a package with 10 libraries, we have the following tiers and
|
||||
// dependencies:
|
||||
// * T0: lib1 - no imports
|
||||
// * T1: lib2 - imports lib1
|
||||
// * T2: lib3, lib4 - each imports two libraries from T0, T1
|
||||
// * T3: lib5, lib6, lib7, lib8 - each imports three libraries from T0, T1,
|
||||
// and T2
|
||||
// * T4: lib9, lib10 - each imports four libraries from T0, T1, T2, T3
|
||||
//
|
||||
// In a package with 1000 libraries, there are 11 tiers, and libraries in
|
||||
// the last have 10 imports each.
|
||||
// TODO(srawlins): Make the "connectedness" of the import graph
|
||||
// configurable.
|
||||
var importGraphTier = (log(lIndex) / ln2).ceil();
|
||||
var importIndexStep =
|
||||
importGraphTier == 0 ? -1 : (lIndex - 1) ~/ importGraphTier;
|
||||
var content = StringBuffer();
|
||||
// Add imports in a library above tier 0.
|
||||
if (importGraphTier > 0) {
|
||||
if (useJsonSerializable) {
|
||||
content
|
||||
.writeln("import 'package:json_annotation/json_annotation.dart';");
|
||||
}
|
||||
if (useBarrelFile && lIndex > middleImportIndex) {
|
||||
content.writeln(import(testPackageLibUri('barrel.dart')));
|
||||
}
|
||||
for (var tierIndex = 1; tierIndex <= importGraphTier; tierIndex++) {
|
||||
var importIndex = tierIndex * importIndexStep;
|
||||
if (useBarrelFile) {
|
||||
if (lIndex <= middleImportIndex || importIndex > middleImportIndex) {
|
||||
content.writeln(import(testPackageLibUri('lib$importIndex.dart')));
|
||||
}
|
||||
} else {
|
||||
content.writeln(import(testPackageLibUri('lib$importIndex.dart')));
|
||||
}
|
||||
}
|
||||
content.writeln('');
|
||||
}
|
||||
|
||||
if (useJsonSerializable) {
|
||||
content.writeln("part '$libraryName.g.dart';");
|
||||
content.writeln('');
|
||||
}
|
||||
|
||||
// Add top-level variables above tier 0.
|
||||
if (importGraphTier > 0) {
|
||||
for (var tierIndex = 1; tierIndex <= importGraphTier; tierIndex++) {
|
||||
var importIndex = tierIndex * importIndexStep;
|
||||
// We instantiate a class which is guaranteed to be found in
|
||||
// `lib$importIndex.dart`.
|
||||
var classReferenceIndex = classCount * importIndex;
|
||||
content
|
||||
.writeln('var x$topLevelVariableIndex = C$classReferenceIndex();');
|
||||
topLevelVariableIndex++;
|
||||
}
|
||||
content.writeln('');
|
||||
}
|
||||
|
||||
for (var cIndex = 1; cIndex <= classCount; cIndex++) {
|
||||
content.writeln('/// Doc comment.');
|
||||
if (useJsonSerializable) {
|
||||
content.writeln('@JsonSerializable()');
|
||||
}
|
||||
content.writeln('class C$classCounter {');
|
||||
if (useJsonSerializable) {
|
||||
content.writeln(' C$classCounter();');
|
||||
content.writeln(
|
||||
' factory C$classCounter.fromJson(Map<String, dynamic> json) => '
|
||||
'_\$C${classCounter}FromJson(json);');
|
||||
content.writeln('Map<String, dynamic> toJson() => '
|
||||
'_\$C${classCounter}ToJson(this);');
|
||||
}
|
||||
for (var mIndex = 1; mIndex <= methodCount; mIndex++) {
|
||||
content.write(' void m$methodCounter(');
|
||||
content.write(List.generate(parameterCount, (pIndex) => 'int p$pIndex')
|
||||
.join(', '));
|
||||
content.writeln(') {}');
|
||||
methodCounter++;
|
||||
}
|
||||
content.writeln('}');
|
||||
classCounter++;
|
||||
}
|
||||
libFiles.add(d.file('$libraryName.dart', content.toString()));
|
||||
}
|
||||
|
||||
if (useBarrelFile) {
|
||||
// Write the barrel file, which exports the first half of the libraries.
|
||||
var content = StringBuffer();
|
||||
for (var j = 1; j <= middleImportIndex; j++) {
|
||||
content.writeln(export(testPackageLibUri('lib$j.dart')));
|
||||
}
|
||||
libFiles.add(d.file('barrel.dart', content.toString()));
|
||||
}
|
||||
|
||||
var testPackageDir = d.dir('test_package', [
|
||||
d.file('pubspec.yaml', pubspec(useJsonSerializable: useJsonSerializable)),
|
||||
d.dir('lib', libFiles),
|
||||
]);
|
||||
await testPackageDir.create(testDataDir.path);
|
||||
}
|
||||
|
||||
String export(String uri) => "export '$uri';";
|
||||
|
||||
String import(String uri) => "import '$uri';";
|
||||
|
||||
/// Returns the text of a 'pubspec.yaml' file.
|
||||
///
|
||||
/// With [useJsonSerializable], several packages are added to the dependencies
|
||||
/// in order to test using build_runner.
|
||||
String pubspec({required bool useJsonSerializable}) {
|
||||
var dependencies = useJsonSerializable
|
||||
? '''
|
||||
dependencies:
|
||||
json_annotation: any
|
||||
json_serializable: any
|
||||
'''
|
||||
: '';
|
||||
var devDependencies = useJsonSerializable
|
||||
? '''
|
||||
dev_dependencies:
|
||||
build_runner: any
|
||||
'''
|
||||
: '';
|
||||
return '''
|
||||
name: test_package
|
||||
version: 0.0.1
|
||||
environment:
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
$dependencies
|
||||
$devDependencies
|
||||
''';
|
||||
}
|
||||
|
||||
String testPackageLibUri(String path) => 'package:test_package/$path';
|
Loading…
Reference in a new issue