Index: test/descriptor_server.dart |
diff --git a/test/descriptor_server.dart b/test/descriptor_server.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4270dc6a840dd7fe7dbe6ca8174865ed6134b963 |
--- /dev/null |
+++ b/test/descriptor_server.dart |
@@ -0,0 +1,124 @@ |
+// Copyright (c) 2016, 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. |
+ |
+import 'dart:async'; |
+import 'dart:io'; |
+ |
+import 'package:path/path.dart' as p; |
+import 'package:pub/src/utils.dart'; |
+import 'package:scheduled_test/scheduled_test.dart' hide fail; |
+import 'package:shelf/shelf.dart' as shelf; |
+import 'package:shelf/shelf_io.dart' as shelf_io; |
+ |
+import 'descriptor.dart' as d; |
+ |
+/// The global [DescriptorServer] that's used by default. |
+/// |
+/// `null` if there's no global server in use. This can be set to replace the |
+/// existing global server. |
+DescriptorServer get globalServer => _globalServer; |
+set globalServer(DescriptorServer value) { |
+ if (_globalServer == null) { |
+ currentSchedule.onComplete.schedule(() { |
+ _globalServer = null; |
+ }, 'clearing the global server'); |
+ } else { |
+ _globalServer.close(); |
+ } |
+ |
+ _globalServer = value; |
+} |
+DescriptorServer _globalServer; |
+ |
+/// Creates a global [DescriptorServer] to serve [contents] as static files. |
+/// |
+/// This server will exist only for the duration of the pub run. It's accessible |
+/// via [server]. Subsequent calls to [serve] replace the previous server. |
+void serve([List<d.Descriptor> contents]) { |
+ globalServer = new DescriptorServer(contents); |
+} |
+ |
+/// Like [serve], but reports an error if a request ever comes in to the server. |
+void serveErrors() { |
+ globalServer = new DescriptorServer.errors(); |
+} |
+ |
+class DescriptorServer { |
+ /// The server, or `null` before it's available. |
+ HttpServer _server; |
+ |
+ /// A future that will complete to the port used for the server. |
+ Future<int> get port => _portCompleter.future; |
+ final _portCompleter = new Completer<int>(); |
+ |
+ /// Gets the list of paths that have been requested from the server. |
+ Future<List<String>> get requestedPaths => |
+ schedule(() => _requestedPaths.toList(), |
+ "get previous network requests"); |
+ |
+ /// The list of paths that have been requested from this server. |
+ final _requestedPaths = <String>[]; |
+ |
+ /// Creates an HTTP server to serve [contents] as static files. |
+ /// |
+ /// This server exists only for the duration of the pub run. Subsequent calls |
+ /// to [serve] replace the previous server. |
+ DescriptorServer([List<d.Descriptor> contents]) { |
+ var baseDir = d.dir("serve-dir", contents); |
+ |
+ schedule(() async { |
+ _server = await shelf_io.serve((request) async { |
+ var path = p.posix.fromUri(request.url.path); |
+ _requestedPaths.add(path); |
+ |
+ try { |
+ var stream = await validateStream(baseDir.load(path)); |
+ return new shelf.Response.ok(stream); |
+ } catch (_) { |
+ return new shelf.Response.notFound('File "$path" not found.'); |
+ } |
+ }, 'localhost', 0); |
+ |
+ _portCompleter.complete(_server.port); |
+ _closeOnComplete(); |
+ }, 'starting a server serving:\n${baseDir.describe()}'); |
+ } |
+ |
+ /// Creates a server that reports an error if a request is ever received. |
+ DescriptorServer.errors() { |
+ schedule(() async { |
+ _server = await shelf_io.serve((request) { |
+ fail("The HTTP server received an unexpected request:\n" |
+ "${request.method} ${request.requestedUri}"); |
+ return new shelf.Response.forbidden(null); |
+ }, 'localhost', 0); |
+ |
+ _portCompleter.complete(_server.port); |
+ _closeOnComplete(); |
+ }); |
+ } |
+ |
+ /// Schedules [requestedPaths] to be emptied. |
+ void clearRequestedPaths() { |
+ schedule(() { |
+ _requestedPaths.clear(); |
+ }, "clearing requested paths"); |
+ } |
+ |
+ /// Schedules the closing of this server. |
+ void close() { |
+ schedule(() async { |
+ if (_server == null) return; |
+ await _server.close(); |
+ }, "closing DescriptorServer"); |
+ } |
+ |
+ /// Schedules this server to close once the schedule is done. |
+ void _closeOnComplete() { |
+ currentSchedule.onComplete.schedule(() async { |
+ if (_server == null) return; |
+ await _server.close(); |
+ }, "closing DescriptorServer"); |
+ } |
+} |