backup_checksum 3.0.23

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 (244) hide show
  1. data/.gitignore +7 -0
  2. data/.travis.yml +10 -0
  3. data/Gemfile +28 -0
  4. data/Gemfile.lock +130 -0
  5. data/Guardfile +21 -0
  6. data/LICENSE.md +24 -0
  7. data/README.md +476 -0
  8. data/backup_checksum.gemspec +32 -0
  9. data/bin/backup +11 -0
  10. data/lib/backup.rb +217 -0
  11. data/lib/backup/archive.rb +117 -0
  12. data/lib/backup/binder.rb +22 -0
  13. data/lib/backup/checksum/base.rb +44 -0
  14. data/lib/backup/checksum/shasum.rb +16 -0
  15. data/lib/backup/cleaner.rb +121 -0
  16. data/lib/backup/cli/helpers.rb +88 -0
  17. data/lib/backup/cli/utility.rb +247 -0
  18. data/lib/backup/compressor/base.rb +29 -0
  19. data/lib/backup/compressor/bzip2.rb +50 -0
  20. data/lib/backup/compressor/gzip.rb +47 -0
  21. data/lib/backup/compressor/lzma.rb +50 -0
  22. data/lib/backup/compressor/pbzip2.rb +56 -0
  23. data/lib/backup/config.rb +173 -0
  24. data/lib/backup/configuration/base.rb +15 -0
  25. data/lib/backup/configuration/checksum/base.rb +9 -0
  26. data/lib/backup/configuration/checksum/shasum.rb +9 -0
  27. data/lib/backup/configuration/compressor/base.rb +9 -0
  28. data/lib/backup/configuration/compressor/bzip2.rb +23 -0
  29. data/lib/backup/configuration/compressor/gzip.rb +23 -0
  30. data/lib/backup/configuration/compressor/lzma.rb +23 -0
  31. data/lib/backup/configuration/compressor/pbzip2.rb +28 -0
  32. data/lib/backup/configuration/database/base.rb +19 -0
  33. data/lib/backup/configuration/database/mongodb.rb +49 -0
  34. data/lib/backup/configuration/database/mysql.rb +42 -0
  35. data/lib/backup/configuration/database/postgresql.rb +41 -0
  36. data/lib/backup/configuration/database/redis.rb +39 -0
  37. data/lib/backup/configuration/database/riak.rb +29 -0
  38. data/lib/backup/configuration/encryptor/base.rb +9 -0
  39. data/lib/backup/configuration/encryptor/gpg.rb +17 -0
  40. data/lib/backup/configuration/encryptor/open_ssl.rb +32 -0
  41. data/lib/backup/configuration/helpers.rb +52 -0
  42. data/lib/backup/configuration/notifier/base.rb +28 -0
  43. data/lib/backup/configuration/notifier/campfire.rb +25 -0
  44. data/lib/backup/configuration/notifier/hipchat.rb +41 -0
  45. data/lib/backup/configuration/notifier/mail.rb +112 -0
  46. data/lib/backup/configuration/notifier/presently.rb +25 -0
  47. data/lib/backup/configuration/notifier/prowl.rb +23 -0
  48. data/lib/backup/configuration/notifier/twitter.rb +21 -0
  49. data/lib/backup/configuration/storage/base.rb +18 -0
  50. data/lib/backup/configuration/storage/cloudfiles.rb +25 -0
  51. data/lib/backup/configuration/storage/dropbox.rb +58 -0
  52. data/lib/backup/configuration/storage/ftp.rb +29 -0
  53. data/lib/backup/configuration/storage/local.rb +17 -0
  54. data/lib/backup/configuration/storage/ninefold.rb +20 -0
  55. data/lib/backup/configuration/storage/rsync.rb +29 -0
  56. data/lib/backup/configuration/storage/s3.rb +25 -0
  57. data/lib/backup/configuration/storage/scp.rb +25 -0
  58. data/lib/backup/configuration/storage/sftp.rb +25 -0
  59. data/lib/backup/configuration/syncer/base.rb +10 -0
  60. data/lib/backup/configuration/syncer/cloud.rb +23 -0
  61. data/lib/backup/configuration/syncer/cloud_files.rb +30 -0
  62. data/lib/backup/configuration/syncer/rsync/base.rb +28 -0
  63. data/lib/backup/configuration/syncer/rsync/local.rb +11 -0
  64. data/lib/backup/configuration/syncer/rsync/pull.rb +11 -0
  65. data/lib/backup/configuration/syncer/rsync/push.rb +31 -0
  66. data/lib/backup/configuration/syncer/s3.rb +23 -0
  67. data/lib/backup/database/base.rb +59 -0
  68. data/lib/backup/database/mongodb.rb +232 -0
  69. data/lib/backup/database/mysql.rb +163 -0
  70. data/lib/backup/database/postgresql.rb +146 -0
  71. data/lib/backup/database/redis.rb +139 -0
  72. data/lib/backup/database/riak.rb +69 -0
  73. data/lib/backup/dependency.rb +114 -0
  74. data/lib/backup/encryptor/base.rb +29 -0
  75. data/lib/backup/encryptor/gpg.rb +80 -0
  76. data/lib/backup/encryptor/open_ssl.rb +72 -0
  77. data/lib/backup/errors.rb +124 -0
  78. data/lib/backup/logger.rb +152 -0
  79. data/lib/backup/model.rb +386 -0
  80. data/lib/backup/notifier/base.rb +81 -0
  81. data/lib/backup/notifier/campfire.rb +168 -0
  82. data/lib/backup/notifier/hipchat.rb +99 -0
  83. data/lib/backup/notifier/mail.rb +206 -0
  84. data/lib/backup/notifier/presently.rb +88 -0
  85. data/lib/backup/notifier/prowl.rb +65 -0
  86. data/lib/backup/notifier/twitter.rb +70 -0
  87. data/lib/backup/package.rb +51 -0
  88. data/lib/backup/packager.rb +108 -0
  89. data/lib/backup/pipeline.rb +107 -0
  90. data/lib/backup/splitter.rb +75 -0
  91. data/lib/backup/storage/base.rb +119 -0
  92. data/lib/backup/storage/cloudfiles.rb +87 -0
  93. data/lib/backup/storage/cycler.rb +117 -0
  94. data/lib/backup/storage/dropbox.rb +181 -0
  95. data/lib/backup/storage/ftp.rb +119 -0
  96. data/lib/backup/storage/local.rb +82 -0
  97. data/lib/backup/storage/ninefold.rb +116 -0
  98. data/lib/backup/storage/rsync.rb +149 -0
  99. data/lib/backup/storage/s3.rb +94 -0
  100. data/lib/backup/storage/scp.rb +99 -0
  101. data/lib/backup/storage/sftp.rb +108 -0
  102. data/lib/backup/syncer/base.rb +42 -0
  103. data/lib/backup/syncer/cloud.rb +190 -0
  104. data/lib/backup/syncer/cloud_files.rb +56 -0
  105. data/lib/backup/syncer/rsync/base.rb +52 -0
  106. data/lib/backup/syncer/rsync/local.rb +53 -0
  107. data/lib/backup/syncer/rsync/pull.rb +38 -0
  108. data/lib/backup/syncer/rsync/push.rb +113 -0
  109. data/lib/backup/syncer/s3.rb +47 -0
  110. data/lib/backup/template.rb +46 -0
  111. data/lib/backup/version.rb +43 -0
  112. data/spec/archive_spec.rb +335 -0
  113. data/spec/cleaner_spec.rb +304 -0
  114. data/spec/cli/helpers_spec.rb +176 -0
  115. data/spec/cli/utility_spec.rb +363 -0
  116. data/spec/compressor/base_spec.rb +31 -0
  117. data/spec/compressor/bzip2_spec.rb +83 -0
  118. data/spec/compressor/gzip_spec.rb +83 -0
  119. data/spec/compressor/lzma_spec.rb +83 -0
  120. data/spec/compressor/pbzip2_spec.rb +124 -0
  121. data/spec/config_spec.rb +321 -0
  122. data/spec/configuration/base_spec.rb +35 -0
  123. data/spec/configuration/compressor/bzip2_spec.rb +29 -0
  124. data/spec/configuration/compressor/gzip_spec.rb +29 -0
  125. data/spec/configuration/compressor/lzma_spec.rb +29 -0
  126. data/spec/configuration/compressor/pbzip2_spec.rb +32 -0
  127. data/spec/configuration/database/base_spec.rb +17 -0
  128. data/spec/configuration/database/mongodb_spec.rb +56 -0
  129. data/spec/configuration/database/mysql_spec.rb +53 -0
  130. data/spec/configuration/database/postgresql_spec.rb +53 -0
  131. data/spec/configuration/database/redis_spec.rb +50 -0
  132. data/spec/configuration/database/riak_spec.rb +35 -0
  133. data/spec/configuration/encryptor/gpg_spec.rb +26 -0
  134. data/spec/configuration/encryptor/open_ssl_spec.rb +35 -0
  135. data/spec/configuration/notifier/base_spec.rb +32 -0
  136. data/spec/configuration/notifier/campfire_spec.rb +32 -0
  137. data/spec/configuration/notifier/hipchat_spec.rb +44 -0
  138. data/spec/configuration/notifier/mail_spec.rb +71 -0
  139. data/spec/configuration/notifier/presently_spec.rb +35 -0
  140. data/spec/configuration/notifier/prowl_spec.rb +29 -0
  141. data/spec/configuration/notifier/twitter_spec.rb +35 -0
  142. data/spec/configuration/storage/cloudfiles_spec.rb +41 -0
  143. data/spec/configuration/storage/dropbox_spec.rb +38 -0
  144. data/spec/configuration/storage/ftp_spec.rb +44 -0
  145. data/spec/configuration/storage/local_spec.rb +29 -0
  146. data/spec/configuration/storage/ninefold_spec.rb +32 -0
  147. data/spec/configuration/storage/rsync_spec.rb +41 -0
  148. data/spec/configuration/storage/s3_spec.rb +38 -0
  149. data/spec/configuration/storage/scp_spec.rb +41 -0
  150. data/spec/configuration/storage/sftp_spec.rb +41 -0
  151. data/spec/configuration/syncer/cloud_files_spec.rb +44 -0
  152. data/spec/configuration/syncer/rsync/base_spec.rb +33 -0
  153. data/spec/configuration/syncer/rsync/local_spec.rb +10 -0
  154. data/spec/configuration/syncer/rsync/pull_spec.rb +10 -0
  155. data/spec/configuration/syncer/rsync/push_spec.rb +43 -0
  156. data/spec/configuration/syncer/s3_spec.rb +38 -0
  157. data/spec/database/base_spec.rb +54 -0
  158. data/spec/database/mongodb_spec.rb +428 -0
  159. data/spec/database/mysql_spec.rb +335 -0
  160. data/spec/database/postgresql_spec.rb +278 -0
  161. data/spec/database/redis_spec.rb +260 -0
  162. data/spec/database/riak_spec.rb +108 -0
  163. data/spec/dependency_spec.rb +49 -0
  164. data/spec/encryptor/base_spec.rb +30 -0
  165. data/spec/encryptor/gpg_spec.rb +134 -0
  166. data/spec/encryptor/open_ssl_spec.rb +129 -0
  167. data/spec/errors_spec.rb +306 -0
  168. data/spec/logger_spec.rb +363 -0
  169. data/spec/model_spec.rb +649 -0
  170. data/spec/notifier/base_spec.rb +89 -0
  171. data/spec/notifier/campfire_spec.rb +199 -0
  172. data/spec/notifier/hipchat_spec.rb +188 -0
  173. data/spec/notifier/mail_spec.rb +280 -0
  174. data/spec/notifier/presently_spec.rb +181 -0
  175. data/spec/notifier/prowl_spec.rb +117 -0
  176. data/spec/notifier/twitter_spec.rb +132 -0
  177. data/spec/package_spec.rb +61 -0
  178. data/spec/packager_spec.rb +225 -0
  179. data/spec/pipeline_spec.rb +257 -0
  180. data/spec/spec_helper.rb +59 -0
  181. data/spec/splitter_spec.rb +120 -0
  182. data/spec/storage/base_spec.rb +160 -0
  183. data/spec/storage/cloudfiles_spec.rb +230 -0
  184. data/spec/storage/cycler_spec.rb +239 -0
  185. data/spec/storage/dropbox_spec.rb +370 -0
  186. data/spec/storage/ftp_spec.rb +247 -0
  187. data/spec/storage/local_spec.rb +235 -0
  188. data/spec/storage/ninefold_spec.rb +319 -0
  189. data/spec/storage/rsync_spec.rb +345 -0
  190. data/spec/storage/s3_spec.rb +221 -0
  191. data/spec/storage/scp_spec.rb +209 -0
  192. data/spec/storage/sftp_spec.rb +220 -0
  193. data/spec/syncer/base_spec.rb +22 -0
  194. data/spec/syncer/cloud_files_spec.rb +192 -0
  195. data/spec/syncer/rsync/base_spec.rb +118 -0
  196. data/spec/syncer/rsync/local_spec.rb +121 -0
  197. data/spec/syncer/rsync/pull_spec.rb +90 -0
  198. data/spec/syncer/rsync/push_spec.rb +327 -0
  199. data/spec/syncer/s3_spec.rb +192 -0
  200. data/spec/version_spec.rb +21 -0
  201. data/templates/cli/utility/archive +25 -0
  202. data/templates/cli/utility/compressor/bzip2 +7 -0
  203. data/templates/cli/utility/compressor/gzip +7 -0
  204. data/templates/cli/utility/compressor/lzma +7 -0
  205. data/templates/cli/utility/compressor/pbzip2 +7 -0
  206. data/templates/cli/utility/config +31 -0
  207. data/templates/cli/utility/database/mongodb +18 -0
  208. data/templates/cli/utility/database/mysql +21 -0
  209. data/templates/cli/utility/database/postgresql +17 -0
  210. data/templates/cli/utility/database/redis +16 -0
  211. data/templates/cli/utility/database/riak +11 -0
  212. data/templates/cli/utility/encryptor/gpg +12 -0
  213. data/templates/cli/utility/encryptor/openssl +9 -0
  214. data/templates/cli/utility/model.erb +23 -0
  215. data/templates/cli/utility/notifier/campfire +12 -0
  216. data/templates/cli/utility/notifier/hipchat +15 -0
  217. data/templates/cli/utility/notifier/mail +22 -0
  218. data/templates/cli/utility/notifier/presently +13 -0
  219. data/templates/cli/utility/notifier/prowl +11 -0
  220. data/templates/cli/utility/notifier/twitter +13 -0
  221. data/templates/cli/utility/splitter +7 -0
  222. data/templates/cli/utility/storage/cloud_files +22 -0
  223. data/templates/cli/utility/storage/dropbox +20 -0
  224. data/templates/cli/utility/storage/ftp +12 -0
  225. data/templates/cli/utility/storage/local +7 -0
  226. data/templates/cli/utility/storage/ninefold +9 -0
  227. data/templates/cli/utility/storage/rsync +11 -0
  228. data/templates/cli/utility/storage/s3 +19 -0
  229. data/templates/cli/utility/storage/scp +11 -0
  230. data/templates/cli/utility/storage/sftp +11 -0
  231. data/templates/cli/utility/syncer/cloud_files +48 -0
  232. data/templates/cli/utility/syncer/rsync_local +12 -0
  233. data/templates/cli/utility/syncer/rsync_pull +17 -0
  234. data/templates/cli/utility/syncer/rsync_push +17 -0
  235. data/templates/cli/utility/syncer/s3 +45 -0
  236. data/templates/general/links +11 -0
  237. data/templates/general/version.erb +2 -0
  238. data/templates/notifier/mail/failure.erb +9 -0
  239. data/templates/notifier/mail/success.erb +7 -0
  240. data/templates/notifier/mail/warning.erb +9 -0
  241. data/templates/storage/dropbox/authorization_url.erb +6 -0
  242. data/templates/storage/dropbox/authorized.erb +4 -0
  243. data/templates/storage/dropbox/cache_file_written.erb +10 -0
  244. metadata +311 -0
