OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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 file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /// Helper program for killing and resetting all Safari settings to a known | 5 /// Helper program for killing and resetting all Safari settings to a known |
6 /// state that works well for testing dart2js output in Safari. | 6 /// state that works well for testing dart2js output in Safari. |
7 /// | 7 /// |
8 /// Warning: this will delete all your Safari settings and bookmarks. | 8 /// Warning: this will delete all your Safari settings and bookmarks. |
9 library testing.reset_safari; | 9 library testing.reset_safari; |
10 | 10 |
11 import 'dart:async' show Future, Timer; | 11 import 'dart:async' show Future, Timer; |
12 | 12 |
13 import 'dart:io' show Directory, File, Platform, Process, ProcessResult; | 13 import 'dart:io' show Directory, File, Platform, Process; |
14 | 14 |
15 const String defaultSafariBundleLocation = "/Applications/Safari.app/"; | 15 const String defaultSafariBundleLocation = "/Applications/Safari.app/"; |
16 | 16 |
17 const String relativeSafariLocation = "Contents/MacOS/Safari"; | 17 const String relativeSafariLocation = "Contents/MacOS/Safari"; |
18 | 18 |
19 const String lsofLocation = "/usr/sbin/lsof"; | 19 const String lsofLocation = "/usr/sbin/lsof"; |
20 | 20 |
21 const String killLocation = "/bin/kill"; | 21 const String killLocation = "/bin/kill"; |
22 | 22 |
23 const String pkillLocation = "/usr/bin/pkill"; | 23 const String pkillLocation = "/usr/bin/pkill"; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 if (force && testOnly) { | 104 if (force && testOnly) { |
105 throw new ArgumentError("[force] and [testOnly] can't both be true."); | 105 throw new ArgumentError("[force] and [testOnly] can't both be true."); |
106 } | 106 } |
107 if (force) return "-KILL"; | 107 if (force) return "-KILL"; |
108 if (testOnly) return "-0"; | 108 if (testOnly) return "-0"; |
109 return defaultSignal; | 109 return defaultSignal; |
110 } | 110 } |
111 | 111 |
112 Future<int> kill(List<String> pids, | 112 Future<int> kill(List<String> pids, |
113 {bool force: false, bool testOnly: false}) async { | 113 {bool force: false, bool testOnly: false}) async { |
114 List<String> arguments = <String>[ | 114 var arguments = [signalArgument("-TERM", force: force, testOnly: testOnly)] |
115 signalArgument("-TERM", force: force, testOnly: testOnly) | 115 ..addAll(pids); |
116 ]..addAll(pids); | 116 var result = await Process.run(killLocation, arguments); |
117 ProcessResult result = await Process.run(killLocation, arguments); | |
118 return result.exitCode; | 117 return result.exitCode; |
119 } | 118 } |
120 | 119 |
121 Future<int> pkill(String pattern, | 120 Future<int> pkill(String pattern, |
122 {bool force: false, bool testOnly: false}) async { | 121 {bool force: false, bool testOnly: false}) async { |
123 List<String> arguments = <String>[ | 122 var arguments = [ |
124 signalArgument("-HUP", force: force, testOnly: testOnly), | 123 signalArgument("-HUP", force: force, testOnly: testOnly), |
125 pattern | 124 pattern |
126 ]; | 125 ]; |
127 ProcessResult result = await Process.run(pkillLocation, arguments); | 126 var result = await Process.run(pkillLocation, arguments); |
128 return result.exitCode; | 127 return result.exitCode; |
129 } | 128 } |
130 | 129 |
131 Uri validatedBundleName(Uri bundle) { | 130 Uri validatedBundleName(Uri bundle) { |
132 if (bundle == null) return Uri.base.resolve(defaultSafariBundleLocation); | 131 if (bundle == null) return Uri.base.resolve(defaultSafariBundleLocation); |
133 if (!bundle.path.endsWith("/")) { | 132 if (!bundle.path.endsWith("/")) { |
134 throw new ArgumentError("Bundle ('$bundle') must end with a slash ('/')."); | 133 throw new ArgumentError("Bundle ('$bundle') must end with a slash ('/')."); |
135 } | 134 } |
136 return bundle; | 135 return bundle; |
137 } | 136 } |
138 | 137 |
139 Future<Null> killSafari({Uri bundle}) async { | 138 Future<Null> killSafari({Uri bundle}) async { |
140 bundle = validatedBundleName(bundle); | 139 bundle = validatedBundleName(bundle); |
141 Uri safariBinary = bundle.resolve(relativeSafariLocation); | 140 var safariBinary = bundle.resolve(relativeSafariLocation); |
142 ProcessResult result = | 141 var result = |
143 await Process.run(lsofLocation, ["-t", safariBinary.toFilePath()]); | 142 await Process.run(lsofLocation, ["-t", safariBinary.toFilePath()]); |
144 if (result.exitCode == 0) { | 143 if (result.exitCode == 0) { |
145 String stdout = result.stdout; | 144 var stdout = result.stdout as String; |
146 List<String> pids = new List<String>.from( | 145 var pids = |
147 stdout.split("\n").where((String line) => !line.isEmpty)); | 146 stdout.split("\n").where((String line) => !line.isEmpty).toList(); |
148 Timer timer = new Timer(const Duration(seconds: 10), () { | 147 var timer = new Timer(const Duration(seconds: 10), () { |
149 print("Kill -9 Safari $pids"); | 148 print("Kill -9 Safari $pids"); |
150 kill(pids, force: true); | 149 kill(pids, force: true); |
151 }); | 150 }); |
152 int exitCode = await kill(pids); | 151 var exitCode = await kill(pids); |
153 while (exitCode == 0) { | 152 while (exitCode == 0) { |
154 await pollDelay; | 153 await pollDelay; |
155 print("Polling Safari $pids"); | 154 print("Polling Safari $pids"); |
156 exitCode = await kill(pids, testOnly: true); | 155 exitCode = await kill(pids, testOnly: true); |
157 } | 156 } |
158 timer.cancel(); | 157 timer.cancel(); |
159 } | 158 } |
160 Timer timer = new Timer(const Duration(seconds: 10), () { | 159 var timer = new Timer(const Duration(seconds: 10), () { |
161 print("Kill -9 $safari"); | 160 print("Kill -9 $safari"); |
162 pkill(safari, force: true); | 161 pkill(safari, force: true); |
163 }); | 162 }); |
164 int exitCode = await pkill(safari); | 163 var exitCode = await pkill(safari); |
165 while (exitCode == 0) { | 164 while (exitCode == 0) { |
166 await pollDelay; | 165 await pollDelay; |
167 print("Polling $safari"); | 166 print("Polling $safari"); |
168 exitCode = await pkill(safari, testOnly: true); | 167 exitCode = await pkill(safari, testOnly: true); |
169 } | 168 } |
170 timer.cancel(); | 169 timer.cancel(); |
171 } | 170 } |
172 | 171 |
173 Future<Null> deleteIfExists(Uri uri) async { | 172 Future<Null> deleteIfExists(Uri uri) async { |
174 Directory directory = new Directory.fromUri(uri); | 173 var directory = new Directory.fromUri(uri); |
175 if (await directory.exists()) { | 174 if (await directory.exists()) { |
176 print("Deleting directory '$uri'."); | 175 print("Deleting directory '$uri'."); |
177 await directory.delete(recursive: true); | 176 await directory.delete(recursive: true); |
178 } else { | 177 } else { |
179 File file = new File.fromUri(uri); | 178 var file = new File.fromUri(uri); |
180 if (await file.exists()) { | 179 if (await file.exists()) { |
181 print("Deleting file '$uri'."); | 180 print("Deleting file '$uri'."); |
182 await file.delete(); | 181 await file.delete(); |
183 } else { | 182 } else { |
184 print("File '$uri' not found."); | 183 print("File '$uri' not found."); |
185 } | 184 } |
186 } | 185 } |
187 } | 186 } |
188 | 187 |
189 Future<Null> resetSafariSettings() async { | 188 Future<Null> resetSafariSettings() async { |
190 String home = Platform.environment["HOME"]; | 189 var home = Platform.environment["HOME"]; |
191 if (!home.endsWith("/")) { | 190 if (!home.endsWith("/")) { |
192 home = "$home/"; | 191 home = "$home/"; |
193 } | 192 } |
194 Uri homeDirectory = Uri.base.resolve(home); | 193 var homeDirectory = Uri.base.resolve(home); |
195 for (String setting in safariSettings) { | 194 for (String setting in safariSettings) { |
196 await deleteIfExists(homeDirectory.resolve(setting)); | 195 await deleteIfExists(homeDirectory.resolve(setting)); |
197 } | 196 } |
198 ProcessResult result = await Process | 197 var result = await Process |
199 .run(defaultsLocation, <String>["write", safari, knownSafariPreference]); | 198 .run(defaultsLocation, <String>["write", safari, knownSafariPreference]); |
200 if (result.exitCode != 0) { | 199 if (result.exitCode != 0) { |
201 throw "Unable to reset Safari settings: ${result.stdout}${result.stderr}"; | 200 throw "Unable to reset Safari settings: ${result.stdout}${result.stderr}"; |
202 } | 201 } |
203 } | 202 } |
204 | 203 |
205 Future<Null> killAndResetSafari({Uri bundle}) async { | 204 Future<Null> killAndResetSafari({Uri bundle}) async { |
206 bundle = validatedBundleName(bundle); | 205 bundle = validatedBundleName(bundle); |
207 await killSafari(bundle: bundle); | 206 await killSafari(bundle: bundle); |
208 await resetSafariSettings(); | 207 await resetSafariSettings(); |
209 } | 208 } |
210 | 209 |
211 Future<Null> main() async { | 210 Future<Null> main() async { |
212 await killAndResetSafari(); | 211 await killAndResetSafari(); |
213 } | 212 } |
OLD | NEW |