Skip to content

Commit 520fe51

Browse files
authored
[tizen_rpc_port] Add integration tests and fix unsigned byte read (#1054)
1 parent bc51298 commit 520fe51

11 files changed

Lines changed: 397 additions & 43 deletions

File tree

packages/tizen_rpc_port/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 0.1.6
2+
3+
* Read byte values as unsigned (0-255) so `Parcel.readByte` is consistent
4+
across ABIs (C `char` is signed on x86 but unsigned on ARM).
5+
* Add 27 integration test cases to the client example.
6+
* Add server-specific integration test cases to the server example (the shared
7+
Parcel and PortType tests are exercised only in the client example).
8+
19
## 0.1.5
210

311
* Update code format.

packages/tizen_rpc_port/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ The generated source files (`message_client.dart` and `message_server.dart`) dep
2121

2222
```yaml
2323
depenedencies:
24-
tizen_rpc_port: ^0.1.5
24+
tizen_rpc_port: ^0.1.6
2525
```
2626
2727
Assuming that the name of the interface defined in your interface file is `Message`, the client must first call its `connect` method to connect to the server before making any remote invocation.

packages/tizen_rpc_port/example/client/integration_test/tizen_rpc_port_test.dart

Lines changed: 261 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,45 @@
44

55
import 'package:flutter_test/flutter_test.dart';
66
import 'package:integration_test/integration_test.dart';
7-
import 'package:tizen_rpc_port/src/parcel.dart';
7+
import 'package:tizen_bundle/tizen_bundle.dart';
8+
import 'package:tizen_rpc_port/tizen_rpc_port.dart';
9+
10+
// A minimal Parcelable implementation used only in tests.
11+
class _Point implements Parcelable {
12+
_Point({this.x = 0, this.y = 0});
13+
14+
int x;
15+
int y;
16+
17+
@override
18+
void serialize(Parcel parcel) {
19+
parcel.writeInt32(x);
20+
parcel.writeInt32(y);
21+
}
22+
23+
@override
24+
void deserialize(Parcel parcel) {
25+
x = parcel.readInt32();
26+
y = parcel.readInt32();
27+
}
28+
}
29+
30+
// A minimal ProxyBase subclass used only to test single-app observable
31+
// behaviour (isConnected initial state, connection rejection).
32+
class _TestProxy extends ProxyBase {
33+
_TestProxy() : super('org.tizen.nonexistent_app_for_rpc_test', 'TestPort');
34+
35+
@override
36+
Future<void> onReceivedEvent(Parcel parcel) async {}
37+
}
838

939
void main() {
1040
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
1141

42+
// ---------------------------------------------------------------------------
43+
// Existing tests — preserved unchanged
44+
// ---------------------------------------------------------------------------
45+
1246
testWidgets('Parcel test', (WidgetTester tester) async {
1347
final Parcel parcel = Parcel();
1448
parcel.writeBool(false);
@@ -23,4 +57,230 @@ void main() {
2357
expect(parcel.readByte(), 0x3f);
2458
expect(parcel.readDouble(), 123.4);
2559
});
60+
61+
// ---------------------------------------------------------------------------
62+
// Parcel — additional primitive types
63+
// ---------------------------------------------------------------------------
64+
65+
group('Parcel', () {
66+
group('writeInt16 / readInt16', () {
67+
testWidgets('round-trips positive value', (WidgetTester _) async {
68+
final Parcel parcel = Parcel();
69+
parcel.writeInt16(32767);
70+
expect(parcel.readInt16(), 32767);
71+
});
72+
73+
testWidgets('round-trips negative value', (WidgetTester _) async {
74+
final Parcel parcel = Parcel();
75+
parcel.writeInt16(-1);
76+
expect(parcel.readInt16(), -1);
77+
});
78+
79+
testWidgets('round-trips minimum value', (WidgetTester _) async {
80+
final Parcel parcel = Parcel();
81+
parcel.writeInt16(-32768);
82+
expect(parcel.readInt16(), -32768);
83+
});
84+
85+
testWidgets('masks value to 16 bits', (WidgetTester _) async {
86+
final Parcel parcel = Parcel();
87+
// 0x10042 & 0xffff == 0x0042 == 66
88+
parcel.writeInt16(0x10042);
89+
expect(parcel.readInt16(), 66);
90+
});
91+
});
92+
93+
group('writeInt64 / readInt64', () {
94+
testWidgets('round-trips large positive value', (WidgetTester _) async {
95+
final Parcel parcel = Parcel();
96+
const int value = 9007199254740992; // 2^53
97+
parcel.writeInt64(value);
98+
expect(parcel.readInt64(), value);
99+
});
100+
101+
testWidgets('round-trips maximum value', (WidgetTester _) async {
102+
final Parcel parcel = Parcel();
103+
const int value = 9223372036854775807; // int64 max
104+
parcel.writeInt64(value);
105+
expect(parcel.readInt64(), value);
106+
});
107+
108+
testWidgets('round-trips minimum value', (WidgetTester _) async {
109+
final Parcel parcel = Parcel();
110+
const int value = -9223372036854775808; // int64 min
111+
parcel.writeInt64(value);
112+
expect(parcel.readInt64(), value);
113+
});
114+
});
115+
116+
group('writeByte / readByte', () {
117+
testWidgets('round-trips a value', (WidgetTester _) async {
118+
final Parcel parcel = Parcel();
119+
parcel.writeByte(0xab);
120+
expect(parcel.readByte(), 0xab);
121+
});
122+
123+
testWidgets('round-trips maximum unsigned value', (WidgetTester _) async {
124+
final Parcel parcel = Parcel();
125+
parcel.writeByte(255);
126+
expect(parcel.readByte(), 255);
127+
});
128+
129+
testWidgets('reads a negative input back as an unsigned byte', (
130+
WidgetTester _,
131+
) async {
132+
final Parcel parcel = Parcel();
133+
// -1 is written as 0xff and must read back as the unsigned byte 255.
134+
parcel.writeByte(-1);
135+
expect(parcel.readByte(), 255);
136+
});
137+
138+
testWidgets('masks value to 8 bits', (WidgetTester _) async {
139+
final Parcel parcel = Parcel();
140+
// 0x142 & 0xff == 0x42 == 66
141+
parcel.writeByte(0x142);
142+
expect(parcel.readByte(), 66);
143+
});
144+
});
145+
146+
group('writeArrayCount / readArrayCount', () {
147+
testWidgets('round-trips a count', (WidgetTester _) async {
148+
final Parcel parcel = Parcel();
149+
parcel.writeArrayCount(42);
150+
expect(parcel.readArrayCount(), 42);
151+
});
152+
});
153+
154+
group('write / read (burst byte array)', () {
155+
testWidgets('round-trips byte array', (WidgetTester _) async {
156+
final Parcel parcel = Parcel();
157+
final Uint8List bytes = Uint8List.fromList(<int>[
158+
0x00,
159+
0x01,
160+
0x7f,
161+
0x80,
162+
0xff,
163+
]);
164+
parcel.write(bytes);
165+
final Uint8List result = parcel.read(bytes.length);
166+
expect(result, equals(bytes));
167+
});
168+
});
169+
170+
group('Parcel.fromRaw', () {
171+
testWidgets('reconstructed parcel reads back original values', (
172+
WidgetTester _,
173+
) async {
174+
final Parcel original = Parcel();
175+
original.writeInt32(99);
176+
original.writeString('raw');
177+
original.writeBool(true);
178+
179+
final Uint8List raw = original.asRaw();
180+
final Parcel restored = Parcel.fromRaw(raw);
181+
182+
expect(restored.readInt32(), 99);
183+
expect(restored.readString(), 'raw');
184+
expect(restored.readBool(), isTrue);
185+
});
186+
});
187+
188+
group('writeBundle / readBundle', () {
189+
testWidgets('round-trips a Bundle with string entries', (
190+
WidgetTester _,
191+
) async {
192+
final Bundle bundle = Bundle();
193+
bundle['key1'] = 'value1';
194+
bundle['key2'] = 'value2';
195+
196+
final Parcel parcel = Parcel();
197+
parcel.writeBundle(bundle);
198+
199+
final Bundle restored = parcel.readBundle();
200+
expect(restored['key1'], 'value1');
201+
expect(restored['key2'], 'value2');
202+
});
203+
204+
testWidgets('round-trips an empty Bundle', (WidgetTester _) async {
205+
final Parcel parcel = Parcel();
206+
parcel.writeBundle(Bundle());
207+
final Bundle restored = parcel.readBundle();
208+
expect(restored.length, 0);
209+
});
210+
});
211+
212+
group('header', () {
213+
testWidgets('tag can be set and retrieved', (WidgetTester _) async {
214+
final Parcel parcel = Parcel();
215+
final ParcelHeader header = parcel.header;
216+
header.tag = '1.2.3';
217+
expect(parcel.header.tag, '1.2.3');
218+
});
219+
220+
testWidgets('sequenceNumber can be set and retrieved', (
221+
WidgetTester _,
222+
) async {
223+
final Parcel parcel = Parcel();
224+
final ParcelHeader header = parcel.header;
225+
header.sequenceNumber = 7;
226+
expect(parcel.header.sequenceNumber, 7);
227+
});
228+
229+
testWidgets('tag defaults to empty string', (WidgetTester _) async {
230+
final Parcel parcel = Parcel();
231+
expect(parcel.header.tag, isEmpty);
232+
});
233+
});
234+
235+
group('Parcelable', () {
236+
testWidgets('custom Parcelable serializes and deserializes correctly', (
237+
WidgetTester _,
238+
) async {
239+
final Parcel parcel = Parcel();
240+
final _Point original = _Point(x: 10, y: 20);
241+
original.serialize(parcel);
242+
243+
final _Point restored = _Point();
244+
restored.deserialize(parcel);
245+
expect(restored.x, 10);
246+
expect(restored.y, 20);
247+
});
248+
});
249+
});
250+
251+
// ---------------------------------------------------------------------------
252+
// PortType enum
253+
// ---------------------------------------------------------------------------
254+
255+
group('PortType', () {
256+
testWidgets('has exactly the main and callback values', (
257+
WidgetTester _,
258+
) async {
259+
expect(
260+
PortType.values,
261+
unorderedEquals(<PortType>[PortType.main, PortType.callback]),
262+
);
263+
});
264+
});
265+
266+
// ---------------------------------------------------------------------------
267+
// ProxyBase — single-app observable behaviour
268+
// ---------------------------------------------------------------------------
269+
270+
group('ProxyBase', () {
271+
testWidgets('isConnected is false before connecting', (
272+
WidgetTester _,
273+
) async {
274+
final _TestProxy proxy = _TestProxy();
275+
expect(proxy.isConnected, isFalse);
276+
});
277+
278+
testWidgets('appid and portName are set from constructor', (
279+
WidgetTester _,
280+
) async {
281+
final _TestProxy proxy = _TestProxy();
282+
expect(proxy.appid, 'org.tizen.nonexistent_app_for_rpc_test');
283+
expect(proxy.portName, 'TestPort');
284+
});
285+
});
26286
}

packages/tizen_rpc_port/example/client/lib/main.dart

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,32 +171,36 @@ class _MyAppState extends State<MyApp> {
171171
children: <Widget>[
172172
TextButton(
173173
style: ButtonStyle(
174-
minimumSize:
175-
MaterialStateProperty.all(const Size.fromHeight(100)),
174+
minimumSize: MaterialStateProperty.all(
175+
const Size.fromHeight(100),
176+
),
176177
),
177178
onPressed: _connect,
178179
child: const Text('Connect'),
179180
),
180181
TextButton(
181182
style: ButtonStyle(
182-
minimumSize:
183-
MaterialStateProperty.all(const Size.fromHeight(100)),
183+
minimumSize: MaterialStateProperty.all(
184+
const Size.fromHeight(100),
185+
),
184186
),
185187
onPressed: _connect2,
186188
child: const Text('Connect2'),
187189
),
188190
TextButton(
189191
style: ButtonStyle(
190-
minimumSize:
191-
MaterialStateProperty.all(const Size.fromHeight(100)),
192+
minimumSize: MaterialStateProperty.all(
193+
const Size.fromHeight(100),
194+
),
192195
),
193196
onPressed: _isConnected ? _send : null,
194197
child: const Text('Send'),
195198
),
196199
TextButton(
197200
style: ButtonStyle(
198-
minimumSize:
199-
MaterialStateProperty.all(const Size.fromHeight(100)),
201+
minimumSize: MaterialStateProperty.all(
202+
const Size.fromHeight(100),
203+
),
200204
),
201205
onPressed: _isConnected2 ? _send2 : null,
202206
child: const Text('Send2'),

packages/tizen_rpc_port/example/client/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ environment:
99
dependencies:
1010
flutter:
1111
sdk: flutter
12+
tizen_bundle: ^0.1.2
1213
tizen_rpc_port:
1314
path: ../../
1415

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import 'package:integration_test/integration_test_driver.dart';
2+
3+
Future<void> main() => integrationDriver();

0 commit comments

Comments
 (0)