@@ -0,0 +1,257 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../spec_helper.rb', __FILE__)
4
+
5
+ describe 'Backup::Pipeline' do
6
+ let(:pipeline) { Backup::Pipeline.new }
7
+
8
+ describe '#initialize' do
9
+ it 'should create a new pipeline' do
10
+ pipeline.instance_variable_get(:@commands).should == []
11
+ pipeline.errors.should == []
12
+ pipeline.stderr.should == ''
13
+ end
14
+ end
15
+
16
+ describe '#<<' do
17
+ it 'should add a command string to @commands' do
18
+ pipeline << 'a command string'
19
+ pipeline.instance_variable_get(:@commands).should == ['a command string']
20
+ end
21
+ end
22
+
23
+ describe '#run' do
24
+ let(:stdout) { mock }
25
+ let(:stderr) { mock }
26
+
27
+ before do
28
+ pipeline.expects(:pipeline).returns('foo')
29
+ pipeline.stubs(:stderr_messages).returns('stderr_messages_output')
30
+ # stub CLI::Helpers#command_name so it simply returns what it's passed
31
+ pipeline.class.send(:define_method, :command_name, lambda {|arg| arg } )
32
+ end
33
+
34
+ context 'when pipeline command is successfully executed' do
35
+ before do
36
+ Open4.expects(:popen4).with('foo').yields(nil, nil, stdout, stderr)
37
+ end
38
+
39
+ context 'when all commands within the pipeline are successful' do
40
+ before do
41
+ stdout.expects(:read).returns("0|0:1|0:\n")
42
+ end
43
+
44
+ context 'when commands output no stderr messages' do
45
+ before do
46
+ stderr.expects(:read).returns('')
47
+ end
48
+
49
+ it 'should process the returned stdout/stderr and report no errors' do
50
+ Backup::Logger.expects(:warn).never
51
+
52
+ pipeline.run
53
+ pipeline.stderr.should == ''
54
+ pipeline.errors.should == []
55
+ end
56
+ end
57
+
58
+ context 'when successful commands output messages on stderr' do
59
+ before do
60
+ stderr.expects(:read).returns("stderr output\n")
61
+ end
62
+
63
+ it 'should log a warning with the stderr messages' do
64
+ Backup::Logger.expects(:warn).with('stderr_messages_output')
65
+
66
+ pipeline.run
67
+ pipeline.stderr.should == 'stderr output'
68
+ pipeline.errors.should == []
69
+ end
70
+ end
71
+ end # context 'when all commands within the pipeline are successful'
72
+
73
+ context 'when commands within the pipeline are not successful' do
74
+ before do
75
+ pipeline.instance_variable_set(:@commands, ['first', 'second', 'third'])
76
+ stderr.expects(:read).returns("stderr output\n")
77
+ end
78
+
79
+ context 'when the commands return in sequence' do
80
+ before do
81
+ stdout.expects(:read).returns("0|0:1|1:2|0:\n")
82
+ end
83
+
84
+ it 'should set @errors and @stderr without logging warnings' do
85
+ Backup::Logger.expects(:warn).never
86
+
87
+ pipeline.run
88
+ pipeline.stderr.should == 'stderr output'
89
+ pipeline.errors.count.should be(1)
90
+ pipeline.errors.first.should be_a_kind_of SystemCallError
91
+ pipeline.errors.first.errno.should be(1)
92
+ pipeline.errors.first.message.should match(
93
+ "'second' returned exit code: 1"
94
+ )
95
+ end
96
+ end # context 'when the commands return in sequence'
97
+
98
+ context 'when the commands return out of sequence' do
99
+ before do
100
+ stdout.expects(:read).returns("1|1:2|0:0|0:\n")
101
+ end
102
+
103
+ it 'should properly associate the exitstatus for each command' do
104
+ Backup::Logger.expects(:warn).never
105
+
106
+ pipeline.run
107
+ pipeline.stderr.should == 'stderr output'
108
+ pipeline.errors.count.should be(1)
109
+ pipeline.errors.first.should be_a_kind_of SystemCallError
110
+ pipeline.errors.first.errno.should be(1)
111
+ pipeline.errors.first.message.should match(
112
+ "'second' returned exit code: 1"
113
+ )
114
+ end
115
+ end # context 'when the commands return out of sequence'
116
+
117
+ context 'when multiple commands fail (out of sequence)' do
118
+ before do
119
+ stdout.expects(:read).returns("1|1:2|0:0|3:\n")
120
+ end
121
+
122
+ it 'should properly associate the exitstatus for each command' do
123
+ Backup::Logger.expects(:warn).never
124
+
125
+ pipeline.run
126
+ pipeline.stderr.should == 'stderr output'
127
+ pipeline.errors.count.should be(2)
128
+ pipeline.errors.each {|err| err.should be_a_kind_of SystemCallError }
129
+ pipeline.errors[0].errno.should be(3)
130
+ pipeline.errors[0].message.should match(
131
+ "'first' returned exit code: 3"
132
+ )
133
+ pipeline.errors[1].errno.should be(1)
134
+ pipeline.errors[1].message.should match(
135
+ "'second' returned exit code: 1"
136
+ )
137
+ end
138
+ end # context 'when the commands return (out of sequence)'
139
+
140
+ end # context 'when commands within the pipeline are not successful'
141
+ end # context 'when pipeline command is successfully executed'
142
+
143
+ context 'when pipeline command fails to execute' do
144
+ before do
145
+ Open4.expects(:popen4).with('foo').raises('exec failed')
146
+ end
147
+
148
+ it 'should raise an error' do
149
+ expect do
150
+ pipeline.run
151
+ end.to raise_error(
152
+ Backup::Errors::Pipeline::ExecutionError,
153
+ "Pipeline::ExecutionError: RuntimeError: exec failed"
154
+ )
155
+ end
156
+ end # context 'when pipeline command fails to execute'
157
+
158
+ end # describe '#run'
159
+
160
+ describe '#success?' do
161
+ it 'returns true when @errors is empty' do
162
+ pipeline.success?.should be_true
163
+ end
164
+
165
+ it 'returns false when @errors is not empty' do
166
+ pipeline.instance_variable_set(:@errors, ['foo'])
167
+ pipeline.success?.should be_false
168
+ end
169
+ end # describe '#success?'
170
+
171
+ describe '#error_messages' do
172
+ before do
173
+ pipeline.instance_variable_set(
174
+ :@errors, [
175
+ StandardError.new('standard error'),
176
+ RuntimeError.new('runtime error')
177
+ ]
178
+ )
179
+ end
180
+
181
+ context 'when #stderr_messages has messages' do
182
+ before do
183
+ pipeline.expects(:stderr_messages).returns('stderr messages')
184
+ end
185
+
186
+ it 'should output #stderr_messages and formatted system error messages' do
187
+ pipeline.error_messages.should == 'stderr messages' +
188
+ "The following system errors were returned:\n" +
189
+ "Error: StandardError: standard error\n" +
190
+ "Error: RuntimeError: runtime error"
191
+ end
192
+ end
193
+
194
+ context 'when #stderr_messages has no messages' do
195
+ before do
196
+ pipeline.expects(:stderr_messages).returns(false)
197
+ end
198
+
199
+ it 'should only output the formatted system error messages' do
200
+ pipeline.error_messages.should ==
201
+ "The following system errors were returned:\n" +
202
+ "Error: StandardError: standard error\n" +
203
+ "Error: RuntimeError: runtime error"
204
+ end
205
+ end
206
+ end # describe '#error_messages'
207
+
208
+ describe '#pipeline' do
209
+ context 'when there are multiple system commands to execute' do
210
+ before do
211
+ pipeline.instance_variable_set(:@commands, %w{ one two three })
212
+ end
213
+
214
+ it 'should build a pipeline with redirected/collected exit codes' do
215
+ pipeline.send(:pipeline).should ==
216
+ '( ( one 2>&4; echo "0|$?:" >&3 ) | ' +
217
+ '( two 2>&4; echo "1|$?:" >&3 ) | ' +
218
+ '( three 2>&4; echo "2|$?:" >&3 ) ) 3>&1- 4>&2'
219
+ end
220
+ end
221
+
222
+ context 'when there is only one system command to execute' do
223
+ before do
224
+ pipeline.instance_variable_set(:@commands, ['foo'])
225
+ end
226
+
227
+ it 'should build the command line in the same manner, but without pipes' do
228
+ pipeline.send(:pipeline).should ==
229
+ '( ( foo 2>&4; echo "0|$?:" >&3 ) ) 3>&1- 4>&2'
230
+ end
231
+ end
232
+ end # describe '#pipeline'
233
+
234
+ describe '#stderr_message' do
235
+ context 'when @stderr has messages' do
236
+ before do
237
+ pipeline.instance_variable_set(:@stderr, "stderr message\n output")
238
+ end
239
+
240
+ it 'should return a formatted message with the @stderr messages' do
241
+ pipeline.send(:stderr_messages).should ==
242
+ " Pipeline STDERR Messages:\n" +
243
+ " (Note: may be interleaved if multiple commands returned error messages)\n" +
244
+ "\n" +
245
+ " stderr message\n" +
246
+ " output\n"
247
+ end
248
+ end
249
+
250
+ context 'when @stderr is empty' do
251
+ it 'should return false' do
252
+ pipeline.send(:stderr_messages).should be_false
253
+ end
254
+ end
255
+ end # describe '#stderr_message'
256
+
257
+ end #describe 'Backup::Pipeline'
@@ -0,0 +1,59 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Use Bundler
5
+ require 'rubygems' if RUBY_VERSION < '1.9'
6
+ require 'bundler/setup'
7
+
8
+ ##
9
+ # Load Backup
10
+ require 'backup'
11
+
12
+ require 'timecop'
13
+
14
+ module Backup::ExampleHelpers
15
+ # ripped from MiniTest :)
16
+ # RSpec doesn't have a method for this? Am I missing something?
17
+ def capture_io
18
+ require 'stringio'
19
+
20
+ orig_stdout, orig_stderr = $stdout, $stderr
21
+ captured_stdout, captured_stderr = StringIO.new, StringIO.new
22
+ $stdout, $stderr = captured_stdout, captured_stderr
23
+
24
+ yield
25
+
26
+ return captured_stdout.string, captured_stderr.string
27
+ ensure
28
+ $stdout = orig_stdout
29
+ $stderr = orig_stderr
30
+ end
31
+ end
32
+
33
+ require 'rspec/autorun'
34
+ RSpec.configure do |config|
35
+ ##
36
+ # Use Mocha to mock with RSpec
37
+ config.mock_with :mocha
38
+
39
+ ##
40
+ # Example Helpers
41
+ config.include Backup::ExampleHelpers
42
+
43
+ ##
44
+ # Actions to perform before each example
45
+ config.before(:each) do
46
+ FileUtils.collect_method(:noop).each do |method|
47
+ FileUtils.stubs(method).raises("Unexpected call to FileUtils.#{method}")
48
+ end
49
+ Open4.stubs(:popen4).raises('Unexpected call to Open4::popen4()')
50
+
51
+ [:message, :error, :warn, :normal, :silent].each do |message_type|
52
+ Backup::Logger.stubs(message_type)
53
+ end
54
+ end
55
+ end
56
+
57
+ unless @_put_ruby_version
58
+ puts @_put_ruby_version = "\n\nRuby version: #{RUBY_DESCRIPTION}\n\n"
59
+ end
@@ -0,0 +1,120 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../spec_helper.rb', __FILE__)
4
+
5
+ describe Backup::Splitter do
6
+ let(:model) { Backup::Model.new(:test_trigger, 'test label') }
7
+ let(:splitter) { Backup::Splitter.new(model, 250) }
8
+ let(:package) { mock }
9
+
10
+ describe '#initialize' do
11
+ it 'should set instance variables' do
12
+ splitter.instance_variable_get(:@model).should be(model)
13
+ splitter.instance_variable_get(:@chunk_size).should be(250)
14
+ end
15
+ end
16
+
17
+ describe '#split_with' do
18
+ it 'should yield the split command, performing before/after methods' do
19
+ s = sequence ''
20
+ given_block = mock
21
+ block = lambda {|arg| given_block.got(arg) }
22
+ splitter.instance_variable_set(:@split_command, 'split command')
23
+
24
+ splitter.expects(:before_packaging).in_sequence(s)
25
+ given_block.expects(:got).in_sequence(s).with('split command')
26
+ splitter.expects(:after_packaging).in_sequence(s)
27
+
28
+ splitter.split_with(&block)
29
+ end
30
+ end
31
+
32
+ # Note: using a 'M' suffix for the byte size is not OSX compatible
33
+ describe '#before_packaging' do
34
+ before do
35
+ model.instance_variable_set(:@package, package)
36
+ splitter.expects(:utility).with(:split).returns('split')
37
+ package.expects(:basename).returns('base_filename')
38
+ end
39
+
40
+ it 'should set @package and @split_command' do
41
+ Backup::Logger.expects(:message).with(
42
+ 'Splitter configured with a chunk size of 250MB.'
43
+ )
44
+ splitter.send(:before_packaging)
45
+
46
+ splitter.instance_variable_get(:@package).should be(package)
47
+
48
+ split_suffix = File.join(Backup::Config.tmp_path, 'base_filename-')
49
+ splitter.instance_variable_get(:@split_command).should ==
50
+ "split -b 250m - '#{ split_suffix }'"
51
+ end
52
+ end
53
+
54
+ describe '#after_packaging' do
55
+ before do
56
+ splitter.instance_variable_set(:@package, package)
57
+ end
58
+
59
+ context 'when splitting occurred during packaging' do
60
+ before do
61
+ splitter.expects(:chunk_suffixes).returns(['aa', 'ab'])
62
+ end
63
+
64
+ it 'should set the chunk_suffixes for the package' do
65
+ package.expects(:chunk_suffixes=).with(['aa', 'ab'])
66
+ splitter.send(:after_packaging)
67
+ end
68
+ end
69
+
70
+ context 'when splitting did not occur during packaging' do
71
+ before do
72
+ splitter.expects(:chunk_suffixes).returns(['aa'])
73
+ package.expects(:basename).twice.returns('base_filename')
74
+ end
75
+
76
+ it 'should remove the suffix from the only package file' do
77
+ package.expects(:chunk_suffixes=).never
78
+ FileUtils.expects(:mv).with(
79
+ File.join(Backup::Config.tmp_path, 'base_filename-aa'),
80
+ File.join(Backup::Config.tmp_path, 'base_filename')
81
+ )
82
+ splitter.send(:after_packaging)
83
+ end
84
+ end
85
+ end # describe '#after_packaging'
86
+
87
+ describe '#chunk_suffixes' do
88
+ before do
89
+ splitter.expects(:chunks).returns(
90
+ ['/path/to/file.tar-aa', '/path/to/file.tar-ab']
91
+ )
92
+ end
93
+
94
+ it 'should return an array of chunk suffixes' do
95
+ splitter.send(:chunk_suffixes).should == ['aa', 'ab']
96
+ end
97
+ end
98
+
99
+ describe '#chunks' do
100
+ before do
101
+ splitter.instance_variable_set(:@package, package)
102
+ package.expects(:basename).returns('base_filename')
103
+ FileUtils.unstub(:touch)
104
+ end
105
+
106
+ it 'should return a sorted array of chunked file paths' do
107
+ Dir.mktmpdir do |dir|
108
+ Backup::Config.expects(:tmp_path).returns(dir)
109
+ FileUtils.touch(File.join(dir, 'base_filename-aa'))
110
+ FileUtils.touch(File.join(dir, 'base_filename-ab'))
111
+
112
+ splitter.send(:chunks).should == [
113
+ File.join(dir, 'base_filename-aa'),
114
+ File.join(dir, 'base_filename-ab')
115
+ ]
116
+ end
117
+ end
118
+ end
119
+
120
+ end
@@ -0,0 +1,160 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../../spec_helper.rb', __FILE__)
4
+
5
+ describe Backup::Storage::Base do
6
+ let(:model) { Backup::Model.new(:test_trigger, 'test label') }
7
+ let(:package) { mock("package") }
8
+ let(:checksum_creator) { mock("checksum_creator") }
9
+ let(:base) { Backup::Storage::Base.new(model) }
10
+
11
+ describe '#initialize' do
12
+ it 'should set instance variables' do
13
+ base.instance_variable_get(:@model).should be(model)
14
+ base.instance_variable_defined?(:@storage_id).should be_true
15
+ base.instance_variable_get(:@storage_id).should be_nil
16
+ base.keep.should be_nil
17
+ end
18
+
19
+ context 'when given a storage_id' do
20
+ it 'should set @storage_id' do
21
+ base = Backup::Storage::Base.new(model, 'my storage id')
22
+ base.instance_variable_get(:@storage_id).should == 'my storage id'
23
+ end
24
+ end
25
+
26
+ context 'when configuration defaults are set' do
27
+ after { Backup::Configuration::Storage::Base.clear_defaults! }
28
+ it 'should use the defaults' do
29
+ Backup::Configuration::Storage::Base.defaults do |base|
30
+ base.keep = 5
31
+ end
32
+ base = Backup::Storage::Base.new(model)
33
+ base.keep.should be(5)
34
+ end
35
+ end
36
+ end # describe '#initialize'
37
+
38
+ describe '#perform!' do
39
+ before do
40
+ model.instance_variable_set(:@package, package)
41
+ end
42
+
43
+ it 'should call #transfer!, then #cycle!' do
44
+ s = sequence ''
45
+ base.expects(:transfer!).in_sequence(s)
46
+ base.expects(:cycle!).in_sequence(s)
47
+ base.perform!
48
+ base.instance_variable_get(:@package).should be(package)
49
+ end
50
+
51
+ it "should process checksum file" do
52
+ model.instance_variable_set(:@checksum_creator, checksum_creator)
53
+ package.stubs(:filenames).returns []
54
+ package.stubs(:checksum_name).returns ""
55
+ s = sequence ''
56
+ checksum_creator.expects(:process_checksum_file_before_transfer).in_sequence(s)
57
+ base.expects(:transfer!).in_sequence(s)
58
+
59
+ base.perform!
60
+
61
+ base.instance_variable_get(:@checksum_creator).should be(checksum_creator)
62
+ end
63
+ end
64
+
65
+ describe '#storage_name' do
66
+ context 'when given a storage_id' do
67
+ before { base.storage_id = 'storage id' }
68
+ it 'should return a log-friendly name with the storage_id' do
69
+ base.send(:storage_name).should == 'Storage::Base (storage id)'
70
+ end
71
+ end
72
+
73
+ context 'when not given a storage_id' do
74
+ it 'should return a log-friendly name without a storage_id' do
75
+ base.send(:storage_name).should == 'Storage::Base'
76
+ end
77
+ end
78
+ end
79
+
80
+ describe '#local_path' do
81
+ it 'should return the configured tmp_path' do
82
+ base.send(:local_path).should == Backup::Config.tmp_path
83
+ end
84
+ end
85
+
86
+ describe '#remote_path_for' do
87
+ before do
88
+ package.expects(:trigger).returns('test_trigger')
89
+ package.expects(:time).returns('backup_time')
90
+ base.expects(:path).returns('base/remote/path')
91
+ end
92
+
93
+ it 'should return the remote_path for the given package' do
94
+ base.send(:remote_path_for, package).should ==
95
+ File.join('base/remote/path', 'test_trigger', 'backup_time')
96
+ end
97
+ end
98
+
99
+ describe '#files_to_transfer_for' do
100
+ let(:given_block) { mock }
101
+ before do
102
+ package.stubs(:filenames).returns(
103
+ ['2011.12.31.11.00.02.backup.tar.enc-aa',
104
+ '2011.12.31.11.00.02.backup.tar.enc-ab']
105
+ )
106
+ end
107
+
108
+ it 'should yield the full filename and the filename without the timestamp' do
109
+ given_block.expects(:got).with(
110
+ '2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'
111
+ )
112
+ given_block.expects(:got).with(
113
+ '2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab'
114
+ )
115
+ base.send(:files_to_transfer_for, package) do |local_file, remote_file|
116
+ given_block.got(local_file, remote_file)
117
+ end
118
+ end
119
+
120
+ it 'should have an alias method called #transferred_files_for' do
121
+ base.method(:transferred_files_for).should ==
122
+ base.method(:files_to_transfer_for)
123
+ end
124
+ end
125
+
126
+ describe '#cycle!' do
127
+ before do
128
+ base.stubs(:storage_name).returns('Storage Name')
129
+ base.instance_variable_set(:@package, package)
130
+ end
131
+
132
+ context 'when keep is set and > 0' do
133
+ before { base.keep = 1 }
134
+ it 'should cycle' do
135
+ s = sequence ''
136
+ Backup::Logger.expects(:message).in_sequence(s).
137
+ with('Storage Name: Cycling Started...')
138
+ Backup::Storage::Cycler.expects(:cycle!).in_sequence(s).
139
+ with(base, package)
140
+ Backup::Logger.expects(:message).in_sequence(s).
141
+ with('Storage Name: Cycling Complete!')
142
+
143
+ base.send(:cycle!)
144
+ end
145
+ end
146
+
147
+ context 'when keep is not set or == 0' do
148
+ it 'should return nil when not set' do
149
+ base.keep = nil
150
+ base.send(:cycle!).should be_nil
151
+ end
152
+
153
+ it 'should return nil when == 0' do
154
+ base.keep = 0
155
+ base.send(:cycle!).should be_nil
156
+ end
157
+ end
158
+ end
159
+
160
+ end