Skip to content

Commit 196beb4

Browse files
authored
Merge pull request #649 from calabash/feature/Device-simulator-paths-may-need-to-be-created
Device: ensure simulator plist paths exist
2 parents b3b5b5c + 896b87f commit 196beb4

File tree

6 files changed

+155
-139
lines changed

6 files changed

+155
-139
lines changed

lib/run_loop/device.rb

+15-50
Original file line numberDiff line numberDiff line change
@@ -275,79 +275,44 @@ def update_simulator_state
275275

276276
# @!visibility private
277277
def simulator_root_dir
278-
@simulator_root_dir ||= lambda {
279-
return nil if physical_device?
280-
File.join(CORE_SIMULATOR_DEVICE_DIR, udid)
281-
}.call
278+
return nil if physical_device?
279+
@simulator_root_dir ||= File.join(CORE_SIMULATOR_DEVICE_DIR, udid)
282280
end
283281

284282
# @!visibility private
285283
def simulator_accessibility_plist_path
286-
@simulator_accessibility_plist_path ||= lambda {
287-
return nil if physical_device?
288-
File.join(simulator_root_dir, 'data/Library/Preferences/com.apple.Accessibility.plist')
289-
}.call
284+
return nil if physical_device?
285+
286+
directory = File.join(simulator_root_dir, "data", "Library", "Preferences")
287+
pbuddy.ensure_plist(directory, "com.apple.Accessibility.plist")
290288
end
291289

292290
# @!visibility private
293291
def simulator_preferences_plist_path
294292
return nil if physical_device?
295293

296-
297294
directory = File.join(simulator_root_dir, "data", "Library", "Preferences")
298-
299-
if !File.exist?(directory)
300-
FileUtils.mkdir_p(directory)
301-
end
302-
303-
plist = File.join(directory, "com.apple.Preferences.plist")
304-
305-
if !File.exist?(plist)
306-
pbuddy.create_plist(plist)
307-
end
308-
plist
295+
pbuddy.ensure_plist(directory, "com.apple.Preferences.plist")
309296
end
310297

311298
# @!visibility private
312299
def simulator_log_file_path
313-
@simulator_log_file_path ||= lambda {
314-
return nil if physical_device?
315-
File.join(CORE_SIMULATOR_LOGS_DIR, udid, 'system.log')
316-
}.call
300+
return nil if physical_device?
301+
@simulator_log_file_path ||= File.join(CORE_SIMULATOR_LOGS_DIR, udid,
302+
'system.log')
317303
end
318304

319305
# @!visibility private
320306
def simulator_device_plist
321-
@simulator_device_plist ||= lambda do
322-
return nil if physical_device?
323-
File.join(simulator_root_dir, 'device.plist')
324-
end.call
307+
return nil if physical_device?
308+
pbuddy.ensure_plist(simulator_root_dir, "device.plist")
325309
end
326310

327311
# @!visibility private
328-
def simulator_global_preferences_path(timeout=10)
312+
def simulator_global_preferences_path
329313
return nil if physical_device?
330-
331-
path = File.join(simulator_root_dir,
332-
"data/Library/Preferences/.GlobalPreferences.plist")
333-
334-
return path if File.exist?(path)
335-
336-
start = Time.now
337-
while !File.exist?(path) && (start + timeout) < Time.now
338-
sleep(1.0)
339-
end
340-
341-
return path if File.exist?(path)
342-
343-
raise(RuntimeError, %Q[
344-
Timed out waiting for .GlobalPreferences.plist after #{Time.now - start} seconds.
345-
346-
File does not exist at path:
347-
348-
#{path}
349-
350-
])
314+
directory = File.join(simulator_root_dir, "data", "Library", "Preferences")
315+
pbuddy.ensure_plist(directory, ".GlobalPreferences.plist")
351316
end
352317

353318
# @!visibility private

lib/run_loop/plist_buddy.rb

