blob: a11668a8aa161f75336dd10094525751b3dcb978 [file] [log] [blame]
// Copyright (c) 2021, 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.
// @dart=2.9
import 'dart:async';
import 'dart:convert';
import 'dart:io' show HttpServer;
import 'package:browser_launcher/browser_launcher.dart';
import 'package:dev_compiler/src/kernel/asset_file_system.dart';
import 'package:front_end/src/api_prototype/file_system.dart';
import 'package:front_end/src/api_prototype/standard_file_system.dart';
import 'package:http_multi_server/http_multi_server.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart';
import 'package:test/test.dart';
const _existingFile = 'existingFile';
const _nonExistingFile = 'nonExistingFile';
const _smallFileContents = 'Hello world!';
List<int> _smallFileBytes = utf8.encode(_smallFileContents);
String _largeFileContents() =>
List.filled(10000, _smallFileContents).join('\n');
List<int> _largeFileBytes() => utf8.encode(_largeFileContents());
FutureOr<Response> handler(Request request) {
final uri = request.requestedUri;
final headers = {
'content-length': '${utf8.encode(_smallFileContents).length}',
...request.headers,
};
if (request.method == 'HEAD') {
// 'exists'
return uri.pathSegments.last == _existingFile
? Response.ok(null, headers: headers)
: Response.notFound(uri.toString());
}
if (request.method == 'GET') {
// 'readAsBytes'
return uri.pathSegments.last == _existingFile
? Response.ok(_smallFileContents, headers: headers)
: Response.notFound(uri.toString());
}
return Response.internalServerError();
}
FutureOr<Response> noisyHandler(Request request) {
final uri = request.requestedUri;
final contents = _largeFileContents();
final headers = {
'content-length': '${utf8.encode(contents).length}',
...request.headers,
};
if (request.method == 'HEAD' || request.method == 'GET') {
// 'exists' or 'readAsBytes'
return uri.pathSegments.last == _existingFile
? Response.ok(contents, headers: headers)
: Response.notFound(uri.toString());
}
return Response.internalServerError();
}
void main() async {
HttpServer server;
AssetFileSystem fileSystem;
group('AssetFileSystem with a server', () {
setUpAll(() async {
var hostname = 'localhost';
var port = await findUnusedPort();
server = await HttpMultiServer.bind(hostname, port);
fileSystem =
AssetFileSystem(StandardFileSystem.instance, hostname, '$port');
serveRequests(server, handler);
});
tearDownAll(() async {
await expectLater(server.close(), completes);
});
test('can tell if file exists', () async {
var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
expect(await entity.exists(), true);
});
test('can tell if file does not exist', () async {
var entity = fileSystem.entityForUri(Uri.parse(_nonExistingFile));
expect(await entity.exists(), false);
});
test('can read existing file using readAsBytes', () async {
var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
expect(await entity.readAsBytes(), _smallFileBytes);
});
test('can read and decode existing file using readAsBytes', () async {
var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
expect(utf8.decode(await entity.readAsBytes()), _smallFileContents);
});
test('can read existing file using readAsString', () async {
var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
expect(await entity.readAsString(), _smallFileContents);
});
test('cannot read non-existing file', () async {
var entity = fileSystem.entityForUri(Uri.parse(_nonExistingFile));
await expectLater(
entity.readAsBytes(), throwsA(isA<FileSystemException>()));
});
test('can read a lot of files concurrently', () async {
var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
var futures = [
for (var i = 0; i < 512; i++) entity.readAsBytes(),
];
var results = await Future.wait(futures);
for (var result in results) {
expect(utf8.decode(result), _smallFileContents);
}
}, timeout: const Timeout.factor(2));
});
group('AssetFileSystem with a noisy server', () {
setUpAll(() async {
var hostname = 'localhost';
var port = await findUnusedPort();
server = await HttpMultiServer.bind(hostname, port);
fileSystem =
AssetFileSystem(StandardFileSystem.instance, hostname, '$port');
serveRequests(server, noisyHandler);
});
tearDownAll(() async {
await expectLater(server.close(), completes);
});
test('can tell if file exists', () async {
var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
expect(await entity.exists(), true);
});
test('can tell if file does not exist', () async {
var entity = fileSystem.entityForUri(Uri.parse(_nonExistingFile));
expect(await entity.exists(), false);
});
test('can read existing file using readAsBytes', () async {
var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
expect(await entity.readAsBytes(), _largeFileBytes());
});
test('can read and decode existing file using readAsBytes', () async {
var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
expect(utf8.decode(await entity.readAsBytes()), _largeFileContents());
});
test('can read existing file using readAsString', () async {
var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
expect(await entity.readAsString(), _largeFileContents());
});
test('cannot read non-existing file', () async {
var entity = fileSystem.entityForUri(Uri.parse(_nonExistingFile));
await expectLater(
entity.readAsBytes(), throwsA(isA<FileSystemException>()));
});
test('readAsString is faster than decoding result of readAsBytes',
() async {
var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
var elapsedReadAsString = () async {
var stopwatch = Stopwatch()..start();
await expectLater(entity.readAsString(), isNotNull);
return stopwatch.elapsedMilliseconds;
};
var elapsedReadAsBytesAndDecode = () async {
var stopwatch = Stopwatch()..start();
await expectLater(utf8.decode(await entity.readAsBytes()), isNotNull);
return stopwatch.elapsedMilliseconds;
};
await expectLater(await elapsedReadAsString(),
lessThan(await elapsedReadAsBytesAndDecode()));
});
test('can read a lot of files concurrently', () async {
var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
var futures = [
for (var i = 0; i < 512; i++) entity.readAsBytes(),
];
var results = await Future.wait(futures);
var fileContents = _largeFileContents();
for (var result in results) {
expect(utf8.decode(result), fileContents);
}
}, timeout: const Timeout.factor(2));
});
}