blob: 6bf7457b8fd87d6019da6c07d47b9a7bfdc268fa [file] [log] [blame]
// Copyright (c) 2022, 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.
// These tests validate summary generation in various scenarios.
// Currently, no validation of the summary content itself is done.
import 'dart:io';
import 'package:jnigen/src/config/config.dart';
import 'package:jnigen/src/elements/elements.dart';
import 'package:jnigen/src/logging/logging.dart';
import 'package:jnigen/src/summary/summary.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' hide equals;
import 'package:test/test.dart';
import 'test_util/test_util.dart';
void expectNonEmptySummary(Classes? classes) {
expect(classes, isNotNull);
final decls = classes!.decls;
expect(decls.entries.length, greaterThanOrEqualTo(javaFiles.length));
final declNames = decls.keys.toSet();
final expectedClasses =
javaClasses.where((name) => !name.contains("annotations.")).toList();
expect(declNames, containsAll(expectedClasses));
}
void deleteTempDir(Directory directory) {
try {
if (Platform.isWindows) {
// This appears to avoid "file used by another process" errors.
sleep(const Duration(seconds: 1));
}
directory.deleteSync(recursive: true);
} on FileSystemException catch (e) {
log.warning("Cannot delete directory: $e");
}
}
List<String> findFiles(Directory dir, String suffix) {
return dir
.listSync(recursive: true)
.map((entry) => relative(entry.path, from: dir.path))
.where((path) => path.endsWith(suffix))
.toList();
}
Future<void> createJar(List<String> paths, String target) async {
final relativeTarget = relative(target, from: simplePackagePath);
final status = await runCommand(
'jar',
['cf', relativeTarget, ...paths],
workingDirectory: simplePackagePath,
);
if (status != 0) {
throw ArgumentError('Cannot create JAR from provided arguments');
}
}
Future<void> compileJavaFiles(List<String> paths, Directory target) async {
final status = await runCommand(
'javac',
['-d', target.absolute.path, ...paths],
workingDirectory: simplePackagePath,
);
if (status != 0) {
throw ArgumentError('Cannot compile Java sources');
}
}
String getClassNameFromPath(String path) {
if (!path.endsWith('.java')) {
throw ArgumentError('Filename must end with java');
}
return path
.replaceAll('/', '.')
.replaceAll('\\', '.')
.substring(0, path.length - 5);
}
final simplePackagePath = join('test', 'simple_package_test', 'java');
final simplePackageDir = Directory(simplePackagePath);
final javaFiles = findFiles(simplePackageDir, '.java');
final javaClasses = javaFiles.map(getClassNameFromPath).toList();
Config getConfig({List<String>? sourcePath, List<String>? classPath}) {
return Config(
outputConfig: OutputConfig(
bindingsType: BindingsType.dartOnly,
dartConfig: DartCodeOutputConfig(
path: Uri.file('unused.dart'),
structure: OutputStructure.singleFile,
),
),
classes: javaClasses,
sourcePath: sourcePath?.map((e) => Uri.file(e)).toList(),
classPath: classPath?.map((e) => Uri.file(e)).toList(),
logLevel: Level.WARNING,
);
}
void main() {
late Directory tempDir;
setUpAll(() {
tempDir = getTempDir("jnigen_summary_tests_");
});
test('Test summary generation from compiled JAR', () async {
final targetDir = tempDir.createTempSync("compiled_jar_test_");
await compileJavaFiles(javaFiles, targetDir);
final classFiles = findFiles(targetDir, '.class');
final jarFilePath = join(targetDir.absolute.path, 'classes.jar');
await createJar(classFiles, jarFilePath);
final config = getConfig(classPath: [jarFilePath]);
final summaryClasses = await getSummary(config);
expectNonEmptySummary(summaryClasses);
});
test('Test summary generation from source JAR', () async {
final targetDir = tempDir.createTempSync("source_jar_test_");
final jarFilePath = join(targetDir.path, 'sources.jar');
await createJar(javaFiles, jarFilePath);
final config = getConfig(sourcePath: [jarFilePath]);
final summaryClasses = await getSummary(config);
expectNonEmptySummary(summaryClasses);
});
test('Test summary generation from source folder', () async {
final config = getConfig(sourcePath: [simplePackagePath]);
final summaryClasses = await getSummary(config);
expectNonEmptySummary(summaryClasses);
});
test('Test summary generation from compiled classes in directory', () async {
final targetDir = tempDir.createTempSync("compiled_classes_test_");
await compileJavaFiles(javaFiles, targetDir);
final config = getConfig(classPath: [targetDir.path]);
final summaryClasses = await getSummary(config);
expectNonEmptySummary(summaryClasses);
});
// Test summary generation from combination of a source and class path
test('Test summary generation from combination', () async {
final targetDir = tempDir.createTempSync("combination_test_");
// remove a class from source files and create a source JAR
final sourceFiles = javaFiles.toList();
sourceFiles.removeLast();
final sourceJarPath = join(targetDir.path, 'sources.jar');
await createJar(sourceFiles, sourceJarPath);
await compileJavaFiles(javaFiles, targetDir);
final classFiles = findFiles(targetDir, '.class');
final classesJarPath = join(targetDir.path, 'classes.jar');
await createJar(classFiles, classesJarPath);
final config = getConfig(
classPath: [classesJarPath],
sourcePath: [sourceJarPath],
);
final summaryClasses = await getSummary(config);
expectNonEmptySummary(summaryClasses);
});
tearDownAll(() => deleteTempDir(tempDir));
}