+15
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
module RunLoop
23
# A class for reading and writing property list values.
34
#
@@ -6,6 +7,8 @@ module RunLoop
67
# is problematic for our purposes.
78
class PlistBuddy
89

10+
require "fileutils"
11+
912
# Reads key from file and returns the result.
1013
# @param [String] key the key to inspect (may not be nil or empty)
1114
# @param [String] file the plist to read
@@ -85,6 +88,18 @@ def create_plist(path)
8588
path
8689
end
8790

91+
# Ensures a plist exists at path by creating necessary directories and
92+
# creating an empty plist if none exists.
93+
def ensure_plist(directory, name)
94+
FileUtils.mkdir_p(directory) if !File.exist?(directory)
95+
96+
plist = File.join(directory, name)
97+
98+
create_plist(plist) if !File.exists?(plist)
99+
100+
plist
101+
end
102+
88103
private
89104

90105
# returns the path to the PlistBuddy executable

lib/run_loop/simctl.rb

+4-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class Simctl
2424
"Shutdown" => 1,
2525
"Shutting Down" => 2,
2626
"Booted" => 3,
27-
"Plist Missing" => -1
27+
"Plist Missing Key" => -1
2828
}.freeze
2929

3030
# @!visibility private
@@ -125,10 +125,11 @@ def app_container(device, bundle_id)
125125
# @!visibility private
126126
def simulator_state_as_int(device)
127127
plist = device.simulator_device_plist
128-
if File.exist?(plist)
128+
129+
if pbuddy.plist_key_exists?("state", plist)
129130
pbuddy.plist_read("state", plist).to_i
130131
else
131-
SIM_STATES["Plist Missing"]
132+
SIM_STATES["Plist Missing Key"]
132133
end
133134
end
134135

spec/lib/device_spec.rb

+72-79
Original file line numberDiff line numberDiff line change
@@ -231,83 +231,103 @@
231231
end
232232
end
233233

234-
describe 'simulator files' do
235-
let (:physical) { RunLoop::Device.new('name',
236-
'7.1.2',
237-
'30c4b52a41d0f6c64a44bd01ff2966f03105de1e') }
238-
let (:simulator) { RunLoop::Device.new('iPhone 5s',
239-
'7.1.2',
240-
'77DA3AC3-EB3E-4B24-B899-4A20E315C318', 'Shutdown') }
241-
describe '#simulator_root_dir' do
242-
it 'is nil if physical device' do
243-
expect(physical.simulator_root_dir).to be_falsey
234+
context "simulator files" do
235+
let(:physical) do
236+
RunLoop::Device.new("name", "7.1.2",
237+
"30c4b52a41d0f6c64a44bd01ff2966f03105de1e")
238+
end
239+
240+
let (:simulator) do
241+
RunLoop::Device.new("iPhone 5s", "7.1.2",
242+
"77DA3AC3-EB3E-4B24-B899-4A20E315C318", "Shutdown")
243+
end
244+
245+
context "#simulator_root_dir" do
246+
it "returns nil when physical device" do
247+
expect(physical.simulator_root_dir).to be == nil
244248
end
245249

