automateit 0.70923

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. data.tar.gz.sig +1 -0
  2. data/CHANGES.txt +100 -0
  3. data/Hoe.rake +35 -0
  4. data/Manifest.txt +111 -0
  5. data/README.txt +44 -0
  6. data/Rakefile +284 -0
  7. data/TESTING.txt +57 -0
  8. data/TODO.txt +26 -0
  9. data/TUTORIAL.txt +390 -0
  10. data/bin/ai +3 -0
  11. data/bin/aifield +82 -0
  12. data/bin/aitag +128 -0
  13. data/bin/automateit +117 -0
  14. data/docs/friendly_errors.txt +50 -0
  15. data/docs/previews.txt +86 -0
  16. data/env.sh +4 -0
  17. data/examples/basic/Rakefile +26 -0
  18. data/examples/basic/config/automateit_env.rb +16 -0
  19. data/examples/basic/config/fields.yml +3 -0
  20. data/examples/basic/config/tags.yml +13 -0
  21. data/examples/basic/dist/README.txt +9 -0
  22. data/examples/basic/dist/myapp_server.erb +30 -0
  23. data/examples/basic/install.log +15 -0
  24. data/examples/basic/lib/README.txt +10 -0
  25. data/examples/basic/recipes/README.txt +4 -0
  26. data/examples/basic/recipes/install.rb +53 -0
  27. data/examples/basic/recipes/uninstall.rb +6 -0
  28. data/gpl.txt +674 -0
  29. data/lib/automateit.rb +66 -0
  30. data/lib/automateit/account_manager.rb +106 -0
  31. data/lib/automateit/account_manager/linux.rb +171 -0
  32. data/lib/automateit/account_manager/passwd.rb +69 -0
  33. data/lib/automateit/account_manager/portable.rb +136 -0
  34. data/lib/automateit/address_manager.rb +165 -0
  35. data/lib/automateit/address_manager/linux.rb +80 -0
  36. data/lib/automateit/address_manager/portable.rb +37 -0
  37. data/lib/automateit/cli.rb +80 -0
  38. data/lib/automateit/common.rb +65 -0
  39. data/lib/automateit/constants.rb +33 -0
  40. data/lib/automateit/edit_manager.rb +292 -0
  41. data/lib/automateit/error.rb +10 -0
  42. data/lib/automateit/field_manager.rb +103 -0
  43. data/lib/automateit/interpreter.rb +641 -0
  44. data/lib/automateit/package_manager.rb +242 -0
  45. data/lib/automateit/package_manager/apt.rb +63 -0
  46. data/lib/automateit/package_manager/egg.rb +64 -0
  47. data/lib/automateit/package_manager/gem.rb +179 -0
  48. data/lib/automateit/package_manager/portage.rb +69 -0
  49. data/lib/automateit/package_manager/yum.rb +65 -0
  50. data/lib/automateit/platform_manager.rb +47 -0
  51. data/lib/automateit/platform_manager/darwin.rb +30 -0
  52. data/lib/automateit/platform_manager/debian.rb +26 -0
  53. data/lib/automateit/platform_manager/freebsd.rb +25 -0
  54. data/lib/automateit/platform_manager/gentoo.rb +26 -0
  55. data/lib/automateit/platform_manager/lsb.rb +40 -0
  56. data/lib/automateit/platform_manager/struct.rb +78 -0
  57. data/lib/automateit/platform_manager/uname.rb +29 -0
  58. data/lib/automateit/platform_manager/windows.rb +33 -0
  59. data/lib/automateit/plugin.rb +7 -0
  60. data/lib/automateit/plugin/base.rb +32 -0
  61. data/lib/automateit/plugin/driver.rb +218 -0
  62. data/lib/automateit/plugin/manager.rb +232 -0
  63. data/lib/automateit/project.rb +460 -0
  64. data/lib/automateit/root.rb +14 -0
  65. data/lib/automateit/service_manager.rb +79 -0
  66. data/lib/automateit/service_manager/chkconfig.rb +39 -0
  67. data/lib/automateit/service_manager/rc_update.rb +37 -0
  68. data/lib/automateit/service_manager/sysv.rb +126 -0
  69. data/lib/automateit/service_manager/update_rcd.rb +35 -0
  70. data/lib/automateit/shell_manager.rb +261 -0
  71. data/lib/automateit/shell_manager/base_link.rb +67 -0
  72. data/lib/automateit/shell_manager/link.rb +24 -0
  73. data/lib/automateit/shell_manager/portable.rb +421 -0
  74. data/lib/automateit/shell_manager/symlink.rb +32 -0
  75. data/lib/automateit/shell_manager/which.rb +25 -0
  76. data/lib/automateit/tag_manager.rb +63 -0
  77. data/lib/automateit/tag_manager/struct.rb +101 -0
  78. data/lib/automateit/tag_manager/tag_parser.rb +91 -0
  79. data/lib/automateit/tag_manager/yaml.rb +29 -0
  80. data/lib/automateit/template_manager.rb +55 -0
  81. data/lib/automateit/template_manager/base.rb +172 -0
  82. data/lib/automateit/template_manager/erb.rb +17 -0
  83. data/lib/ext/metaclass.rb +17 -0
  84. data/lib/ext/object.rb +18 -0
  85. data/lib/hashcache.rb +22 -0
  86. data/lib/helpful_erb.rb +63 -0
  87. data/lib/nested_error.rb +33 -0
  88. data/lib/queued_logger.rb +68 -0
  89. data/lib/tempster.rb +239 -0
  90. data/misc/index_gem_repository.rb +303 -0
  91. data/misc/setup_egg.rb +12 -0
  92. data/misc/setup_gem_dependencies.sh +7 -0
  93. data/misc/setup_rubygems.sh +21 -0
  94. data/misc/which.cmd +6 -0
  95. data/spec/extras/automateit_service_sysv_test +50 -0
  96. data/spec/extras/scratch.rb +15 -0
  97. data/spec/extras/simple_recipe.rb +8 -0
  98. data/spec/integration/account_manager_spec.rb +218 -0
  99. data/spec/integration/address_manager_linux_spec.rb +119 -0
  100. data/spec/integration/address_manager_portable_spec.rb +30 -0
  101. data/spec/integration/cli_spec.rb +215 -0
  102. data/spec/integration/examples_spec.rb +54 -0
  103. data/spec/integration/examples_spec_editor.rb +71 -0
  104. data/spec/integration/package_manager_spec.rb +104 -0
  105. data/spec/integration/platform_manager_spec.rb +69 -0
  106. data/spec/integration/service_manager_sysv_spec.rb +115 -0
  107. data/spec/integration/shell_manager_spec.rb +471 -0
  108. data/spec/integration/template_manager_erb_spec.rb +31 -0
  109. data/spec/spec_helper.rb +23 -0
  110. data/spec/unit/edit_manager_spec.rb +162 -0
  111. data/spec/unit/field_manager_spec.rb +79 -0
  112. data/spec/unit/hashcache_spec.rb +28 -0
  113. data/spec/unit/interpreter_spec.rb +98 -0
  114. data/spec/unit/platform_manager_spec.rb +44 -0
  115. data/spec/unit/plugins_spec.rb +253 -0
  116. data/spec/unit/tag_manager_spec.rb +189 -0
  117. data/spec/unit/template_manager_erb_spec.rb +137 -0
  118. metadata +249 -0
  119. metadata.gz.sig +0 -0
