Skip to content

Commit 74f9d3d

Browse files
authored
Add conformances test that verify that the Client works in Isolates (#889)
1 parent ee03604 commit 74f9d3d

File tree

8 files changed

+89
-15
lines changed

8 files changed

+89
-15
lines changed

pkgs/cronet_http/example/integration_test/client_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import 'package:integration_test/integration_test.dart';
99
import 'package:test/test.dart';
1010

1111
void testClientConformance(CronetClient Function() clientFactory) {
12-
testAll(clientFactory, canStreamRequestBody: false);
12+
testAll(clientFactory, canStreamRequestBody: false, canWorkInIsolates: false);
1313
}
1414

1515
Future<void> testConformance() async {

pkgs/cronet_http/example/integration_test/cronet_configuration_test.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
/// Tests various [CronetEngine] configurations.
6-
library;
7-
85
import 'dart:io';
96

107
import 'package:cronet_http/cronet_http.dart';

pkgs/cronet_http/lib/src/messages.dart

Lines changed: 16 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkgs/cupertino_http/example/integration_test/client_conformance_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ void main() {
1717
group('fromSessionConfiguration', () {
1818
final config = URLSessionConfiguration.ephemeralSessionConfiguration();
1919
testAll(() => CupertinoClient.fromSessionConfiguration(config),
20-
canStreamRequestBody: false);
20+
canStreamRequestBody: false, canWorkInIsolates: false);
2121
});
2222
}

pkgs/http/test/html/client_conformance_test.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ void main() {
1313
testAll(BrowserClient.new,
1414
redirectAlwaysAllowed: true,
1515
canStreamRequestBody: false,
16-
canStreamResponseBody: false);
16+
canStreamResponseBody: false,
17+
canWorkInIsolates: false);
1718
}

pkgs/http_client_conformance_tests/lib/http_client_conformance_tests.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:http/http.dart';
66

77
import 'src/close_tests.dart';
88
import 'src/compressed_response_body_tests.dart';
9+
import 'src/isolate_test.dart';
910
import 'src/multiple_clients_tests.dart';
1011
import 'src/redirect_tests.dart';
1112
import 'src/request_body_streamed_tests.dart';
@@ -19,6 +20,7 @@ import 'src/server_errors_test.dart';
1920
export 'src/close_tests.dart' show testClose;
2021
export 'src/compressed_response_body_tests.dart'
2122
show testCompressedResponseBody;
23+
export 'src/isolate_test.dart' show testIsolate;
2224
export 'src/multiple_clients_tests.dart' show testMultipleClients;
2325
export 'src/redirect_tests.dart' show testRedirect;
2426
export 'src/request_body_streamed_tests.dart' show testRequestBodyStreamed;
@@ -42,13 +44,17 @@ export 'src/server_errors_test.dart' show testServerErrors;
4244
/// If [redirectAlwaysAllowed] is `true` then tests that require the [Client]
4345
/// to limit redirects will be skipped.
4446
///
47+
/// If [canWorkInIsolates] is `false` then tests that require that the [Client]
48+
/// work in Isolates other than the main isolate will be skipped.
49+
///
4550
/// The tests are run against a series of HTTP servers that are started by the
4651
/// tests. If the tests are run in the browser, then the test servers are
4752
/// started in another process. Otherwise, the test servers are run in-process.
4853
void testAll(Client Function() clientFactory,
4954
{bool canStreamRequestBody = true,
5055
bool canStreamResponseBody = true,
51-
bool redirectAlwaysAllowed = false}) {
56+
bool redirectAlwaysAllowed = false,
57+
bool canWorkInIsolates = true}) {
5258
testRequestBody(clientFactory());
5359
testRequestBodyStreamed(clientFactory(),
5460
canStreamRequestBody: canStreamRequestBody);
@@ -63,4 +69,5 @@ void testAll(Client Function() clientFactory,
6369
testCompressedResponseBody(clientFactory());
6470
testMultipleClients(clientFactory);
6571
testClose(clientFactory);
72+
testIsolate(clientFactory, canWorkInIsolates: canWorkInIsolates);
6673
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import 'dart:async';
2+
3+
// ignore: avoid_classes_with_only_static_members
4+
/// An Isolate implementation for the web that throws when used.
5+
abstract class Isolate {
6+
static Future<R> run<R>(FutureOr<R> Function() computation,
7+
{String? debugName}) =>
8+
throw ArgumentError.value('true', 'canWorkInIsolates',
9+
'isolate tests are not supported on the web');
10+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:isolate' if (dart.library.html) 'dummy_isolate.dart';
6+
7+
import 'package:async/async.dart';
8+
import 'package:http/http.dart';
9+
import 'package:stream_channel/stream_channel.dart';
10+
import 'package:test/test.dart';
11+
12+
import 'request_body_server_vm.dart'
13+
if (dart.library.html) 'request_body_server_web.dart';
14+
15+
Future<void> _testPost(Client Function() clientFactory, String host) async {
16+
await Isolate.run(
17+
() => clientFactory().post(Uri.http(host, ''), body: 'Hello World!'));
18+
}
19+
20+
/// Tests that the [Client] is useable from Isolates other than the main
21+
/// isolate.
22+
///
23+
/// If [canWorkInIsolates] is `false` then the tests will be skipped.
24+
void testIsolate(Client Function() clientFactory,
25+
{bool canWorkInIsolates = true}) {
26+
group('test isolate', () {
27+
late final String host;
28+
late final StreamChannel<Object?> httpServerChannel;
29+
late final StreamQueue<Object?> httpServerQueue;
30+
31+
setUpAll(() async {
32+
httpServerChannel = await startServer();
33+
httpServerQueue = StreamQueue(httpServerChannel.stream);
34+
host = 'localhost:${await httpServerQueue.next}';
35+
});
36+
tearDownAll(() => httpServerChannel.sink.add(null));
37+
38+
test('client.post() with string body', () async {
39+
await _testPost(clientFactory, host);
40+
41+
final serverReceivedContentType = await httpServerQueue.next;
42+
final serverReceivedBody = await httpServerQueue.next;
43+
44+
expect(serverReceivedContentType, ['text/plain; charset=utf-8']);
45+
expect(serverReceivedBody, 'Hello World!');
46+
});
47+
},
48+
skip: canWorkInIsolates
49+
? false
50+
: 'does not work outside of the main isolate');
51+
}

0 commit comments

Comments
 (0)