|  | // Copyright (c) 2014, 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:convert'; | 
|  |  | 
|  | import 'package:json_rpc_2/error_code.dart' as error_code; | 
|  | import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc; | 
|  | import 'package:test/test.dart'; | 
|  |  | 
|  | import 'utils.dart'; | 
|  |  | 
|  | void main() { | 
|  | late ServerController controller; | 
|  |  | 
|  | setUp(() => controller = ServerController()); | 
|  |  | 
|  | test('calls a registered method with the given name', () { | 
|  | controller.server.registerMethod('foo', (json_rpc.Parameters params) { | 
|  | return {'params': params.value}; | 
|  | }); | 
|  |  | 
|  | expect( | 
|  | controller.handleRequest({ | 
|  | 'jsonrpc': '2.0', | 
|  | 'method': 'foo', | 
|  | 'params': {'param': 'value'}, | 
|  | 'id': 1234 | 
|  | }), | 
|  | completion(equals({ | 
|  | 'jsonrpc': '2.0', | 
|  | 'result': { | 
|  | 'params': {'param': 'value'} | 
|  | }, | 
|  | 'id': 1234 | 
|  | }))); | 
|  | }); | 
|  |  | 
|  | test('calls a method that takes no parameters', () { | 
|  | controller.server.registerMethod('foo', () => 'foo'); | 
|  |  | 
|  | expect( | 
|  | controller | 
|  | .handleRequest({'jsonrpc': '2.0', 'method': 'foo', 'id': 1234}), | 
|  | completion(equals({'jsonrpc': '2.0', 'result': 'foo', 'id': 1234}))); | 
|  | }); | 
|  |  | 
|  | test('Allows a `null` result', () { | 
|  | controller.server.registerMethod('foo', () => null); | 
|  |  | 
|  | expect( | 
|  | controller | 
|  | .handleRequest({'jsonrpc': '2.0', 'method': 'foo', 'id': 1234}), | 
|  | completion(equals({'jsonrpc': '2.0', 'result': null, 'id': 1234}))); | 
|  | }); | 
|  |  | 
|  | test('a method that takes no parameters rejects parameters', () { | 
|  | controller.server.registerMethod('foo', () => 'foo'); | 
|  |  | 
|  | expectErrorResponse( | 
|  | controller, | 
|  | { | 
|  | 'jsonrpc': '2.0', | 
|  | 'method': 'foo', | 
|  | 'params': <String, dynamic>{}, | 
|  | 'id': 1234 | 
|  | }, | 
|  | error_code.INVALID_PARAMS, | 
|  | 'No parameters are allowed for method "foo".'); | 
|  | }); | 
|  |  | 
|  | test('an unexpected error in a method is captured', () { | 
|  | controller.server | 
|  | .registerMethod('foo', () => throw const FormatException('bad format')); | 
|  |  | 
|  | expect( | 
|  | controller | 
|  | .handleRequest({'jsonrpc': '2.0', 'method': 'foo', 'id': 1234}), | 
|  | completion({ | 
|  | 'jsonrpc': '2.0', | 
|  | 'id': 1234, | 
|  | 'error': { | 
|  | 'code': error_code.SERVER_ERROR, | 
|  | 'message': 'bad format', | 
|  | 'data': { | 
|  | 'request': {'jsonrpc': '2.0', 'method': 'foo', 'id': 1234}, | 
|  | 'full': 'FormatException: bad format', | 
|  | 'stack': isA<String>() | 
|  | } | 
|  | } | 
|  | })); | 
|  | }); | 
|  |  | 
|  | test('doesn\'t return a result for a notification', () { | 
|  | controller.server.registerMethod('foo', (args) => 'result'); | 
|  |  | 
|  | expect( | 
|  | controller.handleRequest( | 
|  | {'jsonrpc': '2.0', 'method': 'foo', 'params': <String, dynamic>{}}), | 
|  | doesNotComplete); | 
|  | }); | 
|  |  | 
|  | test('includes the error data in the response', () { | 
|  | controller.server.registerMethod('foo', (params) { | 
|  | throw json_rpc.RpcException(5, 'Error message.', data: 'data value'); | 
|  | }); | 
|  |  | 
|  | expectErrorResponse( | 
|  | controller, | 
|  | { | 
|  | 'jsonrpc': '2.0', | 
|  | 'method': 'foo', | 
|  | 'params': <String, dynamic>{}, | 
|  | 'id': 1234 | 
|  | }, | 
|  | 5, | 
|  | 'Error message.', | 
|  | data: 'data value'); | 
|  | }); | 
|  |  | 
|  | test('a JSON parse error is rejected', () { | 
|  | return controller.handleJsonRequest('invalid json {').then((result) { | 
|  | expect(jsonDecode(result), { | 
|  | 'jsonrpc': '2.0', | 
|  | 'error': { | 
|  | 'code': error_code.PARSE_ERROR, | 
|  | 'message': startsWith('Invalid JSON: '), | 
|  | // TODO(nweiz): Always expect the source when sdk#25655 is fixed. | 
|  | 'data': { | 
|  | 'request': anyOf([isNull, 'invalid json {']) | 
|  | } | 
|  | }, | 
|  | 'id': null | 
|  | }); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | group('fallbacks', () { | 
|  | test('calls a fallback if no method matches', () { | 
|  | controller.server | 
|  | ..registerMethod('foo', () => 'foo') | 
|  | ..registerMethod('bar', () => 'foo') | 
|  | ..registerFallback((params) => {'fallback': params.value}); | 
|  |  | 
|  | expect( | 
|  | controller.handleRequest({ | 
|  | 'jsonrpc': '2.0', | 
|  | 'method': 'baz', | 
|  | 'params': {'param': 'value'}, | 
|  | 'id': 1234 | 
|  | }), | 
|  | completion(equals({ | 
|  | 'jsonrpc': '2.0', | 
|  | 'result': { | 
|  | 'fallback': {'param': 'value'} | 
|  | }, | 
|  | 'id': 1234 | 
|  | }))); | 
|  | }); | 
|  |  | 
|  | test('calls the first matching fallback', () { | 
|  | controller.server | 
|  | ..registerFallback((params) => | 
|  | throw json_rpc.RpcException.methodNotFound(params.method)) | 
|  | ..registerFallback((params) => 'fallback 2') | 
|  | ..registerFallback((params) => 'fallback 3'); | 
|  |  | 
|  | expect( | 
|  | controller.handleRequest( | 
|  | {'jsonrpc': '2.0', 'method': 'fallback 2', 'id': 1234}), | 
|  | completion( | 
|  | equals({'jsonrpc': '2.0', 'result': 'fallback 2', 'id': 1234}))); | 
|  | }); | 
|  |  | 
|  | test('an unexpected error in a fallback is captured', () { | 
|  | controller.server | 
|  | .registerFallback((_) => throw const FormatException('bad format')); | 
|  |  | 
|  | expect( | 
|  | controller | 
|  | .handleRequest({'jsonrpc': '2.0', 'method': 'foo', 'id': 1234}), | 
|  | completion({ | 
|  | 'jsonrpc': '2.0', | 
|  | 'id': 1234, | 
|  | 'error': { | 
|  | 'code': error_code.SERVER_ERROR, | 
|  | 'message': 'bad format', | 
|  | 'data': { | 
|  | 'request': {'jsonrpc': '2.0', 'method': 'foo', 'id': 1234}, | 
|  | 'full': 'FormatException: bad format', | 
|  | 'stack': isA<String>() | 
|  | } | 
|  | } | 
|  | })); | 
|  | }); | 
|  | }); | 
|  |  | 
|  | test('disallows multiple methods with the same name', () { | 
|  | controller.server.registerMethod('foo', () => null); | 
|  | expect(() => controller.server.registerMethod('foo', () => null), | 
|  | throwsArgumentError); | 
|  | }); | 
|  | } |