zerg_xcode 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/CHANGELOG +1 -0
  2. data/LICENSE +21 -0
  3. data/Manifest +44 -0
  4. data/README.textile +124 -0
  5. data/RUBYFORGE +40 -0
  6. data/Rakefile +27 -0
  7. data/bin/zerg-xcode +7 -0
  8. data/lib/zerg_xcode/file_format/archiver.rb +87 -0
  9. data/lib/zerg_xcode/file_format/encoder.rb +40 -0
  10. data/lib/zerg_xcode/file_format/lexer.rb +60 -0
  11. data/lib/zerg_xcode/file_format/parser.rb +46 -0
  12. data/lib/zerg_xcode/file_format/paths.rb +44 -0
  13. data/lib/zerg_xcode/objects/pbx_build_file.rb +27 -0
  14. data/lib/zerg_xcode/objects/pbx_native_target.rb +19 -0
  15. data/lib/zerg_xcode/objects/pbx_project.rb +60 -0
  16. data/lib/zerg_xcode/objects/xcode_object.rb +144 -0
  17. data/lib/zerg_xcode/plugins/core/core.rb +36 -0
  18. data/lib/zerg_xcode/plugins/help.rb +30 -0
  19. data/lib/zerg_xcode/plugins/import.rb +19 -0
  20. data/lib/zerg_xcode/plugins/irb.rb +22 -0
  21. data/lib/zerg_xcode/plugins/ls.rb +27 -0
  22. data/lib/zerg_xcode/plugins/retarget.rb +90 -0
  23. data/lib/zerg_xcode/shortcuts.rb +22 -0
  24. data/lib/zerg_xcode.rb +17 -0
  25. data/test/file_format/archiver_test.rb +70 -0
  26. data/test/file_format/encoder_test.rb +10 -0
  27. data/test/file_format/lexer_test.rb +56 -0
  28. data/test/file_format/parser_test.rb +44 -0
  29. data/test/file_format/path_test.rb +40 -0
  30. data/test/objects/pbx_build_file_test.rb +38 -0
  31. data/test/objects/pbx_native_target_test.rb +31 -0
  32. data/test/objects/pbx_project_test.rb +62 -0
  33. data/test/objects/xcode_object_test.rb +117 -0
  34. data/test/plugins/core/core_test.rb +32 -0
  35. data/test/plugins/import_test.rb +22 -0
  36. data/test/plugins/irb_test.rb +30 -0
  37. data/test/plugins/ls_test.rb +43 -0
  38. data/test/plugins/retarget_test.rb +65 -0
  39. data/test/plugins/test_helper.rb +21 -0
  40. data/test/shortcuts_test.rb +18 -0
  41. data/testdata/TestApp/TestApp.xcodeproj/project.pbxproj +328 -0
  42. data/testdata/ZergSupport.xcodeproj/project.pbxproj +930 -0
  43. data/testdata/project.pbxproj +250 -0
  44. data/testdata/project.pbxproj.compat +320 -0
  45. data/zerg_xcode.gemspec +34 -0
  46. metadata +137 -0
