blob: 4e7a38e1c1ac589c5005fa5d6df3509a36003b33 [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 'package:test/test.dart';
import 'package:pigeon/objc_generator.dart';
import 'package:pigeon/ast.dart';
void main() {
test('gen one class header', () {
final Root root = Root(apis: <Api>[], classes: <Class>[
Class(
name: 'Foobar',
fields: <Field>[Field(name: 'field1', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(), root, sink);
final String code = sink.toString();
expect(code, contains('@interface Foobar'));
expect(code, matches('@property.*NSString.*field1'));
});
test('gen one class source', () {
final Root root = Root(apis: <Api>[], classes: <Class>[
Class(
name: 'Foobar',
fields: <Field>[Field(name: 'field1', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(header: 'foo.h'), root, sink);
final String code = sink.toString();
expect(code, contains('#import "foo.h"'));
expect(code, contains('@implementation Foobar'));
});
test('gen one api header', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(name: 'doSomething', argType: 'Input', returnType: 'Output')
])
], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
Class(
name: 'Output',
fields: <Field>[Field(name: 'output', dataType: 'String')])
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(), root, sink);
final String code = sink.toString();
expect(code, contains('@interface Input'));
expect(code, contains('@interface Output'));
expect(code, contains('@protocol Api'));
expect(code, matches('nullable Output.*doSomething.*Input.*FlutterError'));
expect(code, matches('ApiSetup.*<Api>.*_Nullable'));
});
test('gen one api source', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(name: 'doSomething', argType: 'Input', returnType: 'Output')
])
], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
Class(
name: 'Output',
fields: <Field>[Field(name: 'output', dataType: 'String')])
]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(header: 'foo.h'), root, sink);
final String code = sink.toString();
expect(code, contains('#import "foo.h"'));
expect(code, contains('@implementation Input'));
expect(code, contains('@implementation Output'));
expect(code, contains('ApiSetup('));
});
test('all the simple datatypes header', () {
final Root root = Root(apis: <Api>[], classes: <Class>[
Class(name: 'Foobar', fields: <Field>[
Field(name: 'aBool', dataType: 'bool'),
Field(name: 'aInt', dataType: 'int'),
Field(name: 'aDouble', dataType: 'double'),
Field(name: 'aString', dataType: 'String'),
Field(name: 'aUint8List', dataType: 'Uint8List'),
Field(name: 'aInt32List', dataType: 'Int32List'),
Field(name: 'aInt64List', dataType: 'Int64List'),
Field(name: 'aFloat64List', dataType: 'Float64List'),
]),
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(header: 'foo.h'), root, sink);
final String code = sink.toString();
expect(code, contains('@interface Foobar'));
expect(code, contains('@class FlutterStandardTypedData;'));
expect(code, matches('@property.*strong.*NSNumber.*aBool'));
expect(code, matches('@property.*strong.*NSNumber.*aInt'));
expect(code, matches('@property.*strong.*NSNumber.*aDouble'));
expect(code, matches('@property.*copy.*NSString.*aString'));
expect(code,
matches('@property.*strong.*FlutterStandardTypedData.*aUint8List'));
expect(code,
matches('@property.*strong.*FlutterStandardTypedData.*aInt32List'));
expect(code,
matches('@property.*strong.*FlutterStandardTypedData.*Int64List'));
expect(code,
matches('@property.*strong.*FlutterStandardTypedData.*Float64List'));
});
test('bool source', () {
final Root root = Root(apis: <Api>[], classes: <Class>[
Class(name: 'Foobar', fields: <Field>[
Field(name: 'aBool', dataType: 'bool'),
]),
]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(header: 'foo.h'), root, sink);
final String code = sink.toString();
expect(code, contains('@implementation Foobar'));
expect(code, contains('result.aBool = dict[@"aBool"];'));
});
test('nested class header', () {
final Root root = Root(apis: <Api>[], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
Class(
name: 'Nested',
fields: <Field>[Field(name: 'nested', dataType: 'Input')])
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(header: 'foo.h'), root, sink);
final String code = sink.toString();
expect(code,
contains('@property(nonatomic, strong, nullable) Input * nested;'));
});
test('nested class source', () {
final Root root = Root(apis: <Api>[], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
Class(
name: 'Nested',
fields: <Field>[Field(name: 'nested', dataType: 'Input')])
]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(header: 'foo.h'), root, sink);
final String code = sink.toString();
expect(code, contains('result.nested = [Input fromMap:dict[@"nested"]];'));
expect(code, matches('[self.nested toMap].*@"nested"'));
});
test('prefix class header', () {
final Root root = Root(apis: <Api>[], classes: <Class>[
Class(
name: 'Foobar',
fields: <Field>[Field(name: 'field1', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(code, contains('@interface ABCFoobar'));
});
test('prefix class source', () {
final Root root = Root(apis: <Api>[], classes: <Class>[
Class(
name: 'Foobar',
fields: <Field>[Field(name: 'field1', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(code, contains('@implementation ABCFoobar'));
});
test('prefix nested class header', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(name: 'doSomething', argType: 'Input', returnType: 'Nested')
])
], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
Class(
name: 'Nested',
fields: <Field>[Field(name: 'nested', dataType: 'Input')])
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(code, matches('property.*ABCInput'));
expect(code, matches('ABCNested.*doSomething.*ABCInput'));
expect(code, contains('@protocol ABCApi'));
});
test('prefix nested class source', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(name: 'doSomething', argType: 'Input', returnType: 'Nested')
])
], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
Class(
name: 'Nested',
fields: <Field>[Field(name: 'nested', dataType: 'Input')])
]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(code, contains('ABCInput fromMap'));
expect(code, matches('ABCInput.*=.*ABCInput fromMap'));
expect(code, contains('void ABCApiSetup('));
});
test('gen flutter api header', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.flutter, methods: <Method>[
Method(name: 'doSomething', argType: 'Input', returnType: 'Output')
])
], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
Class(
name: 'Output',
fields: <Field>[Field(name: 'output', dataType: 'String')])
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(header: 'foo.h'), root, sink);
final String code = sink.toString();
expect(code, contains('@interface Api : NSObject'));
expect(
code,
contains(
'initWithBinaryMessenger:(id<FlutterBinaryMessenger>)binaryMessenger;'));
expect(code, matches('void.*doSomething.*Input.*Output'));
});
test('gen flutter api source', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.flutter, methods: <Method>[
Method(name: 'doSomething', argType: 'Input', returnType: 'Output')
])
], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
Class(
name: 'Output',
fields: <Field>[Field(name: 'output', dataType: 'String')])
]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(header: 'foo.h'), root, sink);
final String code = sink.toString();
expect(code, contains('@implementation Api'));
expect(code, matches('void.*doSomething.*Input.*Output.*{'));
});
test('gen host void header', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(name: 'doSomething', argType: 'Input', returnType: 'void')
])
], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(code, contains('(void)doSomething:'));
});
test('gen host void source', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(name: 'doSomething', argType: 'Input', returnType: 'void')
])
], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(code, isNot(matches('=.*doSomething')));
expect(code, matches('[.*doSomething:.*]'));
expect(code, contains('callback(wrapResult(nil, error))'));
});
test('gen flutter void return header', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.flutter, methods: <Method>[
Method(name: 'doSomething', argType: 'Input', returnType: 'void')
])
], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(code, contains('completion:(void(^)(NSError* _Nullable))'));
});
test('gen flutter void return source', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.flutter, methods: <Method>[
Method(name: 'doSomething', argType: 'Input', returnType: 'void')
])
], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(code, contains('completion:(void(^)(NSError* _Nullable))'));
expect(code, contains('completion(nil)'));
});
test('gen host void arg header', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(name: 'doSomething', argType: 'void', returnType: 'Output')
])
], classes: <Class>[
Class(
name: 'Output',
fields: <Field>[Field(name: 'output', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(code, matches('ABCOutput.*doSomething:[(]FlutterError'));
});
test('gen host void arg source', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(name: 'doSomething', argType: 'void', returnType: 'Output')
])
], classes: <Class>[
Class(
name: 'Output',
fields: <Field>[Field(name: 'output', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(code, matches('output.*=.*api doSomething:&error'));
});
test('gen flutter void arg header', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.flutter, methods: <Method>[
Method(name: 'doSomething', argType: 'void', returnType: 'Output')
])
], classes: <Class>[
Class(
name: 'Output',
fields: <Field>[Field(name: 'output', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(
code,
contains(
'(void)doSomething:(void(^)(ABCOutput*, NSError* _Nullable))completion'));
});
test('gen flutter void arg header', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.flutter, methods: <Method>[
Method(name: 'doSomething', argType: 'void', returnType: 'Output')
])
], classes: <Class>[
Class(
name: 'Output',
fields: <Field>[Field(name: 'output', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(
code,
contains(
'(void)doSomething:(void(^)(ABCOutput*, NSError* _Nullable))completion'));
expect(code, contains('channel sendMessage:nil'));
});
test('gen list', () {
final Root root = Root(apis: <Api>[], classes: <Class>[
Class(
name: 'Foobar',
fields: <Field>[Field(name: 'field1', dataType: 'List')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(), root, sink);
final String code = sink.toString();
expect(code, contains('@interface Foobar'));
expect(code, matches('@property.*NSArray.*field1'));
});
test('gen map', () {
final Root root = Root(apis: <Api>[], classes: <Class>[
Class(
name: 'Foobar',
fields: <Field>[Field(name: 'field1', dataType: 'Map')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(), root, sink);
final String code = sink.toString();
expect(code, contains('@interface Foobar'));
expect(code, matches('@property.*NSDictionary.*field1'));
});
test('async void(input) HostApi header', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(
name: 'doSomething',
argType: 'Input',
returnType: 'void',
isAsynchronous: true)
])
], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
Class(
name: 'Output',
fields: <Field>[Field(name: 'output', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(
code,
contains(
'(void)doSomething:(nullable ABCInput *)input completion:(void(^)(FlutterError *_Nullable))completion'));
});
test('async output(input) HostApi header', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(
name: 'doSomething',
argType: 'Input',
returnType: 'Output',
isAsynchronous: true)
])
], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
Class(
name: 'Output',
fields: <Field>[Field(name: 'output', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(
code,
contains(
'(void)doSomething:(nullable ABCInput *)input completion:(void(^)(ABCOutput *_Nullable, FlutterError *_Nullable))completion'));
});
test('async output(void) HostApi header', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(
name: 'doSomething',
argType: 'void',
returnType: 'Output',
isAsynchronous: true)
])
], classes: <Class>[
Class(
name: 'Output',
fields: <Field>[Field(name: 'output', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(
code,
contains(
'(void)doSomething:(void(^)(ABCOutput *_Nullable, FlutterError *_Nullable))completion'));
});
test('async void(void) HostApi header', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(
name: 'doSomething',
argType: 'void',
returnType: 'void',
isAsynchronous: true)
])
], classes: <Class>[]);
final StringBuffer sink = StringBuffer();
generateObjcHeader(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(
code,
contains(
'(void)doSomething:(void(^)(FlutterError *_Nullable))completion'));
});
test('async output(input) HostApi source', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(
name: 'doSomething',
argType: 'Input',
returnType: 'Output',
isAsynchronous: true)
])
], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
Class(
name: 'Output',
fields: <Field>[Field(name: 'output', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(
code,
contains(
'[api doSomething:input completion:^(ABCOutput *_Nullable output, FlutterError *_Nullable error) {'));
});
test('async void(input) HostApi source', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(
name: 'doSomething',
argType: 'Input',
returnType: 'void',
isAsynchronous: true)
])
], classes: <Class>[
Class(
name: 'Input',
fields: <Field>[Field(name: 'input', dataType: 'String')]),
Class(
name: 'Output',
fields: <Field>[Field(name: 'output', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(
code,
contains(
'[api doSomething:input completion:^(FlutterError *_Nullable error) {'));
});
test('async void(void) HostApi source', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(
name: 'doSomething',
argType: 'void',
returnType: 'void',
isAsynchronous: true)
])
], classes: <Class>[]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(
code, contains('[api doSomething:^(FlutterError *_Nullable error) {'));
});
test('async output(void) HostApi source', () {
final Root root = Root(apis: <Api>[
Api(name: 'Api', location: ApiLocation.host, methods: <Method>[
Method(
name: 'doSomething',
argType: 'void',
returnType: 'Output',
isAsynchronous: true)
])
], classes: <Class>[
Class(
name: 'Output',
fields: <Field>[Field(name: 'output', dataType: 'String')]),
]);
final StringBuffer sink = StringBuffer();
generateObjcSource(ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink);
final String code = sink.toString();
expect(
code,
contains(
'[api doSomething:^(ABCOutput *_Nullable output, FlutterError *_Nullable error) {'));
});
}