blob: 99bec26ab88d1ddabba5e10a8beb42f26648856d [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// ignore_for_file: implementation_imports
import 'dart:typed_data';
import 'package:fidl/fidl.dart';
import 'package:fidl_fuchsia_mem/fidl_async.dart' as fuchsia_mem;
import 'package:fidl_fuchsia_modular/fidl_async.dart' as fuchsia_modular;
import 'package:fidl_fuchsia_modular/fidl_test.dart' as fuchsia_modular_test;
import 'package:fuchsia_modular/src/entity/entity_exceptions.dart';
import 'package:fuchsia_modular/src/entity/internal/_entity_impl.dart';
import 'package:test/test.dart';
import 'package:zircon/zircon.dart';
void main() {
MockProxy proxy;
EntityImpl entity;
group('enity interactions', () {
setUp(() {
proxy = MockProxy();
entity = EntityImpl(proxyFactory: () => proxy, type: 'foo');
});
tearDown(() {
proxy = null;
entity = null;
});
test('getData returns correct data', () async {
final data = Uint8List.fromList([1, 2, 3]);
await entity.write(data);
expect(await entity.getData(), data);
});
test('write returns success for valid write', () async {
final data = Uint8List.fromList([1, 2, 3]);
await entity.write(data);
// test will fail if write fails
});
test('write fails for error in write', () async {
proxy.writeStatus = fuchsia_modular.EntityWriteStatus.error;
final data = Uint8List.fromList([1, 2, 3]);
expect(entity.write(data),
throwsA(const TypeMatcher<EntityWriteException>()));
});
test('write fails for readonly', () async {
proxy.writeStatus = fuchsia_modular.EntityWriteStatus.readOnly;
final data = Uint8List.fromList([1, 2, 3]);
expect(entity.write(data),
throwsA(const TypeMatcher<EntityWriteException>()));
});
test('getEntityReference returns the correct ref', () async {
proxy.entityReference = 'my-entity';
expect(await entity.getEntityReference(), 'my-entity');
});
test('watch closes stream when binding is closed', () {
proxy.forceCloseWatchers = true;
final stream = entity.watch();
expect(stream, emitsInOrder([emitsDone]));
});
test('watch udpates stream', () async {
Uint8List _bufferWithValue(int v) {
final data = ByteData(1)..setInt8(0, v);
return data.buffer.asUint8List();
}
int _getValue(Uint8List buffer) {
return ByteData.view(buffer.buffer).getInt8(0);
}
final stream = entity.watch();
expect(stream.map(_getValue), emitsInOrder([1, 2, 3]));
await entity.write(_bufferWithValue(1));
await entity.write(_bufferWithValue(2));
await entity.write(_bufferWithValue(3));
});
});
}
class MockProxy extends fuchsia_modular_test.Entity$TestBase {
Uint8List _data;
String entityReference;
List<fuchsia_modular.EntityWatcherProxy> watchers = [];
/// if set to true the watchers will be closed after they are added.
bool forceCloseWatchers = false;
/// Can be set to control how write results are handled.
fuchsia_modular.EntityWriteStatus writeStatus =
fuchsia_modular.EntityWriteStatus.ok;
@override
Future<fuchsia_mem.Buffer> getData(String _) async {
final vmo = SizedVmo.fromUint8List(_data);
final buffer = fuchsia_mem.Buffer(vmo: vmo, size: _data.length);
return buffer;
}
@override
Future<String> getReference() async => entityReference;
@override
Future<void> watch(String type,
InterfaceHandle<fuchsia_modular.EntityWatcher> watcher) async {
final proxy = fuchsia_modular.EntityWatcherProxy();
proxy.ctrl.bind(watcher);
watchers.add(proxy);
if (forceCloseWatchers) {
//ignore: unawaited_futures
Future(proxy.ctrl.close);
}
}
@override
Future<fuchsia_modular.EntityWriteStatus> writeData(
String type, fuchsia_mem.Buffer buffer) async {
if (writeStatus != fuchsia_modular.EntityWriteStatus.ok) {
return writeStatus;
}
final dataVmo = SizedVmo(buffer.vmo.handle, buffer.size);
final result = dataVmo.read(buffer.size);
dataVmo.close();
final data = result.bytesAsUint8List();
_setData(data, notify: true);
return fuchsia_modular.EntityWriteStatus.ok;
}
void _setData(Uint8List data, {bool notify = false}) {
_data = data;
if (notify) {
final vmo = SizedVmo.fromUint8List(data);
final buffer = fuchsia_mem.Buffer(vmo: vmo, size: data.length);
for (final watcher in watchers) {
if (watcher.ctrl.isBound) {
watcher.onUpdated(buffer);
}
}
}
}
}