blob: 564ccd8155a6b35840070a0e409cca537da14d68 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. 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:convert';
import 'dart:typed_data';
import 'package:litetest/litetest.dart';
import 'package:zircon/zircon.dart';
/// Helper method to turn a [String] into a [ByteData] containing the
/// text of the string encoded as UTF-8.
ByteData utf8Bytes(final String text) {
return ByteData.view(Uint8List.fromList(utf8.encode(text)).buffer);
}
void main() {
test('create channel', () {
final HandlePairResult pair = System.channelCreate();
expect(pair.status, equals(ZX.OK));
expect(pair.first.isValid, isTrue);
expect(pair.second.isValid, isTrue);
});
test('[ffi] create channel', () {
final ZDChannel? channel = ZDChannel.create();
expect(channel, isNotNull);
final ZDHandlePair pair = channel!.handlePair;
expect(pair.left.isValid(), isTrue);
expect(pair.right.isValid(), isTrue);
});
test('close channel', () {
final HandlePairResult pair = System.channelCreate();
expect(pair.first.close(), equals(0));
expect(pair.first.isValid, isFalse);
expect(pair.second.isValid, isTrue);
expect(System.channelWrite(pair.first, ByteData(1), <Handle>[]),
equals(ZX.ERR_BAD_HANDLE));
expect(System.channelWrite(pair.second, ByteData(1), <Handle>[]),
equals(ZX.ERR_PEER_CLOSED));
});
test('[ffi] close channel', () {
final ZDChannel? channel = ZDChannel.create();
final ZDHandlePair pair = channel!.handlePair;
expect(pair.left.close(), isTrue);
expect(pair.left.isValid, isFalse);
expect(pair.right.isValid, isTrue);
expect(channel.writeLeft(ByteData(1), <ZDHandle>[]),
equals(ZX.ERR_BAD_HANDLE));
expect(channel.writeRight(ByteData(1), <ZDHandle>[]),
equals(ZX.ERR_PEER_CLOSED));
});
test('channel bytes', () {
final HandlePairResult pair = System.channelCreate();
// When no data is available, ZX.ERR_SHOULD_WAIT is returned.
expect(System.channelQueryAndRead(pair.second).status,
equals(ZX.ERR_SHOULD_WAIT));
// Write bytes.
final ByteData data = utf8Bytes('Hello, world');
final int status = System.channelWrite(pair.first, data, <Handle>[]);
expect(status, equals(ZX.OK));
// Read bytes.
final ReadResult readResult = System.channelQueryAndRead(pair.second);
expect(readResult.status, equals(ZX.OK));
expect(readResult.numBytes, equals(data.lengthInBytes));
expect(readResult.bytes.lengthInBytes, equals(data.lengthInBytes));
expect(readResult.bytesAsUTF8String(), equals('Hello, world'));
expect(readResult.handles.length, equals(0));
});
test('channel handles', () {
final HandlePairResult pair = System.channelCreate();
final ByteData data = utf8Bytes('');
final HandlePairResult eventPair = System.eventpairCreate();
final int status =
System.channelWrite(pair.first, data, <Handle>[eventPair.first]);
expect(status, equals(ZX.OK));
expect(eventPair.first.isValid, isFalse);
final ReadResult readResult = System.channelQueryAndRead(pair.second);
expect(readResult.status, equals(ZX.OK));
expect(readResult.numBytes, equals(0));
expect(readResult.bytes.lengthInBytes, equals(0));
expect(readResult.bytesAsUTF8String(), equals(''));
expect(readResult.handles.length, equals(1));
expect(readResult.handles[0].isValid, isTrue);
});
group('etc functions', () {
test('moved handle', () {
final HandlePairResult pair = System.channelCreate();
final ByteData data = utf8Bytes('');
final HandlePairResult transferred = System.channelCreate();
final HandleDisposition disposition = HandleDisposition(ZX.HANDLE_OP_MOVE,
transferred.first, ZX.OBJ_TYPE_CHANNEL, ZX.RIGHTS_IO);
final int status = System.channelWriteEtc(
pair.first, data, <HandleDisposition>[disposition]);
expect(status, equals(ZX.OK));
expect(disposition.result, equals(ZX.OK));
expect(transferred.first.isValid, isFalse);
final ReadEtcResult readResult =
System.channelQueryAndReadEtc(pair.second);
expect(readResult.status, equals(ZX.OK));
expect(readResult.numBytes, equals(0));
expect(readResult.bytes.lengthInBytes, equals(0));
expect(readResult.bytesAsUTF8String(), equals(''));
expect(readResult.handleInfos.length, equals(1));
final HandleInfo handleInfo = readResult.handleInfos[0];
expect(handleInfo.handle.isValid, isTrue);
expect(handleInfo.type, equals(ZX.OBJ_TYPE_CHANNEL));
expect(handleInfo.rights, equals(ZX.RIGHTS_IO));
});
test('copied handle', () {
final HandlePairResult pair = System.channelCreate();
final ByteData data = utf8Bytes('');
final HandleResult vmo = System.vmoCreate(0);
final HandleDisposition disposition = HandleDisposition(
ZX.HANDLE_OP_DUPLICATE,
vmo.handle,
ZX.OBJ_TYPE_VMO,
ZX.RIGHT_SAME_RIGHTS);
final int status = System.channelWriteEtc(
pair.first, data, <HandleDisposition>[disposition]);
expect(status, equals(ZX.OK));
expect(disposition.result, equals(ZX.OK));
expect(vmo.handle.isValid, isTrue);
final ReadEtcResult readResult =
System.channelQueryAndReadEtc(pair.second);
expect(readResult.status, equals(ZX.OK));
expect(readResult.numBytes, equals(0));
expect(readResult.bytes.lengthInBytes, equals(0));
expect(readResult.bytesAsUTF8String(), equals(''));
expect(readResult.handleInfos.length, equals(1));
final HandleInfo handleInfo = readResult.handleInfos[0];
expect(handleInfo.handle.isValid, isTrue);
expect(handleInfo.type, equals(ZX.OBJ_TYPE_VMO));
expect(handleInfo.rights, equals(ZX.DEFAULT_VMO_RIGHTS));
});
test('closed handle should error', () {
final HandlePairResult pair = System.channelCreate();
final ByteData data = utf8Bytes('');
final HandlePairResult closed = System.channelCreate();
final HandleDisposition disposition = HandleDisposition(ZX.HANDLE_OP_MOVE,
closed.first, ZX.OBJ_TYPE_CHANNEL, ZX.RIGHT_SAME_RIGHTS);
closed.first.close();
final int status = System.channelWriteEtc(
pair.first, data, <HandleDisposition>[disposition]);
expect(status, equals(ZX.ERR_BAD_HANDLE));
expect(disposition.result, equals(ZX.ERR_BAD_HANDLE));
expect(closed.first.isValid, isFalse);
final ReadEtcResult readResult =
System.channelQueryAndReadEtc(pair.second);
expect(readResult.status, equals(ZX.ERR_SHOULD_WAIT));
});
test('multiple handles', () {
final HandlePairResult pair = System.channelCreate();
final ByteData data = utf8Bytes('');
final HandlePairResult transferred = System.channelCreate();
final HandleResult vmo = System.vmoCreate(0);
final List<HandleDisposition> dispositions = [
HandleDisposition(ZX.HANDLE_OP_MOVE, transferred.first,
ZX.OBJ_TYPE_CHANNEL, ZX.RIGHTS_IO),
HandleDisposition(ZX.HANDLE_OP_DUPLICATE, vmo.handle, ZX.OBJ_TYPE_VMO,
ZX.RIGHT_SAME_RIGHTS)
];
final int status = System.channelWriteEtc(pair.first, data, dispositions);
expect(status, equals(ZX.OK));
expect(dispositions[0].result, equals(ZX.OK));
expect(dispositions[1].result, equals(ZX.OK));
expect(transferred.first.isValid, isFalse);
expect(vmo.handle.isValid, isTrue);
final ReadEtcResult readResult =
System.channelQueryAndReadEtc(pair.second);
expect(readResult.status, equals(ZX.OK));
expect(readResult.numBytes, equals(0));
expect(readResult.bytes.lengthInBytes, equals(0));
expect(readResult.bytesAsUTF8String(), equals(''));
expect(readResult.handleInfos.length, equals(2));
final HandleInfo handleInfo = readResult.handleInfos[0];
expect(handleInfo.handle.isValid, isTrue);
expect(handleInfo.type, equals(ZX.OBJ_TYPE_CHANNEL));
expect(handleInfo.rights, equals(ZX.RIGHTS_IO));
final HandleInfo vmoInfo = readResult.handleInfos[1];
expect(vmoInfo.handle.isValid, isTrue);
expect(vmoInfo.type, equals(ZX.OBJ_TYPE_VMO));
expect(vmoInfo.rights, equals(ZX.DEFAULT_VMO_RIGHTS));
});
});
test('async wait channel read', () async {
final HandlePairResult pair = System.channelCreate();
final Completer<List<int>> completer = Completer<List<int>>();
pair.first.asyncWait(ZX.CHANNEL_READABLE, (int status, int pending) {
completer.complete(<int>[status, pending]);
});
expect(completer.isCompleted, isFalse);
System.channelWrite(pair.second, utf8Bytes('Hi'), <Handle>[]);
final List<int> result = await completer.future;
expect(result[0], equals(ZX.OK)); // status
expect(result[1] & ZX.CHANNEL_READABLE,
equals(ZX.CHANNEL_READABLE)); // pending
});
test('async wait channel closed', () async {
final HandlePairResult pair = System.channelCreate();
final Completer<int> completer = Completer<int>();
pair.first.asyncWait(ZX.CHANNEL_PEER_CLOSED, (int status, int pending) {
completer.complete(status);
});
expect(completer.isCompleted, isFalse);
pair.second.close();
final int status = await completer.future;
expect(status, equals(ZX.OK));
});
}