Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: tests/fletchc/driver/mock_vm.dart

Issue 1659163007: Rename fletch -> dartino (Closed) Base URL: https://github.com/dartino/sdk.git@master
Patch Set: address comments Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE.md file.
4
5 /// Mock VM implementation used for testing VM connections.
6 library fletchc.test.client.mock_vm;
7
8 import 'dart:async' show
9 Future,
10 StreamIterator;
11
12 import 'dart:io' show
13 InternetAddress,
14 ServerSocket,
15 Socket;
16
17 import 'dart:isolate' show
18 ReceivePort,
19 SendPort;
20
21 import 'dart:typed_data' show
22 ByteData;
23
24 import 'package:fletchc/src/shared_command_infrastructure.dart' show
25 CommandTransformerBuilder,
26 toUint8ListView;
27
28 import 'package:fletchc/vm_commands.dart' show
29 VmCommand,
30 VmCommandCode,
31 CommitChangesResult,
32 HandShakeResult,
33 ProcessTerminated;
34
35 import 'package:dart_isolate/ports.dart' show
36 singleResponseFuture;
37
38 import 'package:dart_isolate/isolate_runner.dart' show
39 IsolateRunner;
40
41 import 'package:fletchc/src/zone_helper.dart' show
42 runGuarded;
43
44 /// Represents state associated with a mocked VM.
45 class MockVm {
46 /// Port number the mock VM is listening on. Host is always 127.0.0.1.
47 final int port;
48
49 /// Future completes with VM's exit code.
50 final Future<int> exitCode;
51
52 // Internal.
53 final IsolateRunner isolate;
54
55 MockVm(this.port, this.isolate, this.exitCode);
56
57 /// Create a new MockVm.
58 /// If [closeImmediately] is true, the mock VM will close its socket
59 /// immediately after accepting an incoming connection.
60 /// If [closeAfterFirst] is non-null, the mock VM will close its socket
61 /// immediately after receiving a command with that code.
62 /// [closeImmediately] and [closeAfterFirst] can't be used together.
63 static Future<MockVm> spawn(
64 {bool closeImmediately: false,
65 VmCommandCode closeAfterFirst}) async {
66 if (closeImmediately && closeAfterFirst != null) {
67 throw new ArgumentError(
68 "[closeImmediately] and [closeAfterFirst] can't be used together");
69 }
70 IsolateRunner isolate = await IsolateRunner.spawn();
71 Future exitCode;
72 ReceivePort stdout = new ReceivePort();
73 stdout.listen(print);
74 int port = await singleResponseFuture((SendPort port) {
75 int index = closeAfterFirst == null ? -1 : closeAfterFirst.index;
76 var arguments = new MockVmArguments(
77 port, closeImmediately, index, stdout.sendPort);
78 exitCode = isolate.run(mockVm, arguments)
79 .whenComplete(stdout.close)
80 .whenComplete(isolate.close);
81 });
82 return new MockVm(port, isolate, exitCode);
83 }
84 }
85
86 /// Encodes arguments to [mockVm].
87 class MockVmArguments {
88 // Keep this class simple. See notice in `SharedTask` in
89 // `package:fletchc/src/verbs/infrastructure.dart`.
90
91 final SendPort port;
92 final bool closeImmediately;
93 final int closeAfterFirstIndex;
94 final SendPort stdout;
95
96 const MockVmArguments(
97 this.port,
98 this.closeImmediately,
99 this.closeAfterFirstIndex,
100 this.stdout);
101
102 VmCommandCode get closeAfterFirst {
103 return closeAfterFirstIndex == -1
104 ? null : VmCommandCode.values[closeAfterFirstIndex];
105 }
106 }
107
108 /// See [MockVm.spawn].
109 Future<int> mockVm(MockVmArguments arguments) async {
110 int exitCode = 0;
111 await runGuarded(() async {
112 Socket socket = await compilerConnection(arguments.port);
113 if (arguments.closeImmediately) {
114 socket.listen(null).cancel();
115 await socket.close();
116 return;
117 }
118 var transformer = new MockCommandTransformerBuilder().build();
119 await for (var command in socket.transform(transformer)) {
120 VmCommandCode code = command[0];
121 if (arguments.closeAfterFirst == code) break;
122 VmCommand reply = mockReply(code);
123 if (reply == null) {
124 print(command);
125 } else {
126 reply.addTo(socket);
127 await socket.flush();
128 }
129 }
130 await socket.close();
131 }, printLineOnStdout: arguments.stdout.send);
132 return exitCode;
133 }
134
135 /// Transform List<int> (socket datagrams) to a two-element list of
136 /// `[VmCommandCode, payload]`.
137 class MockCommandTransformerBuilder extends CommandTransformerBuilder<List> {
138 List makeCommand(int code, ByteData payload) {
139 return [VmCommandCode.values[code], toUint8ListView(payload)];
140 }
141 }
142
143 /// Listens for a single connection from a compiler/debugger/etc. When the
144 /// server is started, its port number is returned on [port] letting a listener
145 /// know that the server is ready and listening for a connection.
146 Future<Socket> compilerConnection(SendPort port) async {
147 ServerSocket server =
148 await ServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0);
149 port.send(server.port);
150 var connectionIterator = new StreamIterator(server);
151 if (!await connectionIterator.moveNext()) {
152 throw "ServerSocket didn't get a connection";
153 }
154 Socket socket = connectionIterator.current;
155 await server.close();
156 while (await connectionIterator.moveNext()) {
157 throw "unexpected connection: ${connectionIterator.current}";
158 }
159 return socket;
160 }
161
162 /// Mock a reply if [code] requires a response for the compiler/debugger to
163 /// make progress.
164 VmCommand mockReply(VmCommandCode code) {
165 // Please add more cases as needed.
166 switch (code) {
167 case VmCommandCode.HandShake:
168 return new HandShakeResult(true, "");
169
170 case VmCommandCode.CommitChanges:
171 return new CommitChangesResult(
172 true, "Successfully applied program update.");
173
174 case VmCommandCode.ProcessRun:
175 return const ProcessTerminated();
176
177 default:
178 return null;
179 }
180 }
OLDNEW
« no previous file with comments | « tests/fletch_tests/zone_helper_tests.dart ('k') | tests/fletchc/driver/test_control_stream.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698