@@ -0,0 +1,253 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "/../spec_helper.rb")
2
+
3
+ #===[ stub classes ]====================================================# {{{
4
+
5
+ class MyManager < AutomateIt::Plugin::Manager
6
+ alias_methods :mymethod
7
+
8
+ def mymethod(opts)
9
+ dispatch(opts)
10
+ end
11
+ end
12
+
13
+ class MyManager::BaseDriver < AutomateIt::Plugin::Driver
14
+ # Is abstract by default
15
+ end
16
+
17
+ class MyManager::AnotherBaseDriver < MyManager::BaseDriver
18
+ abstract_driver
19
+ end
20
+
21
+ class MyManager::MyUnsuitableDriver < MyManager::BaseDriver
22
+ # +suitability+ method deliberately not implemented to test errors
23
+
24
+ depends_on \
25
+ :files => ["non_existent_file"],
26
+ :directories => ["non_existent_directory"],
27
+ :programs => ["non_existent_program"]
28
+
29
+ def unavailable_method
30
+ _raise_unless_available
31
+ end
32
+ end
33
+
34
+ class MyManager::MyUnimplementedDriver < MyManager::BaseDriver
35
+ def available?
36
+ true
37
+ end
38
+
39
+ def suitability(method, *args)
40
+ return 50
41
+ end
42
+
43
+ # +mymethod+ method deliberately not implemented to test errors
44
+ end
45
+
46
+
47
+ class MyManager::MyFirstDriver < MyManager::BaseDriver
48
+ depends_on :directories => ["/"]
49
+
50
+ def suitability(method, *args)
51
+ case method
52
+ when :mymethod
53
+ return args.first[:one] == 1 ? 10 : 0
54
+ else
55
+ return -1
56
+ end
57
+ end
58
+
59
+ def mymethod(opts)
60
+ opts[:one]
61
+ end
62
+ end
63
+
64
+ class MyManager::MySecondDriver < MyManager::BaseDriver
65
+ def available?
66
+ true
67
+ end
68
+
69
+ def suitability(method, *args)
70
+ case method
71
+ when :mymethod
72
+ return args.first[:one] == 1 ? 5 : 0
73
+ else
74
+ return -1
75
+ end
76
+ end
77
+
78
+ def mymethod(opts)
79
+ opts[:one]
80
+ end
81
+ end
82
+
83
+ class MyManagerSubclass < AutomateIt::Plugin::Manager
84
+ abstract_manager
85
+ end
86
+
87
+ class MyManagerSubclassImplementation < MyManagerSubclass
88
+ end
89
+ # }}}
90
+ #===[ rspec ]===========================================================
91
+
92
+ describe "AutomateIt::Plugin::Manager" do
93
+ before(:all) do
94
+ @x = AutomateIt::Plugin::Manager
95
+ end
96
+
97
+ it "should have plugins" do
98
+ @x.classes.should include(MyManager)
99
+ end
100
+
101
+ it "should not have abstract plugins" do
102
+ @x.classes.should_not include(MyManagerSubclass)
103
+ end
104
+
105
+ it "should have implementations of abstract plugins" do
106
+ @x.classes.should include(MyManagerSubclassImplementation)
107
+ end
108
+ end
109
+
110
+ describe "MyManager" do
111
+ before(:all) do
112
+ @m = MyManager.new
113
+ end
114
+
115
+ it "should have drivers" do
116
+ for driver in [MyManager::MyUnsuitableDriver, MyManager::MyFirstDriver, MyManager::MySecondDriver]
117
+ @m.class.driver_classes.should include(driver)
118
+ end
119
+ end
120
+
121
+ it "should inherit common instance mehtods" do
122
+ @m.should respond_to(:log)
123
+ end
124
+
125
+ it "should access drivers by index keys" do
126
+ @m[:my_first_driver].should be_a_kind_of(MyManager::MyFirstDriver)
127
+ @m.drivers[:my_first_driver].should be_a_kind_of(MyManager::MyFirstDriver)
128
+ end
129
+
130
+ it "should have aliased methods" do
131
+ @m.class.aliased_methods.should include(:mymethod)
132
+ end
133
+
134
+ it "should respond to aliased methods" do
135
+ @m.should respond_to(:mymethod)
136
+ end
137
+
138
+ it "should have an interpreter instance" do
139
+ @m.interpreter.should be_a_kind_of(AutomateIt::Interpreter)
140
+ end
141
+
142
+ # XXX Plugins spec -- Instantiating a Plugin outside of an Interpreter should retain consistent object references
143
+ # it "should inject interpreter instance into drivers" do
144
+ # @m.interpreter.object_id.should == m[:my_first_driver].interpreter.object_id
145
+ # end
146
+ end
147
+
148
+ describe "MyManager's drivers" do
149
+ before(:all) do
150
+ @m = MyManager.new
151
+ end
152
+
153
+ it "should be available" do
154
+ MyManager::MyFirstDriver.new.available?.should be_true
155
+ end
156
+
157
+ it "should fail on unavailable methods" do
158
+ lambda{ MyManager::MyUnsuitableDriver.new.unavailable_method }.should
159
+ raise_error(NotImplementedError, /non_existent/)
160
+ end
161
+
162
+ it "should have a token" do
163
+ MyManager::MyFirstDriver.token.should == :my_first_driver
164
+ end
165
+
166
+ it "should consider good drivers to be suitable" do
167
+ MyManager::MyFirstDriver.new.suitability(:mymethod, :one => 1).should > 0
168
+ end
169
+
170
+ it "should not consider drivers that don't declare their suitability" do
171
+ MyManager::MyUnsuitableDriver.new.suitability(:mymethod, :one => 1).should < 0
172
+ end
173
+
174
+ it "should determine suitability levels" do
175
+ rs = @m.driver_suitability_levels_for(:mymethod, :one => 1)
176
+ rs[:my_first_driver].should == 10
177
+ rs[:my_second_driver].should == 5
178
+ rs[:my_unsuitable_driver].should be_nil
179
+ end
180
+
181
+ it "should choose suitable driver" do
182
+ @m.driver_for(:mymethod, :one => 1).should be_a_kind_of(MyManager::MyFirstDriver)
183
+ end
184
+
185
+ it "should not choose driver if none match" do
186
+ lambda { @m.driver_for(:mymethod, :one => 9) }.should raise_error(NotImplementedError)
187
+ end
188
+
189
+ it "should dispatch_to suitable driver" do
190
+ @m.dispatch_to(:mymethod, :one => 1).should == 1
191
+ @m.mymethod(:one => 1).should == 1
192
+ end
193
+
194
+ it "should fail dispatch_to if no suitable driver is found" do
195
+ lambda { @m.dispatch_to(:mymethod, :one => 9) }.should raise_error(NotImplementedError)
196
+ lambda { @m.mymethod(:one => 9) }.should raise_error(NotImplementedError)
197
+ end
198
+
199
+ it "should dispatch_to to default driver regardless of suitability" do
200
+ @m.default(:my_unimplemented_driver)
201
+ lambda { @m.dispatch_to(:mymethod, :one => 1) }.should raise_error(NoMethodError)
202
+ lambda { @m.mymethod(:one => 1) }.should raise_error(NoMethodError)
203
+ end
204
+
205
+ it "should have an interpreter instance" do
206
+ MyManager::MyFirstDriver.new.interpreter.should be_a_kind_of(AutomateIt::Interpreter)
207
+ end
208
+
209
+ it "should share object instances" do
210
+ @m[:my_first_driver].should == @m.interpreter.my_manager[:my_first_driver]
211
+ end
212
+ end
213
+
214
+ describe AutomateIt::Interpreter do
215
+ before(:all) do
216
+ @a = AutomateIt::Interpreter.new
217
+ end
218
+
219
+ it "should instantiate plugins" do
220
+ @a.should respond_to(:plugins)
221
+ @a.plugins.should include(:my_manager)
222
+ end
223
+
224
+ it "should expose plugin instance aliases" do
225
+ @a.should respond_to(:my_manager)
226
+ @a.my_manager.class.should == MyManager
227
+ end
228
+
229
+ it "should expose plugin method aliases" do
230
+ @a.should respond_to(:mymethod)
231
+ lambda {@a.mymethod(:one => 1)}.should_not raise_error
232
+ end
233
+
234
+ it "should inject itself into plugins" do
235
+ @a.my_manager.interpreter.should == @a
236
+ end
237
+
238
+ it "should inject itself into drivers" do
239
+ @a.my_manager[:my_first_driver].interpreter.should == @a
240
+ end
241
+
242
+ it "should not see abstract managers" do
243
+ @a.plugins.should_not include(MyManagerSubclass.token)
244
+ end
245
+
246
+ it "should not see abstract drivers" do
247
+ @a.my_manager.drivers.should_not include(MyManager::AnotherBaseDriver.token)
248
+ end
249
+
250
+ it "should not see base drivers" do
251
+ @a.my_manager.drivers.should_not include(MyManager::BaseDriver.token)
252
+ end
253
+ end
@@ -0,0 +1,189 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "/../spec_helper.rb")
2
+
3
+ describe "AutomateIt::TagManager", :shared => true do
4
+ before(:all) do
5
+ @a = AutomateIt.new
6
+ @a.address_manager.should_receive(:hostnames).any_number_of_times.and_return(["kurou", "kurou.foo"])
7
+ @a.platform_manager.setup(
8
+ :default => :struct,
9
+ :struct => {
10
+ :os => "mizrahi",
11
+ :arch => "realian",
12
+ :distro => "momo",
13
+ :version => "s100",
14
+ }
15
+ )
16
+ @m = @a.tag_manager
17
+ end
18
+
19
+ it "should have tags" do
20
+ @a.tags.should be_a_kind_of(Enumerable)
21
+ end
22
+
23
+ it "should have tags that include tag for hostname" do
24
+ @a.tags.should include("kurou")
25
+ end
26
+
27
+ it "should have tag for short hostname" do
28
+ @a.tagged?("kurou").should be_true
29
+ end
30
+
31
+ it "should have tag for long hostname" do
32
+ @a.tagged?("kurou.foo").should be_true
33
+ end
34
+
35
+ it "should have tag for OS" do
36
+ @a.tagged?("mizrahi").should be_true
37
+ end
38
+
39
+ it "should have tag for OS/arch" do
40
+ @a.tagged?("mizrahi_realian").should be_true
41
+ end
42
+
43
+ it "should have tag for distro/release" do
44
+ @a.tagged?("momo_s100").should be_true
45
+ end
46
+
47
+ it "should have tag for a role" do
48
+ @a.tagged?("apache_servers").should be_true
49
+ end
50
+
51
+ it "should match a symbol query" do
52
+ @a.tagged?(:apache_servers).should be_true
53
+ end
54
+
55
+ it "should match a string query" do
56
+ @a.tagged?("apache_servers").should be_true
57
+ end
58
+
59
+ it "should not match unknown symbol keys" do
60
+ @a.tagged?(:foo).should be_false
61
+ end
62
+
63
+ it "should not match unknown string keys" do
64
+ @a.tagged?("foo").should be_false
65
+ end
66
+
67
+ it "should match an AND query" do
68
+ @a.tagged?("kurou && apache_servers").should be_true
69
+ end
70
+
71
+ it "should match an OR query" do
72
+ @a.tagged?("kurou || apache_servers").should be_true
73
+ end
74
+
75
+ it "should match a grouped AND and OR query" do
76
+ @a.tagged?("(kurou || apache_servers) && momo_s100").should be_true
77
+ end
78
+
79
+ it "should not match AND with unknown keys" do
80
+ @a.tagged?("kurou && foo").should be_false
81
+ end
82
+
83
+ it "should not match OR with unknown keys" do
84
+ @a.tagged?("foo && bar").should be_false
85
+ end
86
+
87
+ it "should query tags for a specific host" do
88
+ @a.tagged?("proxy_servers", "kurou").should be_false
89
+ @a.tagged?("proxy_servers", "akane.foo").should be_true
90
+ @a.tagged?("proxy_servers", "akane").should be_true
91
+ end
92
+
93
+ it "should append tags" do
94
+ @a.tagged?("magic").should be_false
95
+ @a.tags << "magic"
96
+ @a.tagged?("magic").should be_true
97
+ end
98
+
99
+ it "should find tags for a host using an array" do
100
+ @a.tags_for(["kurou"]).should include("apache_servers")
101
+ end
102
+
103
+ it "should find tags for a host using a string" do
104
+ @a.tags_for("akane.foo.bar").should include("proxy_servers")
105
+ end
106
+
107
+ it "should find hosts with a tag" do
108
+ hosts = @a.hosts_tagged_with("apache_servers")
109
+ hosts.should include("kurou")
110
+ hosts.should include("shirou")
111
+ hosts.should_not include("akane")
112
+ end
113
+
114
+ it "should find using negative queries" do
115
+ @a.tagged?("akane").should be_false
116
+ @a.tagged?("!akane").should be_true
117
+ @a.tagged?("!akane && !proxy_servers").should be_true
118
+ end
119
+
120
+ it "should include group aliases" do
121
+ @a.hosts_tagged_with("all_servers").sort.should == ["kurou", "shirou", "akane.foo"].sort
122
+ end
123
+
124
+ it "should exclude hosts from groups" do
125
+ @a.hosts_tagged_with("apache_servers_except_kurou").should == ["shirou"]
126
+ end
127
+
128
+ it "should exclude groups from groups" do
129
+ @a.hosts_tagged_with("all_servers_except_proxy_servers").sort.should == ["kurou", "shirou"].sort
130
+ end
131
+ end
132
+
133
+ describe "AutomateIt::TagManager::Struct" do
134
+ it_should_behave_like "AutomateIt::TagManager"
135
+
136
+ before(:all) do
137
+ @m.setup(
138
+ :default => :struct,
139
+ :struct => {
140
+ "apache_servers" => [
141
+ "kurou",
142
+ "shirou",
143
+ ],
144
+ "proxy_servers" => [
145
+ "akane.foo",
146
+ ],
147
+ "all_servers" => [
148
+ "@apache_servers",
149
+ "@proxy_servers",
150
+ ],
151
+ "apache_servers_except_kurou" => [
152
+ "@apache_servers",
153
+ "!kurou",
154
+ ],
155
+ "all_servers_except_proxy_servers" => [
156
+ "@all_servers",
157
+ "!@proxy_servers",
158
+ ],
159
+ }
160
+ )
161
+ end
162
+ end
163
+
164
+ describe "AutomateIt::TagManager::YAML" do
165
+ it_should_behave_like "AutomateIt::TagManager"
166
+
167
+ before(:all) do
168
+ @m[:yaml].should_receive(:_read).with("demo.yml").and_return(<<-EOB)
169
+ <%="apache_servers"%>:
170
+ - kurou
171
+ - shirou
172
+ proxy_servers:
173
+ - akane.foo
174
+ all_servers:
175
+ - @apache_servers
176
+ - @proxy_servers
177
+ apache_servers_except_kurou:
178
+ - @apache_servers
179
+ - !kurou
180
+ all_servers_except_proxy_servers:
181
+ - @all_servers
182
+ - !@proxy_servers
183
+ EOB
184
+ @m.setup(
185
+ :default => :yaml,
186
+ :file => "demo.yml"
187
+ )
188
+ end
189
+ end
@@ -0,0 +1,137 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "/../spec_helper.rb")
2
+
3
+ describe "AutomateIt::TemplateManager::ERB" do
4
+ before(:all) do
5
+ @a = AutomateIt.new(:verbosity => Logger::WARN)
6
+ @m = @a.template_manager
7
+ @d = @m[:erb]
8
+
9
+ @source = "source_for_template"
10
+ @target = "target_for_template"
11
+ end
12
+
13
+ after(:each) do
14
+ if File.exists?(@target)
15
+ File.unlink(@target)
16
+ raise "A write wasn't intercepted by the mocks! Removing file and giving up."
17
+ end
18
+ end
19
+
20
+ it "should render a string template" do
21
+ @d.should_receive(:_exists?).once.with(@target).and_return(false)
22
+ @d.should_receive(:_write).once.with(@target, "my template content").and_return(true)
23
+
24
+ @a.render(:text => "my template content", :to => @target).should be_true
25
+ end
26
+
27
+ it "should render a file template" do
28
+ @d.should_receive(:_exists?).once.with(@source).and_return(true)
29
+ @d.should_receive(:_exists?).once.with(@target).and_return(false)
30
+ @d.should_receive(:_read).once.with(@source).and_return("my template content")
31
+ @d.should_receive(:_write).once.with(@target, "my template content").and_return(true)
32
+
33
+ @a.render(@source, @target).should be_true
34
+ end
35
+
36
+ it "should render with local variables" do
37
+ @d.should_receive(:_exists?).once.with(@source).and_return(true)
38
+ @d.should_receive(:_exists?).once.with(@target).and_return(false)
39
+ @d.should_receive(:_read).once.with(@source).and_return("hello <%=entity%>")
40
+ @d.should_receive(:_write).once.with(@target, "hello world").and_return(true)
41
+
42
+ @a.render(@source, @target, :locals => {:entity => "world"}).should be_true
43
+ end
44
+
45
+ it "should render when the template was updated" do
46
+ timestamp = Time.now
47
+ @d.should_receive(:_exists?).once.with(@source).and_return(true)
48
+ @d.should_receive(:_exists?).once.with(@target).and_return(true)
49
+ @d.should_receive(:_read).once.with(@target).and_return("my old content")
50
+ @d.should_receive(:_read).once.with(@source).and_return("my template content")
51
+ @d.should_receive(:_mtime).once.with(@source).and_return(timestamp+1)
52
+ @d.should_receive(:_mtime).once.with(@target).and_return(timestamp)
53
+ @d.should_receive(:_write).once.with(@target, "my template content").and_return(true)
54
+
55
+ @a.render(@source, @target, :check => :timestamp).should be_true
56
+ end
57
+
58
+ it "shouldn't render when the template wasn't updated" do
59
+ timestamp = Time.now
60
+ @d.should_receive(:_exists?).once.with(@source).and_return(true)
61
+ @d.should_receive(:_exists?).once.with(@target).and_return(true)
62
+ @d.should_receive(:_mtime).once.with(@source).and_return(timestamp)
63
+ @d.should_receive(:_mtime).once.with(@target).and_return(timestamp+1)
64
+
65
+ @a.render(@source, @target, :check => :timestamp).should be_false
66
+ end
67
+
68
+ it "should render when the template's dependencies are updated" do
69
+ timestamp = Time.now
70
+ @d.should_receive(:_exists?).once.with(@source).and_return(true)
71
+ @d.should_receive(:_exists?).once.with(@target).and_return(true)
72
+ @d.should_receive(:_read).once.with(@target).and_return("my old content")
73
+ @d.should_receive(:_read).once.with(@source).and_return("my template content")
74
+ @d.should_receive(:_mtime).once.with("foo").and_return(timestamp+1)
75
+ @d.should_receive(:_mtime).once.with(@source).and_return(timestamp)
76
+ @d.should_receive(:_mtime).once.with(@target).and_return(timestamp)
77
+ @d.should_receive(:_write).once.with(@target, "my template content").and_return(true)
78
+
79
+ @a.render(@source, @target, :check => :timestamp, :dependencies => ["foo"]).should be_true
80
+ end
81
+
82
+ it "shouldn't render when the template's dependencies weren't updated" do
83
+ timestamp = Time.now
84
+ @d.should_receive(:_exists?).once.with(@source).and_return(true)
85
+ @d.should_receive(:_exists?).once.with(@target).and_return(true)
86
+ @d.should_receive(:_mtime).once.with("foo").and_return(timestamp)
87
+ @d.should_receive(:_mtime).once.with(@source).and_return(timestamp)
88
+ @d.should_receive(:_mtime).once.with(@target).and_return(timestamp+1)
89
+
90
+ @a.render(@source, @target, :check => :timestamp, :dependencies => ["foo"]).should be_false
91
+ end
92
+
93
+ it "should render when forced even if the template wasn't updated" do
94
+ @d.should_receive(:_exists?).once.with(@source).and_return(true)
95
+ @d.should_receive(:_exists?).once.with(@target).and_return(true)
96
+ @d.should_receive(:_read).once.with(@target).and_return("my old content")
97
+ @d.should_receive(:_read).once.with(@source).and_return("my template content")
98
+ @d.should_receive(:_write).once.with(@target, "my template content").and_return(true)
99
+
100
+ @a.render(@source, @target, :check => :timestamp, :dependencies => ["foo"], :force => true).should be_true
101
+ end
102
+
103
+ it "should render if told to check the existence of output and it doesn't exist" do
104
+ @d.should_receive(:_exists?).once.with(@source).and_return(true)
105
+ @d.should_receive(:_exists?).once.with(@target).and_return(false)
106
+ @d.should_receive(:_read).once.with(@source).and_return("my template content")
107
+ @d.should_receive(:_write).once.with(@target, "my template content").and_return(true)
108
+
109
+ @a.render(@source, @target, :check => :exists).should be_true
110
+ end
111
+
112
+ it "shouldn't render if told to check the existence of output and it exists" do
113
+ @d.should_receive(:_exists?).once.with(@source).and_return(true)
114
+ @d.should_receive(:_exists?).once.with(@target).and_return(true)
115
+
116
+ @a.render(@source, @target, :check => :exists).should be_false
117
+ end
118
+
119
+ it "should render if told to compare if the output is different" do
120
+ @d.should_receive(:_exists?).once.with(@source).and_return(true)
121
+ @d.should_receive(:_exists?).once.with(@target).and_return(true)
122
+ @d.should_receive(:_read).once.with(@target).and_return("my old content")
123
+ @d.should_receive(:_read).once.with(@source).and_return("my template content")
124
+ @d.should_receive(:_write).once.with(@target, "my template content").and_return(true)
125
+
126
+ @a.render(@source, @target, :check => :compare).should be_true
127
+ end
128
+
129
+ it "shouldn't render if told to compare if the output is the same" do
130
+ @d.should_receive(:_exists?).once.with(@source).and_return(true)
131
+ @d.should_receive(:_exists?).once.with(@target).and_return(true)
132
+ @d.should_receive(:_read).once.with(@target).and_return("my template content")
133
+ @d.should_receive(:_read).once.with(@source).and_return("my template content")
134
+
135
+ @a.render(@source, @target, :check => :compare).should be_false
136
+ end
137
+ end