Skip to content

Commit

Permalink
Add conformances test that verify that the Client works in Isolates (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
brianquinlan authored Mar 9, 2023
1 parent ee03604 commit 74f9d3d
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 15 deletions.
2 changes: 1 addition & 1 deletion pkgs/cronet_http/example/integration_test/client_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import 'package:integration_test/integration_test.dart';
import 'package:test/test.dart';

void testClientConformance(CronetClient Function() clientFactory) {
testAll(clientFactory, canStreamRequestBody: false);
testAll(clientFactory, canStreamRequestBody: false, canWorkInIsolates: false);
}

Future<void> testConformance() async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
// 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.

/// Tests various [CronetEngine] configurations.
library;

import 'dart:io';

import 'package:cronet_http/cronet_http.dart';
Expand Down
24 changes: 16 additions & 8 deletions pkgs/cronet_http/lib/src/messages.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ void main() {
group('fromSessionConfiguration', () {
final config = URLSessionConfiguration.ephemeralSessionConfiguration();
testAll(() => CupertinoClient.fromSessionConfiguration(config),
canStreamRequestBody: false);
canStreamRequestBody: false, canWorkInIsolates: false);
});
}
3 changes: 2 additions & 1 deletion pkgs/http/test/html/client_conformance_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ void main() {
testAll(BrowserClient.new,
redirectAlwaysAllowed: true,
canStreamRequestBody: false,
canStreamResponseBody: false);
canStreamResponseBody: false,
canWorkInIsolates: false);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:http/http.dart';

import 'src/close_tests.dart';
import 'src/compressed_response_body_tests.dart';
import 'src/isolate_test.dart';
import 'src/multiple_clients_tests.dart';
import 'src/redirect_tests.dart';
import 'src/request_body_streamed_tests.dart';
Expand All @@ -19,6 +20,7 @@ import 'src/server_errors_test.dart';
export 'src/close_tests.dart' show testClose;
export 'src/compressed_response_body_tests.dart'
show testCompressedResponseBody;
export 'src/isolate_test.dart' show testIsolate;
export 'src/multiple_clients_tests.dart' show testMultipleClients;
export 'src/redirect_tests.dart' show testRedirect;
export 'src/request_body_streamed_tests.dart' show testRequestBodyStreamed;
Expand All @@ -42,13 +44,17 @@ export 'src/server_errors_test.dart' show testServerErrors;
/// If [redirectAlwaysAllowed] is `true` then tests that require the [Client]
/// to limit redirects will be skipped.
///
/// If [canWorkInIsolates] is `false` then tests that require that the [Client]
/// work in Isolates other than the main isolate will be skipped.
///
/// The tests are run against a series of HTTP servers that are started by the
/// tests. If the tests are run in the browser, then the test servers are
/// started in another process. Otherwise, the test servers are run in-process.
void testAll(Client Function() clientFactory,
{bool canStreamRequestBody = true,
bool canStreamResponseBody = true,
bool redirectAlwaysAllowed = false}) {
bool redirectAlwaysAllowed = false,
bool canWorkInIsolates = true}) {
testRequestBody(clientFactory());
testRequestBodyStreamed(clientFactory(),
canStreamRequestBody: canStreamRequestBody);
Expand All @@ -63,4 +69,5 @@ void testAll(Client Function() clientFactory,
testCompressedResponseBody(clientFactory());
testMultipleClients(clientFactory);
testClose(clientFactory);
testIsolate(clientFactory, canWorkInIsolates: canWorkInIsolates);
}
10 changes: 10 additions & 0 deletions pkgs/http_client_conformance_tests/lib/src/dummy_isolate.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'dart:async';

// ignore: avoid_classes_with_only_static_members
/// An Isolate implementation for the web that throws when used.
abstract class Isolate {
static Future<R> run<R>(FutureOr<R> Function() computation,
{String? debugName}) =>
throw ArgumentError.value('true', 'canWorkInIsolates',
'isolate tests are not supported on the web');
}
51 changes: 51 additions & 0 deletions pkgs/http_client_conformance_tests/lib/src/isolate_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// 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.

import 'dart:isolate' if (dart.library.html) 'dummy_isolate.dart';

import 'package:async/async.dart';
import 'package:http/http.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:test/test.dart';

import 'request_body_server_vm.dart'
if (dart.library.html) 'request_body_server_web.dart';

Future<void> _testPost(Client Function() clientFactory, String host) async {
await Isolate.run(
() => clientFactory().post(Uri.http(host, ''), body: 'Hello World!'));
}

/// Tests that the [Client] is useable from Isolates other than the main
/// isolate.
///
/// If [canWorkInIsolates] is `false` then the tests will be skipped.
void testIsolate(Client Function() clientFactory,
{bool canWorkInIsolates = true}) {
group('test isolate', () {
late final String host;
late final StreamChannel<Object?> httpServerChannel;
late final StreamQueue<Object?> httpServerQueue;

setUpAll(() async {
httpServerChannel = await startServer();
httpServerQueue = StreamQueue(httpServerChannel.stream);
host = 'localhost:${await httpServerQueue.next}';
});
tearDownAll(() => httpServerChannel.sink.add(null));

test('client.post() with string body', () async {
await _testPost(clientFactory, host);

final serverReceivedContentType = await httpServerQueue.next;
final serverReceivedBody = await httpServerQueue.next;

expect(serverReceivedContentType, ['text/plain; charset=utf-8']);
expect(serverReceivedBody, 'Hello World!');
});
},
skip: canWorkInIsolates
? false
: 'does not work outside of the main isolate');
}

0 comments on commit 74f9d3d

Please sign in to comment.