Skip to content

Commit

Permalink
Clean up the support matrix a bit, and what we do/don't test for acro…
Browse files Browse the repository at this point in the history
…ss platforms.
  • Loading branch information
bramp committed Feb 2, 2024
1 parent 183233c commit 212574d
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 34 deletions.
3 changes: 2 additions & 1 deletion melos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ scripts:
test:
run: |
melos run test:dart --no-select && \
melos run test:flutter --no-select
melos run test:flutter --no-select && \
melos run test:chrome --no-select
test:node:
run: melos run test:dart:node --no-select
Expand Down
15 changes: 15 additions & 0 deletions packages/pmtiles/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,21 @@ Future<int> main() async {
```

## Support Matrix

Some effort has been made to ensure this library works correctly on
the native Dart VM, as well as when dart2js is used to compiled to
JavaScript (e.g. for use with Node.js or Chrome). The following table
shows the support matrix.

| Feature | Dart VM | Node.js | Browsers (e.g Chrome) |
| ------: | :-----: | :-----: | :-------------------: |
| | Native | dart2js | dart2js |
| File | Yes | No | No |
| HTTP | Yes | No | Yes |

If the library is used in an UnsupportedError exception will be thrown.

## Development

Use `melos bootstrap` to install dependencies and link packages together.
Expand Down
8 changes: 3 additions & 5 deletions packages/pmtiles/lib/src/io.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ import 'dart:collection';
import 'dart:math' as math;
import 'package:http/http.dart';

// Browsers don't support the File APIs
export 'io_file.dart' if (dart.library.browser) 'io_file_fake.dart';
// JS don't support the File APIs
export 'io_file_fake.dart' if (dart.library.io) 'io_file.dart';

// Node doesn't support the HTTP APIs
// https://github.com/dart-lang/http/issues/1126
export 'io_http.dart' if (dart.library.node) 'io_http_fake.dart';
export 'io_http.dart';

/// Simple interface so we can abstract reading from Files, or Http.
abstract interface class ReadAt {
Expand Down
6 changes: 3 additions & 3 deletions packages/pmtiles/lib/src/io_file_fake.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import 'io.dart';

class FileAt implements ReadAt {
FileAt(Object file) {
throw UnimplementedError('File APIs are not implemented on the web');
throw UnsupportedError('File APIs are not supported for dart2js');
}

@override
Future<ByteStream> readAt(final int offset, final int length) async {
throw UnimplementedError('File APIs are not implemented on the web');
throw UnsupportedError('File APIs are not supported for dart2js');
}

@override
Future<void> close() {
throw UnimplementedError('File APIs are not implemented on the web');
throw UnsupportedError('File APIs are not supported for dart2js');
}
}
46 changes: 31 additions & 15 deletions packages/pmtiles/lib/src/io_http.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,43 @@ class HttpAt implements ReadAt {

@override
Future<ByteStream> readAt(int offset, int length) async {
final request = Request("GET", url);
try {
final request = Request("GET", url);

if (headers != null) request.headers.addAll(headers!);
request.headers[HttpHeaders.rangeHeader] =
'bytes=$offset-${offset + length - 1}';
if (headers != null) request.headers.addAll(headers!);
request.headers[HttpHeaders.rangeHeader] =
'bytes=$offset-${offset + length - 1}';

final response = await client.send(request);
final response = await client.send(request);

if (response.statusCode != 206) {
throw HttpException('Unexpected status code: ${response.statusCode}');
}
if (response.statusCode != 206) {
throw HttpException('Unexpected status code: ${response.statusCode}');
}

final responseLength = response.headers[HttpHeaders.contentLengthHeader];
if (responseLength != null && int.parse(responseLength) != length) {
throw HttpException(
'Unexpected Content-Length: $responseLength expected $length');
}
final responseLength = response.headers[HttpHeaders.contentLengthHeader];
if (responseLength != null && int.parse(responseLength) != length) {
throw HttpException(
'Unexpected Content-Length: $responseLength expected $length');
}

// TODO check Content-Range: bytes 0-1023/146515
// TODO check Content-Range: bytes 0-1023/146515

return response.stream;
return response.stream;
} catch (e) {
if (e
.toString()
.contains('Error: self.XMLHttpRequest is not a constructor')) {
// Node doesn't support the HTTP APIs
// https://github.com/dart-lang/http/issues/1126
//
// I don't know a better way to detect this, then after the error has
// happened. But hopefully this helps someone recongise what the odd
// error.
throw UnsupportedError('HTTP APIs are not supported for nodejs');
}

rethrow;
}
}

@override
Expand Down
6 changes: 3 additions & 3 deletions packages/pmtiles/lib/src/io_http_fake.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import 'io.dart';
class HttpAt implements ReadAt {
HttpAt(Object client, Uri url,
{Map<String, String>? headers, bool closeClient = false}) {
throw UnimplementedError('HTTP APIs are not implemented for nodejs');
throw UnsupportedError('HTTP APIs are not supported for nodejs');
}

@override
Future<ByteStream> readAt(final int offset, final int length) async {
throw UnimplementedError('HTTP APIs are not implemented for nodejs');
throw UnsupportedError('HTTP APIs are not supported for nodejs');
}

@override
Future<void> close() {
throw UnimplementedError('HTTP APIs are not implemented for nodejs');
throw UnsupportedError('HTTP APIs are not supported for nodejs');
}
}
10 changes: 6 additions & 4 deletions packages/pmtiles/test/io_file_test.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@TestOn('!browser') // Exclude from browsers because they doesn't support [File]
@TestOn('!js') // Exclude from js because they doesn't support [File]

import 'dart:io';
import 'dart:typed_data';
Expand All @@ -8,12 +8,12 @@ import 'package:test/test.dart';

void main() {
group('FileAt', () {
late Directory directory;
Directory? directory;
late File tempFile;

setUp(() async {
directory = await Directory.systemTemp.createTemp();
tempFile = File("${directory.path}/test_file");
tempFile = File("${directory!.path}/test_file");

final f = await tempFile.create();
await f.writeAsBytes(
Expand All @@ -22,7 +22,9 @@ void main() {
});

tearDown(() async {
await directory.delete(recursive: true);
if (directory != null) {
await directory!.delete(recursive: true);
}
});

final tests = <(int, int), List<int>>{
Expand Down
27 changes: 27 additions & 0 deletions packages/pmtiles/test/support_matrix_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'dart:io';

import 'package:pmtiles/src/io.dart';
import 'package:test/test.dart';
import 'package:http/http.dart' as http;

void main() {
test('File API is available', () {
expect(() => FileAt(File('/tmp/blah')), returnsNormally);
}, testOn: '!js');

test('File API is not available', () {
expect(() => FileAt(File('/tmp/blah')), throwsUnsupportedError);
}, testOn: 'js');

test('HTTP API is available', () {
final client = http.Client();
expect(() => HttpAt(client, Uri.parse("http://localhost/")).readAt(0, 1),
returnsNormally);
}, testOn: '!node');

test('HTTP API is not available', () {
final client = http.Client();
expect(() => HttpAt(client, Uri.parse("http://localhost/")).readAt(0, 1),
throwsUnsupportedError);
}, testOn: 'node');
}
1 change: 0 additions & 1 deletion packages/pmtiles_tests/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ dev_dependencies:
path: ^1.8.3
pmtiles: ^1.2.0
stream_channel: ^2.1.2

json_serializable: ^6.7.1
json_annotation: ^4.8.1
build_runner: ^2.4.8
Expand Down
2 changes: 1 addition & 1 deletion packages/pmtiles_tests/test/archive_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ void main() async {
}
}, onPlatform: {
...api == 'file'
? {'browser': Skip('File API is not supported in browsers')}
? {'js': Skip('File API is not supported in dart2js')}
: {},
}, timeout: Timeout(Duration(seconds: 90)));
}
Expand Down
2 changes: 1 addition & 1 deletion packages/pmtiles_tests/test/headers_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Exclude on browsers because it doesn't support the filesystem.
@TestOn('!browser')
@TestOn('!js')

import 'package:pmtiles/pmtiles.dart';

Expand Down
2 changes: 2 additions & 0 deletions packages/pmtiles_tests/test/simple_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ void main() async {
'invalid_v4.pmtiles': throwsA(isA<UnsupportedError>()),
'test_fixture_1.pmtiles': throwsA(isA<UnsupportedError>()),
'test_fixture_2.pmtiles': throwsA(isA<UnsupportedError>()),

// TODO Add a valid pmtiles file, that we can test against.
};

for (final e in fixtures.entries) {
Expand Down

0 comments on commit 212574d

Please sign in to comment.