| // Copyright (c) 2015, 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:async'; | |
| import 'package:http2/src/frames/frames.dart'; | |
| import 'package:http2/src/ping/ping_handler.dart'; | |
| import 'package:mockito/mockito.dart'; | |
| import 'package:test/test.dart'; | |
| import '../error_matchers.dart'; | |
| void main() { | |
| group('ping-handler', () { | |
| test('successful-ping', () async { | |
| var writer = FrameWriterMock(); | |
| var pingHandler = instantiateHandler(writer); | |
| var p1 = pingHandler.ping(); | |
| var p2 = pingHandler.ping(); | |
| verifyInOrder([ | |
| writer.writePingFrame(1), | |
| writer.writePingFrame(2), | |
| ]); | |
| var header = FrameHeader(8, FrameType.PING, PingFrame.FLAG_ACK, 0); | |
| pingHandler.processPingFrame(PingFrame(header, 1)); | |
| var header2 = FrameHeader(8, FrameType.PING, PingFrame.FLAG_ACK, 0); | |
| pingHandler.processPingFrame(PingFrame(header2, 2)); | |
| await p1; | |
| await p2; | |
| verifyNoMoreInteractions(writer); | |
| }); | |
| test('successful-ack-to-remote-ping', () async { | |
| var writer = FrameWriterMock(); | |
| var pingHandler = instantiateHandler(writer); | |
| var header = FrameHeader(8, FrameType.PING, 0, 0); | |
| pingHandler.processPingFrame(PingFrame(header, 1)); | |
| var header2 = FrameHeader(8, FrameType.PING, 0, 0); | |
| pingHandler.processPingFrame(PingFrame(header2, 2)); | |
| verifyInOrder([ | |
| writer.writePingFrame(1, ack: true), | |
| writer.writePingFrame(2, ack: true) | |
| ]); | |
| verifyNoMoreInteractions(writer); | |
| }); | |
| test('ping-unknown-opaque-data', () async { | |
| var writer = FrameWriterMock(); | |
| var pingHandler = instantiateHandler(writer); | |
| var future = pingHandler.ping(); | |
| verify(writer.writePingFrame(1)).called(1); | |
| var header = FrameHeader(8, FrameType.PING, PingFrame.FLAG_ACK, 0); | |
| expect(() => pingHandler.processPingFrame(PingFrame(header, 2)), | |
| throwsA(isProtocolException)); | |
| // Ensure outstanding pings will be completed with an error once we call | |
| // `pingHandler.terminate()`. | |
| unawaited(future.catchError(expectAsync2((Object error, Object _) { | |
| expect(error, 'hello world'); | |
| }))); | |
| pingHandler.terminate('hello world'); | |
| verifyNoMoreInteractions(writer); | |
| }); | |
| test('terminate-ping-handler', () async { | |
| var writer = FrameWriterMock(); | |
| var pingHandler = instantiateHandler(writer); | |
| pingHandler.terminate('hello world'); | |
| expect( | |
| () => pingHandler.processPingFrame(PingFrame( | |
| FrameHeader(8, FrameType.PING, PingFrame.FLAG_ACK, 1), 1)), | |
| throwsA(isTerminatedException)); | |
| expect(pingHandler.ping(), throwsA(isTerminatedException)); | |
| verifyZeroInteractions(writer); | |
| }); | |
| test('ping-non-zero-stream-id', () async { | |
| var writer = FrameWriterMock(); | |
| var pingHandler = instantiateHandler(writer); | |
| var header = FrameHeader(8, FrameType.PING, PingFrame.FLAG_ACK, 1); | |
| expect(() => pingHandler.processPingFrame(PingFrame(header, 1)), | |
| throwsA(isProtocolException)); | |
| verifyZeroInteractions(writer); | |
| }); | |
| test('receiving-ping-calls-stream', () async { | |
| final pings = <int>[]; | |
| final writer = FrameWriterMock(); | |
| final pingStream = StreamController<int>()..stream.listen(pings.add); | |
| PingHandler(writer, pingStream) | |
| ..processPingFrame(PingFrame( | |
| FrameHeader(8, FrameType.PING, 0, 0), | |
| 1, | |
| )) | |
| ..processPingFrame(PingFrame( | |
| FrameHeader(8, FrameType.PING, 0, 0), | |
| 2, | |
| )); | |
| await pingStream.close(); | |
| expect(pings, [1, 2]); | |
| }); | |
| }); | |
| } | |
| PingHandler instantiateHandler(FrameWriterMock writer) { | |
| var controller = StreamController<int>(); | |
| return PingHandler(writer, controller); | |
| } | |
| class FrameWriterMock extends Mock implements FrameWriter {} |