@@ -0,0 +1,31 @@
1
+ require 'test/unit'
2
+
3
+ require 'zerg_xcode'
4
+
5
+ class PBXNativeTargetTest < Test::Unit::TestCase
6
+ PBXNativeTarget = ZergXcode::Objects::PBXNativeTarget
7
+
8
+ def test_all_files
9
+ golden_list = [
10
+ ["PBXResourcesBuildPhase", "MainWindow.xib"],
11
+ ["PBXResourcesBuildPhase", "TestAppViewController.xib"],
12
+ ["PBXSourcesBuildPhase", "main.m"],
13
+ ["PBXSourcesBuildPhase", "TestAppAppDelegate.m"],
14
+ ["PBXSourcesBuildPhase", "TestAppViewController.m"],
15
+ ["PBXFrameworksBuildPhase",
16
+ "System/Library/Frameworks/Foundation.framework"],
17
+ ["PBXFrameworksBuildPhase",
18
+ "System/Library/Frameworks/UIKit.framework"],
19
+ ["PBXFrameworksBuildPhase",
20
+ "System/Library/Frameworks/CoreGraphics.framework"],
21
+ ]
22
+
23
+ project = ZergXcode.load('testdata/project.pbxproj')
24
+ assert_equal PBXNativeTarget, project['targets'].first.class
25
+ files = project['targets'].first.all_files
26
+ file_list = files.map do |file|
27
+ [file[:phase]['isa'], file[:object]['path']]
28
+ end
29
+ assert_equal golden_list.sort, file_list.sort
30
+ end
31
+ end
@@ -0,0 +1,62 @@
1
+ require 'test/unit'
2
+
3
+ require 'zerg_xcode'
4
+
5
+ require 'rubygems'
6
+ require 'flexmock'
7
+
8
+
9
+ class PBXProjectTest < Test::Unit::TestCase
10
+ PBXProject = ZergXcode::Objects::PBXProject
11
+ def test_all_files_small
12
+ golden_list = [
13
+ ["./Classes/TestAppAppDelegate.h", "sourcecode.c.h"],
14
+ ["./Classes/TestAppAppDelegate.m", "sourcecode.c.objc"],
15
+ ["./Classes/TestAppViewController.h", "sourcecode.c.h"],
16
+ ["./Classes/TestAppViewController.m", "sourcecode.c.objc"],
17
+ ["./TestApp_Prefix.pch", "sourcecode.c.h"],
18
+ ["./main.m", "sourcecode.c.objc"],
19
+ ["./TestAppViewController.xib", "file.xib"],
20
+ ["./MainWindow.xib", "file.xib"],
21
+ ["./Info.plist", "text.plist.xml"],
22
+ ["SDKROOT/System/Library/Frameworks/UIKit.framework",
23
+ "wrapper.framework"],
24
+ ["SDKROOT/System/Library/Frameworks/Foundation.framework",
25
+ "wrapper.framework"],
26
+ ["SDKROOT/System/Library/Frameworks/CoreGraphics.framework",
27
+ "wrapper.framework"],
28
+ ["BUILT_PRODUCTS_DIR/TestApp.app", nil],
29
+ ]
30
+
31
+ project = ZergXcode.load('testdata/project.pbxproj')
32
+ assert_equal PBXProject, project.class
33
+ files = project.all_files
34
+ file_list = files.map { |f| [f[:path], f[:object]['lastKnownFileType']] }
35
+ assert_equal golden_list.sort, file_list.sort
36
+ end
37
+
38
+ def test_all_files_large
39
+ golden_entries = [
40
+ ["./ZergSupport/FormatSupport/ZNFormFieldFormatter+Snake2LCamel.m",
41
+ "sourcecode.c.objc"],
42
+ ["./ZergSupport/ModelSupport/ZNModelDefinitionAttributeTest.m",
43
+ "sourcecode.c.objc"],
44
+ ["./ZergSupport/TestSupport/TestSupport.h", "sourcecode.c.h"],
45
+ ["./ZergSupport/TestSupport/GTM/GTMDefines.h", "sourcecode.c.h"],
46
+ ["./ZergSupport/WebSupport/ZNHttpRequest.m", "sourcecode.c.objc"],
47
+ ]
48
+ files = ZergXcode.load('testdata/ZergSupport').all_files
49
+ file_list = files.map { |f| [f[:path], f[:object]['lastKnownFileType']] }
50
+ golden_entries.each do |entry|
51
+ assert file_list.include?(entry), "Missing #{entry.inspect}"
52
+ end
53
+ end
54
+
55
+ def test_save
56
+ project = ZergXcode.load('testdata')
57
+ flexmock(ZergXcode).should_receive(:dump).
58
+ with(project, 'testdata/project.pbxproj').
59
+ and_return(nil)
60
+ project.save!
61
+ end
62
+ end
@@ -0,0 +1,117 @@
1
+ require 'set'
2
+ require 'test/unit'
3
+
4
+ require 'zerg_xcode'
5
+
6
+ class ObjectTest < Test::Unit::TestCase
7
+ XcodeObject = ZergXcode::XcodeObject
8
+ PBXProject = ZergXcode::Objects::PBXProject
9
+
10
+ def setup
11
+ @sub1 = XcodeObject.new :array => ['a', 'b', 'c'], :string => 's'
12
+ @sub1.archive_id = 39
13
+ @sub2 = XcodeObject.new :hash => { :k => 'v', :k2 => 'v2' }, :sub1 => @sub1
14
+ @sub2.archive_id = 42
15
+ @root = XcodeObject.new :sub1 => @sub1, :sub2 => @sub2
16
+ @root.archive_id = 49
17
+ @root.version = 45
18
+ end
19
+
20
+ def test_readonly_visit
21
+ golden_visited = [
22
+ [49, 'sub1', @sub1],
23
+ [39, 'array', @sub1[:array]],
24
+ [39, '0', 'a'],
25
+ [39, '1', 'b'],
26
+ [39, '2', 'c'],
27
+ [39, 'string', 's'],
28
+ [49, 'sub2', @sub2],
29
+ [42, 'hash', @sub2[:hash]],
30
+ [42, 'k', 'v'],
31
+ [42, 'k2', 'v2'],
32
+ [42, 'sub1', @sub1],
33
+ ]
34
+
35
+ visited = []
36
+ visited_objects = Set.new
37
+ @root.visit do |object, parent, key, value|
38
+ assert_equal value, parent[key], 'Parent/Key/Value check'
39
+
40
+ visited << [object.archive_id, key.to_s, value]
41
+ next true unless value.kind_of? XcodeObject
42
+ next false if visited_objects.include? value
43
+ visited_objects << value
44
+ next true
45
+ end
46
+ assert_equal golden_visited.sort, visited.sort
47
+ end
48
+
49
+ def test_mutating_visit
50
+ golden_visited = [
51
+ [49, 'sub1', @sub1],
52
+ [39, 'array', @sub1[:array]],
53
+ [39, '0', 'a'],
54
+ [39, '1', 'b'],
55
+ [39, '2', 'c'],
56
+ [39, '3', 'a'],
57
+ [39, '4', 'b'],
58
+ [39, '5', 'c'],
59
+ [39, 'string', 's'],
60
+ [49, 'sub2', @sub2],
61
+ [42, 'hash', @sub2[:hash]],
62
+ [42, 'k', 'v'],
63
+ [42, 'k2', 'v2'],
64
+ [42, 'sub1', @sub1],
65
+ ]
66
+
67
+ visited = []
68
+ visited_objects = Set.new
69
+ @root.visit do |object, parent, key, value|
70
+ assert_equal value, parent[key], 'Parent/Key/Value check'
71
+
72
+ visited << [object.archive_id, key.to_s, value]
73
+ case value
74
+ when XcodeObject
75
+ next false if visited_objects.include? value
76
+ visited_objects << value
77
+ next true
78
+ when Array, String
79
+ next value * 2
80
+ when Hash
81
+ next true
82
+ end
83
+ end
84
+
85
+ assert_equal golden_visited.sort, visited.sort
86
+ assert_equal @sub1[:array], ['aa', 'bb', 'cc', 'aa', 'bb', 'cc']
87
+ assert_equal @sub1[:string], 'ss'
88
+ end
89
+
90
+ def test_deep_copy
91
+ root = XcodeObject.from @root
92
+ assert_equal root[:sub2][:sub1], root[:sub1], 'Deep copy tracks objects'
93
+
94
+ root[:sub1] = 'break'
95
+ assert @root[:sub1] != 'break', 'Deep copy duplicates object attributes'
96
+ root[:sub2][:hash][:k] = 'break'
97
+ assert @root[:sub2][:hash] != 'break', 'Deep copy duplicates hashes'
98
+ root[:sub2][:sub1][:array][0] = 'break'
99
+ assert @root[:sub2][:sub1][:array][0] != 'break',
100
+ 'Deep copy duplicates hashes'
101
+ end
102
+
103
+ def test_messed_up_inheritance
104
+ assert_equal XcodeObject, @root.class
105
+
106
+ p = XcodeObject.new 'isa' => 'PBXProject', 'name' => 'awesome'
107
+ assert_equal PBXProject, p.class
108
+
109
+ root = XcodeObject.from @root
110
+ assert_equal XcodeObject, root.class, 'After deep copy'
111
+ assert_equal PBXProject, XcodeObject.from(p).class, 'After deep copy'
112
+
113
+ p = PBXProject.new 'name' => 'boo'
114
+ assert_equal 'PBXProject', p['isa'], 'Subclass creation does not set isa.'
115
+ assert_equal 'boo', p['name'], 'Subclass creation corrupts attributes'
116
+ end
117
+ end
@@ -0,0 +1,32 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require 'test/plugins/test_helper.rb'
4
+
5
+ require 'zerg_xcode'
6
+
7
+ class Plugins::CoreTest < Test::Unit::TestCase
8
+ include Plugins::TestHelper
9
+
10
+ def test_all
11
+ assert ZergXcode::Plugins.all.include?('ls'), 'Incomplete list'
12
+ end
13
+
14
+ def test_get
15
+ ls_instance = ZergXcode::Plugins.get 'ls'
16
+ ls_class = ZergXcode::Plugins::Ls
17
+ assert ls_instance.kind_of?(ls_class), 'Get retrieves wrong object'
18
+ end
19
+
20
+ def test_help
21
+ help = ZergXcode::Plugins.help 'ls'
22
+ assert help[:short], 'Help object does not contain short description'
23
+ assert help[:long], 'Help object does not contain long description'
24
+ end
25
+
26
+ def test_run
27
+ help_output = capture_output { ZergXcode::Plugins.run('help', []) }
28
+
29
+ assert help_output.index('Xcode Project Modifier brought to you by '),
30
+ 'The result of running help does not match the expected result'
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ require 'test/unit'
2
+ require 'test/plugins/test_helper.rb'
3
+
4
+ require 'zerg_xcode'
5
+
6
+ require 'rubygems'
7
+ require 'flexmock/test_unit'
8
+
9
+ module Plugins; end
10
+
11
+ class Plugins::ImportTest < Test::Unit::TestCase
12
+ include Plugins::TestHelper
13
+
14
+ def setup
15
+ super
16
+ @plugin = ZergXcode.plugin 'import'
17
+ end
18
+
19
+ def test_plugin
20
+ flunk
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ require 'test/unit'
2
+ require 'test/plugins/test_helper.rb'
3
+
4
+ require 'zerg_xcode'
5
+
6
+ require 'rubygems'
7
+ require 'flexmock/test_unit'
8
+ require 'irb'
9
+
10
+ module Plugins; end
11
+
12
+ class Plugins::IrbTest < Test::Unit::TestCase
13
+ include Plugins::TestHelper
14
+
15
+ def setup
16
+ super
17
+ @plugin = ZergXcode.plugin 'irb'
18
+ end
19
+
20
+ def test_irb_call
21
+ test_project = ZergXcode.load '.'
22
+
23
+ flexmock(IRB).should_receive(:start).and_return(nil)
24
+ output = capture_output { @plugin.run([]) }
25
+ assert_equal test_project.attrs, $p.attrs, 'Loaded incorrect project'
26
+ assert output.index("'quit'"), 'Missing instructions on how to leave IRB'
27
+ assert_equal "\n", output[-1, 1], 'Instructions missing trailing newline'
28
+ $p = nil
29
+ end
30
+ end
@@ -0,0 +1,43 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require 'test/plugins/test_helper.rb'
4
+
5
+ require 'zerg_xcode'
6
+
7
+ module Plugins; end
8
+
9
+ class Plugins::LsTest < Test::Unit::TestCase
10
+ include Plugins::TestHelper
11
+
12
+ def setup
13
+ @plugin = ZergXcode.plugin 'ls'
14
+ end
15
+
16
+ def test_list
17
+ golden_list = [
18
+ ["./Classes/TestAppAppDelegate.h", "sourcecode.c.h"],
19
+ ["./Classes/TestAppAppDelegate.m", "sourcecode.c.objc"],
20
+ ["./Classes/TestAppViewController.h", "sourcecode.c.h"],
21
+ ["./Classes/TestAppViewController.m", "sourcecode.c.objc"],
22
+ ["./TestApp_Prefix.pch", "sourcecode.c.h"],
23
+ ["./main.m", "sourcecode.c.objc"],
24
+ ["./TestAppViewController.xib", "file.xib"],
25
+ ["./MainWindow.xib", "file.xib"],
26
+ ["./Info.plist", "text.plist.xml"],
27
+ ["SDKROOT/System/Library/Frameworks/UIKit.framework",
28
+ "wrapper.framework"],
29
+ ["SDKROOT/System/Library/Frameworks/Foundation.framework",
30
+ "wrapper.framework"],
31
+ ["SDKROOT/System/Library/Frameworks/CoreGraphics.framework",
32
+ "wrapper.framework"],
33
+ ["BUILT_PRODUCTS_DIR/TestApp.app", nil]]
34
+ file_list = @plugin.list_for 'testdata/project.pbxproj'
35
+ assert_equal golden_list.sort, file_list.sort
36
+ end
37
+
38
+ def test_run
39
+ output = capture_output { @plugin.run(['testdata']) }
40
+ assert_equal "sourcecode.c.h ./Classes/TestAppAppDelegate.h",
41
+ output[/^(.*?)$/]
42
+ end
43
+ end
@@ -0,0 +1,65 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require 'test/plugins/test_helper.rb'
4
+
5
+ require 'zerg_xcode'
6
+
7
+ require 'rubygems'
8
+ require 'flexmock'
9
+
10
+ module Plugins; end
11
+
12
+ class Plugins::RetargetTest < Test::Unit::TestCase
13
+ def setup
14
+ super
15
+ @plugin = ZergXcode.plugin 'retarget'
16
+ @proj = ZergXcode.load 'testdata/TestApp/TestApp.xcodeproj'
17
+ @regexp = /^Test.*\.[^a]/
18
+
19
+ @golden_list_for_app = [
20
+ ["PBXResourcesBuildPhase", "MainWindow.xib"],
21
+ ["PBXSourcesBuildPhase", "main.m"],
22
+ ["PBXFrameworksBuildPhase",
23
+ "System/Library/Frameworks/Foundation.framework"],
24
+ ["PBXFrameworksBuildPhase",
25
+ "System/Library/Frameworks/UIKit.framework"],
26
+ ["PBXFrameworksBuildPhase",
27
+ "System/Library/Frameworks/CoreGraphics.framework"],
28
+ ]
29
+ @golden_list_for_lib = [
30
+ ["PBXHeadersBuildPhase", "TestAppAppDelegate.h"],
31
+ ["PBXHeadersBuildPhase", "TestAppViewController.h"],
32
+ ["PBXHeadersBuildPhase", "TestApp_Prefix.pch"],
33
+ ["PBXSourcesBuildPhase", "TestAppAppDelegate.m"],
34
+ ["PBXSourcesBuildPhase", "TestAppViewController.m"],
35
+ ["PBXResourcesBuildPhase", "TestAppViewController.xib"],
36
+ ]
37
+ end
38
+
39
+ def file_list_for(target)
40
+ target.all_files.map { |file| [file[:phase]['isa'], file[:object]['path']] }
41
+ end
42
+
43
+ def test_remove_files
44
+ @plugin.retarget! @proj, @regexp, []
45
+ app_file_list, lib_file_list = @proj['targets'].map { |t| file_list_for t }
46
+ assert_equal @golden_list_for_app.sort, app_file_list.sort
47
+ assert_equal [], lib_file_list
48
+ end
49
+
50
+ def test_add_files
51
+ # first remove the files, so they'll be added out of thin air
52
+ @plugin.retarget! @proj, @regexp, []
53
+ @plugin.retarget! @proj, @regexp, ['TestLib']
54
+ app_file_list, lib_file_list = @proj['targets'].map { |t| file_list_for t }
55
+ assert_equal @golden_list_for_app.sort, app_file_list.sort
56
+ assert_equal @golden_list_for_lib, lib_file_list
57
+ end
58
+
59
+ def test_move_files
60
+ @plugin.retarget! @proj, @regexp, ['TestLib']
61
+ app_file_list, lib_file_list = @proj['targets'].map { |t| file_list_for t }
62
+ assert_equal @golden_list_for_app.sort, app_file_list.sort
63
+ assert_equal @golden_list_for_lib, lib_file_list
64
+ end
65
+ end
@@ -0,0 +1,21 @@
1
+ module Plugins; end
2
+
3
+ module Plugins::TestHelper
4
+ # Captures output produced with print.
5
+ def capture_output
6
+ begin
7
+ output = ""
8
+ Kernel.class_eval do
9
+ alias_method :no_print_for_now, :print
10
+ define_method(:print) { |*args| output << args.join }
11
+ end
12
+ yield
13
+ return output
14
+ ensure
15
+ Kernel.class_eval do
16
+ alias_method :print, :no_print_for_now
17
+ undef no_print_for_now
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ require 'test/unit'
2
+ require 'zerg_xcode'
3
+
4
+ class ShortcutsTest < Test::Unit::TestCase
5
+ def test_load
6
+ proj = ZergXcode.load 'testdata/ZergSupport'
7
+ assert_equal ['ZergSupport', 'ZergTestSupport', 'ZergSupportTests'].sort,
8
+ proj['targets'].map { |target| target['name'] }.sort
9
+ assert_equal 'testdata/ZergSupport.xcodeproj/project.pbxproj',
10
+ proj.source_filename, 'Loading did not set project source'
11
+ end
12
+
13
+ def test_plugin
14
+ ls_instance = ZergXcode.plugin 'ls'
15
+ ls_class = ZergXcode::Plugins::Ls
16
+ assert ls_instance.kind_of?(ls_class), 'plugin retrieves wrong object'
17
+ end
18
+ end