246-
it 'is non nil if a simulator' do
247-
expect(simulator.simulator_root_dir[/#{simulator.udid}/,0]).to be_truthy
250+
it "returns path to Library/Developer/CoreSimulator/<UDID>" do
251+
expect(simulator.simulator_root_dir[/#{simulator.udid}/]).to be_truthy
248252
end
249253
end
250254

251-
describe '#simulator_accessibility_plist_path' do
252-
it 'is nil if physical device' do
253-
expect(physical.simulator_accessibility_plist_path).to be_falsey
255+
context "#simulator_log_file_path" do
256+
it "returns nil when physical device" do
257+
expect(physical.simulator_log_file_path).to be == nil
254258
end
255259

256-
it 'is non nil if a simulator' do
257-
expect(simulator.simulator_accessibility_plist_path[/#{simulator.udid}/,0]).to be_truthy
258-
expect(simulator.simulator_accessibility_plist_path[/com.apple.Accessibility.plist/,0]).to be_truthy
260+
it "returns path to Library/Logs/CoreSimulator/<UDID>/system.log" do
261+
actual = simulator.simulator_log_file_path
262+
expect(actual[/#{simulator.udid}/]).to be_truthy
263+
expect(actual[/system.log/]).to be_truthy
259264
end
260265
end
261266

262-
describe "#simulator_preferences_plist_path" do
263-
it "returns nil if physical device" do
264-
expect(physical.simulator_preferences_plist_path).to be_falsey
267+
context "simulator plists" do
268+
let(:root_dir) do
269+
File.join(Resources.shared.local_tmp_dir, "CoreSimulator", "Devices",
270+
simulator.udid)
265271
end
266272

267-
context "simulator" do
268-
let(:root_dir) { File.join(Resources.shared.local_tmp_dir) }
269-
let(:directory) { File.join(root_dir, "data", "Library", "Preferences") }
270-
let(:plist) { File.join(directory, "com.apple.Preferences.plist") }
271-
let(:template) { Resources.shared.plist_with_software_keyboard(true) }
273+
before do
274+
FileUtils.rm_rf(root_dir)
275+
FileUtils.mkdir_p(root_dir)
276+
end
272277

273-
before do
274-
FileUtils.rm_rf(directory)
275-
FileUtils.mkdir_p(directory)
278+
context "#simulator_accessibility_plist_path" do
279+
it "returns nil when physical device" do
280+
expect(physical.simulator_accessibility_plist_path).to be == nil
281+
end
282+
283+
it "returns path to Accessibility.plist when device is a simulator" do
276284
expect(simulator).to receive(:simulator_root_dir).and_return(root_dir)
285+
286+
actual = simulator.simulator_accessibility_plist_path
287+
288+
expect(actual[/com.apple.Accessibility.plist/]).to be_truthy
277289
end
290+
end
278291

279-
it "returns path to plist" do
280-
FileUtils.cp(template, plist)
281-
expect(simulator.simulator_preferences_plist_path).to be == plist
292+
context "#simulator_preferences_plist_path" do
293+
it "returns nil if physical device" do
294+
expect(physical.simulator_preferences_plist_path).to be == nil
282295
end
283296

284-
it "returns path to plist; creates file if necessary" do
285-
expect(File.exist?(plist)).to be_falsey
286-
expect(simulator.simulator_preferences_plist_path).to be == plist
287-
expect(File.exist?(plist)).to be_truthy
297+
it "returns path to Preference.plist when device is a simulator" do
298+
expect(simulator).to receive(:simulator_root_dir).and_return(root_dir)
299+
300+
actual = simulator.simulator_preferences_plist_path
301+
302+
expect(actual[/com.apple.Preferences.plist/]).to be_truthy
288303
end
289304
end
290-
end
291305

292-
describe '#simulator_log_file_path' do
293-
it 'is nil if physical device' do
294-
expect(physical.simulator_log_file_path).to be_falsey
295-
end
306+
context "#simulator_device_plist" do
307+
it "returns nil physical device" do
308+
expect(physical.simulator_device_plist).to be == nil
309+
end
296310

297-
it 'is non nil if a simulator' do
298-
expect(simulator.simulator_log_file_path[/#{simulator.udid}/,0]).to be_truthy
299-
expect(simulator.simulator_log_file_path[/system.log/,0]).to be_truthy
300-
end
301-
end
311+
it "returns path to device.plist when device is a simulator" do
312+
expect(simulator).to receive(:simulator_root_dir).and_return(root_dir)
302313

303-
describe '#simulator_device_plist' do
304-
it 'is nil if a physical device' do
305-
expect(physical.simulator_device_plist).to be_falsey
314+
actual = simulator.simulator_device_plist
315+
expect(actual[/device.plist/]).to be_truthy
316+
end
306317
end
307318

308-
it 'is non-nil for simulators' do
309-
actual = simulator.simulator_device_plist
310-
expect(actual[/#{simulator.udid}\/device.plist/, 0]).to be_truthy
319+
context "#simulator_global_preferences_path" do
320+
it "returns nil for physical devices" do
321+
expect(physical.simulator_global_preferences_path).to be == nil
322+
end
323+
324+
it "returns path to the .GlobalPreferences.plist when simulator" do
325+
expect(simulator).to receive(:simulator_root_dir).and_return(root_dir)
326+
327+
actual = simulator.simulator_global_preferences_path
328+
329+
expect(actual[/.GlobalPreferences.plist/]).to be_truthy
330+
end
311331
end
312332
end
313333

@@ -340,33 +360,6 @@
340360
expect(actual).to be_truthy
341361
end
342362
end
343-
344-
describe "#simulator_global_preferences_path" do
345-
it "returns nil for physical devices" do
346-
expect(physical.simulator_global_preferences_path).to be_falsey
347-
end
348-
349-
it "raises an error after waiting for the plist to exist" do
350-
path = File.join(simulator.simulator_root_dir,
351-
"data/Library/Preferences/.GlobalPreferences.plist")
352-
expect(File).to receive(:exist?).with(path).at_least(:twice).and_return(false)
353-
354-
expect do
355-
simulator.simulator_global_preferences_path(0.05)
356-
end.to raise_error(RuntimeError,
357-
/Timed out waiting for .GlobalPreferences.plist/)
358-
end
359-
360-
it "returns the path to the global plist" do
361-
simulator = Resources.shared.default_simulator
362-
363-
actual = simulator.simulator_global_preferences_path
364-
365-
expect(actual[/.GlobalPreferences.plist/]).to be_truthy
366-
expect(actual[/#{simulator.udid}/]).to be_truthy
367-
expect(File.exist?(actual)).to be_truthy
368-
end
369-
end
370363
end
371364

372365
describe "#simulator_languages" do

spec/lib/plist_buddy_spec.rb

+36
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,42 @@
1616
expect(File.open(path).read).not_to be == ''
1717
end
1818

19+
context "#ensure_plist" do
20+
let(:base_dir) { File.join(Resources.shared.local_tmp_dir, "PlistBuddy") }
21+
let(:directory) { File.join(base_dir, "A", "B") }
22+
let(:name) { "com.example.MyApp.plist" }
23+
let(:plist) { File.join(directory, name) }
24+
25+
before do
26+
FileUtils.rm_rf(base_dir)
27+
FileUtils.mkdir_p(base_dir)
28+
end
29+
30+
it "returns a path to an existing plist" do
31+
FileUtils.mkdir_p(directory)
32+
FileUtils.touch(plist)
33+
34+
expect(FileUtils).not_to receive(:mkdir_p).with(directory)
35+
expect(pbuddy).not_to receive(:create_plist)
36+
expect(pbuddy.ensure_plist(directory, name)).to be == plist
37+
end
38+
39+
it "returns a path to an empty plist if one does not already exist" do
40+
FileUtils.mkdir_p(directory)
41+
42+
expect(FileUtils).not_to receive(:mkdir_p).with(directory)
43+
expect(pbuddy).to receive(:create_plist).with(plist)
44+
expect(pbuddy.ensure_plist(directory, name)).to be == plist
45+
end
46+
47+
it "returns a path to an empty plist after creating any necessary directories" do
48+
expect(FileUtils).to receive(:mkdir_p).with(directory)
49+
expect(pbuddy).to receive(:create_plist).with(plist)
50+
51+
expect(pbuddy.ensure_plist(directory, name)).to be == plist
52+
end
53+
end
54+
1955
describe '#build_plist_cmd' do
2056
describe 'raises errors' do
2157
it 'if file does not exist' do

0 commit comments

Comments
 (0)