backup 3.0.23 → 3.0.24

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 (197) hide show
  1. data/Gemfile.lock +42 -45
  2. data/Guardfile +7 -4
  3. data/README.md +10 -7
  4. data/backup.gemspec +2 -2
  5. data/lib/backup.rb +27 -97
  6. data/lib/backup/archive.rb +14 -6
  7. data/lib/backup/cli/helpers.rb +52 -49
  8. data/lib/backup/cli/utility.rb +9 -1
  9. data/lib/backup/compressor/base.rb +10 -4
  10. data/lib/backup/compressor/bzip2.rb +22 -26
  11. data/lib/backup/compressor/custom.rb +53 -0
  12. data/lib/backup/compressor/gzip.rb +22 -23
  13. data/lib/backup/compressor/lzma.rb +15 -13
  14. data/lib/backup/compressor/pbzip2.rb +20 -17
  15. data/lib/backup/config.rb +6 -3
  16. data/lib/backup/configuration.rb +33 -0
  17. data/lib/backup/configuration/helpers.rb +114 -28
  18. data/lib/backup/configuration/store.rb +24 -0
  19. data/lib/backup/database/base.rb +0 -6
  20. data/lib/backup/database/mongodb.rb +27 -11
  21. data/lib/backup/database/mysql.rb +19 -14
  22. data/lib/backup/database/postgresql.rb +16 -11
  23. data/lib/backup/database/redis.rb +7 -11
  24. data/lib/backup/database/riak.rb +3 -6
  25. data/lib/backup/dependency.rb +5 -11
  26. data/lib/backup/model.rb +14 -5
  27. data/lib/backup/notifier/campfire.rb +3 -16
  28. data/lib/backup/notifier/hipchat.rb +1 -7
  29. data/lib/backup/notifier/mail.rb +1 -1
  30. data/lib/backup/packager.rb +29 -19
  31. data/lib/backup/pipeline.rb +110 -0
  32. data/lib/backup/storage/dropbox.rb +4 -7
  33. data/lib/backup/syncer/base.rb +8 -4
  34. data/lib/backup/syncer/cloud/base.rb +247 -0
  35. data/lib/backup/syncer/cloud/cloud_files.rb +78 -0
  36. data/lib/backup/syncer/cloud/s3.rb +68 -0
  37. data/lib/backup/syncer/rsync/base.rb +1 -4
  38. data/lib/backup/syncer/rsync/local.rb +9 -5
  39. data/lib/backup/syncer/rsync/pull.rb +1 -1
  40. data/lib/backup/syncer/rsync/push.rb +10 -5
  41. data/lib/backup/version.rb +1 -1
  42. data/spec-live/.gitignore +6 -0
  43. data/spec-live/README +7 -0
  44. data/spec-live/backups/config.rb +153 -0
  45. data/spec-live/backups/config.yml.template +43 -0
  46. data/spec-live/compressor/custom_spec.rb +30 -0
  47. data/spec-live/compressor/gzip_spec.rb +30 -0
  48. data/spec-live/notifier/mail_spec.rb +85 -0
  49. data/spec-live/spec_helper.rb +85 -0
  50. data/spec-live/storage/dropbox_spec.rb +151 -0
  51. data/spec-live/storage/local_spec.rb +83 -0
  52. data/spec-live/storage/scp_spec.rb +193 -0
  53. data/spec-live/syncer/cloud/s3_spec.rb +124 -0
  54. data/spec/archive_spec.rb +86 -31
  55. data/spec/cleaner_spec.rb +8 -0
  56. data/spec/cli/helpers_spec.rb +200 -75
  57. data/spec/cli/utility_spec.rb +11 -3
  58. data/spec/compressor/base_spec.rb +31 -10
  59. data/spec/compressor/bzip2_spec.rb +212 -57
  60. data/spec/compressor/custom_spec.rb +106 -0
  61. data/spec/compressor/gzip_spec.rb +212 -57
  62. data/spec/compressor/lzma_spec.rb +75 -35
  63. data/spec/compressor/pbzip2_spec.rb +93 -52
  64. data/spec/configuration/helpers_spec.rb +406 -0
  65. data/spec/configuration/store_spec.rb +39 -0
  66. data/spec/configuration_spec.rb +62 -0
  67. data/spec/database/base_spec.rb +19 -10
  68. data/spec/database/mongodb_spec.rb +195 -70
  69. data/spec/database/mysql_spec.rb +183 -64
  70. data/spec/database/postgresql_spec.rb +167 -53
  71. data/spec/database/redis_spec.rb +121 -46
  72. data/spec/database/riak_spec.rb +96 -27
  73. data/spec/dependency_spec.rb +2 -0
  74. data/spec/encryptor/base_spec.rb +10 -0
  75. data/spec/encryptor/gpg_spec.rb +29 -13
  76. data/spec/encryptor/open_ssl_spec.rb +40 -21
  77. data/spec/logger_spec.rb +4 -0
  78. data/spec/model_spec.rb +19 -2
  79. data/spec/notifier/base_spec.rb +32 -17
  80. data/spec/notifier/campfire_spec.rb +63 -45
  81. data/spec/notifier/hipchat_spec.rb +79 -56
  82. data/spec/notifier/mail_spec.rb +82 -46
  83. data/spec/notifier/prowl_spec.rb +53 -32
  84. data/spec/notifier/twitter_spec.rb +62 -41
  85. data/spec/packager_spec.rb +95 -36
  86. data/spec/pipeline_spec.rb +259 -0
  87. data/spec/spec_helper.rb +6 -5
  88. data/spec/storage/base_spec.rb +61 -41
  89. data/spec/storage/cloudfiles_spec.rb +69 -45
  90. data/spec/storage/dropbox_spec.rb +158 -36
  91. data/spec/storage/ftp_spec.rb +69 -45
  92. data/spec/storage/local_spec.rb +47 -23
  93. data/spec/storage/ninefold_spec.rb +55 -31
  94. data/spec/storage/rsync_spec.rb +67 -50
  95. data/spec/storage/s3_spec.rb +65 -41
  96. data/spec/storage/scp_spec.rb +65 -41
  97. data/spec/storage/sftp_spec.rb +65 -41
  98. data/spec/syncer/base_spec.rb +91 -4
  99. data/spec/syncer/cloud/base_spec.rb +511 -0
  100. data/spec/syncer/cloud/cloud_files_spec.rb +181 -0
  101. data/spec/syncer/cloud/s3_spec.rb +174 -0
  102. data/spec/syncer/rsync/base_spec.rb +46 -66
  103. data/spec/syncer/rsync/local_spec.rb +55 -26
  104. data/spec/syncer/rsync/pull_spec.rb +15 -4
  105. data/spec/syncer/rsync/push_spec.rb +59 -52
  106. data/templates/cli/utility/compressor/bzip2 +1 -4
  107. data/templates/cli/utility/compressor/custom +11 -0
  108. data/templates/cli/utility/compressor/gzip +1 -4
  109. data/templates/cli/utility/compressor/lzma +3 -0
  110. data/templates/cli/utility/compressor/pbzip2 +3 -0
  111. data/templates/cli/utility/database/mysql +4 -1
  112. data/templates/cli/utility/syncer/cloud_files +17 -19
  113. data/templates/cli/utility/syncer/s3 +18 -20
  114. metadata +38 -92
  115. data/lib/backup/configuration/base.rb +0 -15
  116. data/lib/backup/configuration/compressor/base.rb +0 -9
  117. data/lib/backup/configuration/compressor/bzip2.rb +0 -23
  118. data/lib/backup/configuration/compressor/gzip.rb +0 -23
  119. data/lib/backup/configuration/compressor/lzma.rb +0 -23
  120. data/lib/backup/configuration/compressor/pbzip2.rb +0 -28
  121. data/lib/backup/configuration/database/base.rb +0 -19
  122. data/lib/backup/configuration/database/mongodb.rb +0 -49
  123. data/lib/backup/configuration/database/mysql.rb +0 -42
  124. data/lib/backup/configuration/database/postgresql.rb +0 -41
  125. data/lib/backup/configuration/database/redis.rb +0 -39
  126. data/lib/backup/configuration/database/riak.rb +0 -29
  127. data/lib/backup/configuration/encryptor/base.rb +0 -9
  128. data/lib/backup/configuration/encryptor/gpg.rb +0 -17
  129. data/lib/backup/configuration/encryptor/open_ssl.rb +0 -32
  130. data/lib/backup/configuration/notifier/base.rb +0 -28
  131. data/lib/backup/configuration/notifier/campfire.rb +0 -25
  132. data/lib/backup/configuration/notifier/hipchat.rb +0 -41
  133. data/lib/backup/configuration/notifier/mail.rb +0 -112
  134. data/lib/backup/configuration/notifier/presently.rb +0 -25
  135. data/lib/backup/configuration/notifier/prowl.rb +0 -23
  136. data/lib/backup/configuration/notifier/twitter.rb +0 -21
  137. data/lib/backup/configuration/storage/base.rb +0 -18
  138. data/lib/backup/configuration/storage/cloudfiles.rb +0 -25
  139. data/lib/backup/configuration/storage/dropbox.rb +0 -58
  140. data/lib/backup/configuration/storage/ftp.rb +0 -29
  141. data/lib/backup/configuration/storage/local.rb +0 -17
  142. data/lib/backup/configuration/storage/ninefold.rb +0 -20
  143. data/lib/backup/configuration/storage/rsync.rb +0 -29
  144. data/lib/backup/configuration/storage/s3.rb +0 -25
  145. data/lib/backup/configuration/storage/scp.rb +0 -25
  146. data/lib/backup/configuration/storage/sftp.rb +0 -25
  147. data/lib/backup/configuration/syncer/base.rb +0 -10
  148. data/lib/backup/configuration/syncer/cloud.rb +0 -23
  149. data/lib/backup/configuration/syncer/cloud_files.rb +0 -30
  150. data/lib/backup/configuration/syncer/rsync/base.rb +0 -28
  151. data/lib/backup/configuration/syncer/rsync/local.rb +0 -11
  152. data/lib/backup/configuration/syncer/rsync/pull.rb +0 -11
  153. data/lib/backup/configuration/syncer/rsync/push.rb +0 -31
  154. data/lib/backup/configuration/syncer/s3.rb +0 -23
  155. data/lib/backup/notifier/presently.rb +0 -88
  156. data/lib/backup/syncer/cloud.rb +0 -187
  157. data/lib/backup/syncer/cloud_files.rb +0 -56
  158. data/lib/backup/syncer/s3.rb +0 -47
  159. data/spec/configuration/base_spec.rb +0 -35
  160. data/spec/configuration/compressor/bzip2_spec.rb +0 -29
  161. data/spec/configuration/compressor/gzip_spec.rb +0 -29
  162. data/spec/configuration/compressor/lzma_spec.rb +0 -29
  163. data/spec/configuration/compressor/pbzip2_spec.rb +0 -32
  164. data/spec/configuration/database/base_spec.rb +0 -17
  165. data/spec/configuration/database/mongodb_spec.rb +0 -56
  166. data/spec/configuration/database/mysql_spec.rb +0 -53
  167. data/spec/configuration/database/postgresql_spec.rb +0 -53
  168. data/spec/configuration/database/redis_spec.rb +0 -50
  169. data/spec/configuration/database/riak_spec.rb +0 -35
  170. data/spec/configuration/encryptor/gpg_spec.rb +0 -26
  171. data/spec/configuration/encryptor/open_ssl_spec.rb +0 -35
  172. data/spec/configuration/notifier/base_spec.rb +0 -32
  173. data/spec/configuration/notifier/campfire_spec.rb +0 -32
  174. data/spec/configuration/notifier/hipchat_spec.rb +0 -44
  175. data/spec/configuration/notifier/mail_spec.rb +0 -71
  176. data/spec/configuration/notifier/presently_spec.rb +0 -35
  177. data/spec/configuration/notifier/prowl_spec.rb +0 -29
  178. data/spec/configuration/notifier/twitter_spec.rb +0 -35
  179. data/spec/configuration/storage/cloudfiles_spec.rb +0 -41
  180. data/spec/configuration/storage/dropbox_spec.rb +0 -38
  181. data/spec/configuration/storage/ftp_spec.rb +0 -44
  182. data/spec/configuration/storage/local_spec.rb +0 -29
  183. data/spec/configuration/storage/ninefold_spec.rb +0 -32
  184. data/spec/configuration/storage/rsync_spec.rb +0 -41
  185. data/spec/configuration/storage/s3_spec.rb +0 -38
  186. data/spec/configuration/storage/scp_spec.rb +0 -41
  187. data/spec/configuration/storage/sftp_spec.rb +0 -41
  188. data/spec/configuration/syncer/cloud_files_spec.rb +0 -44
  189. data/spec/configuration/syncer/rsync/base_spec.rb +0 -33
  190. data/spec/configuration/syncer/rsync/local_spec.rb +0 -10
  191. data/spec/configuration/syncer/rsync/pull_spec.rb +0 -10
  192. data/spec/configuration/syncer/rsync/push_spec.rb +0 -43
  193. data/spec/configuration/syncer/s3_spec.rb +0 -38
  194. data/spec/notifier/presently_spec.rb +0 -181
  195. data/spec/syncer/cloud_files_spec.rb +0 -192
  196. data/spec/syncer/s3_spec.rb +0 -192
  197. data/templates/cli/utility/notifier/presently +0 -13
@@ -10,29 +10,67 @@ describe 'Backup::Packager' do
10
10
  let(:package) { mock }
11
11
  let(:encryptor) { mock }
12
12
  let(:splitter) { mock }
13
+ let(:pipeline) { mock }
13
14
  let(:procedure) { mock }
14
15
  let(:s) { sequence '' }
15
16
 
16
- it 'should setup variables and perform packaging procedures' do
17
- model.expects(:package).in_sequence(s).returns(package)
18
- model.expects(:encryptor).in_sequence(s).returns(encryptor)
19
- model.expects(:splitter).in_sequence(s).returns(splitter)
20
-
21
- Backup::Logger.expects(:message).in_sequence(s).with(
22
- 'Packaging the backup files...'
23
- )
24
- packager.expects(:procedure).in_sequence(s).returns(procedure)
25
- procedure.expects(:call).in_sequence(s)
26
- Backup::Logger.expects(:message).in_sequence(s).with(
27
- 'Packaging Complete!'
28
- )
29
-
30
- packager.package!(model)
31
-
32
- packager.instance_variable_get(:@package).should be(package)
33
- packager.instance_variable_get(:@encryptor).should be(encryptor)
34
- packager.instance_variable_get(:@splitter).should be(splitter)
35
- end
17
+ context 'when pipeline command is successful' do
18
+ it 'should setup variables and perform packaging procedures' do
19
+ model.expects(:package).in_sequence(s).returns(package)
20
+ model.expects(:encryptor).in_sequence(s).returns(encryptor)
21
+ model.expects(:splitter).in_sequence(s).returns(splitter)
22
+ Backup::Pipeline.expects(:new).in_sequence(s).returns(pipeline)
23
+
24
+ Backup::Logger.expects(:message).in_sequence(s).with(
25
+ 'Packaging the backup files...'
26
+ )
27
+ packager.expects(:procedure).in_sequence(s).returns(procedure)
28
+ procedure.expects(:call).in_sequence(s)
29
+
30
+ pipeline.expects(:success?).in_sequence(s).returns(true)
31
+ Backup::Logger.expects(:message).in_sequence(s).with(
32
+ 'Packaging Complete!'
33
+ )
34
+
35
+ packager.package!(model)
36
+
37
+ packager.instance_variable_get(:@package).should be(package)
38
+ packager.instance_variable_get(:@encryptor).should be(encryptor)
39
+ packager.instance_variable_get(:@splitter).should be(splitter)
40
+ packager.instance_variable_get(:@pipeline).should be(pipeline)
41
+ end
42
+ end #context 'when pipeline command is successful'
43
+
44
+ context 'when pipeline command is not successful' do
45
+ it 'should raise an error' do
46
+ model.expects(:package).in_sequence(s).returns(package)
47
+ model.expects(:encryptor).in_sequence(s).returns(encryptor)
48
+ model.expects(:splitter).in_sequence(s).returns(splitter)
49
+ Backup::Pipeline.expects(:new).in_sequence(s).returns(pipeline)
50
+
51
+ Backup::Logger.expects(:message).in_sequence(s).with(
52
+ 'Packaging the backup files...'
53
+ )
54
+ packager.expects(:procedure).in_sequence(s).returns(procedure)
55
+ procedure.expects(:call).in_sequence(s)
56
+
57
+ pipeline.expects(:success?).in_sequence(s).returns(false)
58
+ pipeline.expects(:error_messages).in_sequence(s).returns('pipeline_errors')
59
+
60
+ expect do
61
+ packager.package!(model)
62
+ end.to raise_error(
63
+ Backup::Errors::Packager::PipelineError,
64
+ "Packager::PipelineError: Failed to Create Backup Package\n" +
65
+ " pipeline_errors"
66
+ )
67
+
68
+ packager.instance_variable_get(:@package).should be(package)
69
+ packager.instance_variable_get(:@encryptor).should be(encryptor)
70
+ packager.instance_variable_get(:@splitter).should be(splitter)
71
+ packager.instance_variable_get(:@pipeline).should be(pipeline)
72
+ end
73
+ end #context 'when pipeline command is successful'
36
74
  end # describe '#package!'
37
75
 
38
76
  describe '#procedure' do
@@ -66,11 +104,14 @@ describe 'Backup::Packager' do
66
104
  let(:package) { Fake::Package.new }
67
105
  let(:encryptor) { Fake::Encryptor.new }
68
106
  let(:splitter) { Fake::Splitter.new }
107
+ let(:pipeline) { mock }
108
+ let(:s) { sequence '' }
69
109
 
70
110
  before do
71
111
  Fake.stack_trace.clear
72
112
  packager.expects(:utility).with(:tar).returns('tar')
73
113
  packager.instance_variable_set(:@package, package)
114
+ packager.instance_variable_set(:@pipeline, pipeline)
74
115
  package.trigger = 'model_trigger'
75
116
  package.extension = 'tar'
76
117
  end
@@ -80,10 +121,14 @@ describe 'Backup::Packager' do
80
121
  packager.instance_variable_set(:@encryptor, nil)
81
122
  packager.instance_variable_set(:@splitter, nil)
82
123
 
83
- packager.expects(:run).with(
84
- "tar -cf - -C '#{ Backup::Config.tmp_path }' 'model_trigger'" +
85
- " > #{ File.join(Backup::Config.tmp_path, 'base_filename.tar') }"
124
+ pipeline.expects(:<<).in_sequence(s).with(
125
+ "tar -cf - -C '#{ Backup::Config.tmp_path }' 'model_trigger'"
86
126
  )
127
+ pipeline.expects(:<<).in_sequence(s).with(
128
+ "cat > #{ File.join(Backup::Config.tmp_path, 'base_filename.tar') }"
129
+ )
130
+ pipeline.expects(:run).in_sequence(s)
131
+
87
132
  packager.send(:procedure).call
88
133
  end
89
134
  end
@@ -93,13 +138,18 @@ describe 'Backup::Packager' do
93
138
  packager.instance_variable_set(:@encryptor, encryptor)
94
139
  packager.instance_variable_set(:@splitter, nil)
95
140
 
96
- packager.expects(:run).with do |command|
141
+ pipeline.expects(:<<).in_sequence(s).with(
142
+ "tar -cf - -C '#{ Backup::Config.tmp_path }' 'model_trigger'"
143
+ )
144
+ pipeline.expects(:<<).in_sequence(s).with('encryption_command')
145
+ pipeline.expects(:<<).in_sequence(s).with(
146
+ "cat > #{ File.join(Backup::Config.tmp_path, 'base_filename.tar.enc') }"
147
+ )
148
+ pipeline.expects(:run).in_sequence(s).with do
97
149
  Fake.stack_trace << :command_executed
98
- command.should ==
99
- "tar -cf - -C '#{ Backup::Config.tmp_path }' 'model_trigger'" +
100
- " | encryption_command" +
101
- " > #{ File.join(Backup::Config.tmp_path, 'base_filename.tar.enc') }"
150
+ true
102
151
  end
152
+
103
153
  packager.send(:procedure).call
104
154
 
105
155
  Fake.stack_trace.should == [
@@ -113,12 +163,16 @@ describe 'Backup::Packager' do
113
163
  packager.instance_variable_set(:@encryptor, nil)
114
164
  packager.instance_variable_set(:@splitter, splitter)
115
165
 
116
- packager.expects(:run).with do |command|
166
+ pipeline.expects(:<<).in_sequence(s).with(
167
+ "tar -cf - -C '#{ Backup::Config.tmp_path }' 'model_trigger'"
168
+ )
169
+ pipeline.expects(:<<).in_sequence(s).with('splitter_command')
170
+
171
+ pipeline.expects(:run).in_sequence(s).with do
117
172
  Fake.stack_trace << :command_executed
118
- command.should ==
119
- "tar -cf - -C '#{ Backup::Config.tmp_path }' 'model_trigger'" +
120
- " | splitter_command"
173
+ true
121
174
  end
175
+
122
176
  packager.send(:procedure).call
123
177
 
124
178
  Fake.stack_trace.should == [
@@ -132,12 +186,17 @@ describe 'Backup::Packager' do
132
186
  packager.instance_variable_set(:@encryptor, encryptor)
133
187
  packager.instance_variable_set(:@splitter, splitter)
134
188
 
135
- packager.expects(:run).with do |command|
189
+ pipeline.expects(:<<).in_sequence(s).with(
190
+ "tar -cf - -C '#{ Backup::Config.tmp_path }' 'model_trigger'"
191
+ )
192
+ pipeline.expects(:<<).in_sequence(s).with('encryption_command')
193
+ pipeline.expects(:<<).in_sequence(s).with('splitter_command')
194
+
195
+ pipeline.expects(:run).in_sequence(s).with do
136
196
  Fake.stack_trace << :command_executed
137
- command.should ==
138
- "tar -cf - -C '#{ Backup::Config.tmp_path }' 'model_trigger'" +
139
- " | encryption_command | splitter_command"
197
+ true
140
198
  end
199
+
141
200
  packager.send(:procedure).call
142
201
 
143
202
  Fake.stack_trace.should == [
@@ -0,0 +1,259 @@
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
+ # stub CLI::Helpers#command_name so it simply returns what it's passed
30
+ pipeline.class.send(:define_method, :command_name, lambda {|arg| arg } )
31
+ end
32
+
33
+ context 'when pipeline command is successfully executed' do
34
+ before do
35
+ Open4.expects(:popen4).with('foo').yields(nil, nil, stdout, stderr)
36
+ end
37
+
38
+ context 'when all commands within the pipeline are successful' do
39
+ before do
40
+ stdout.expects(:read).returns("0|0:1|0:\n")
41
+ end
42
+
43
+ context 'when commands output no stderr messages' do
44
+ before do
45
+ stderr.expects(:read).returns('')
46
+ pipeline.stubs(:stderr_messages).returns(false)
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
+ pipeline.stubs(:stderr_messages).returns('stderr_messages_output')
62
+ end
63
+
64
+ it 'should log a warning with the stderr messages' do
65
+ Backup::Logger.expects(:warn).with('stderr_messages_output')
66
+
67
+ pipeline.run
68
+ pipeline.stderr.should == 'stderr output'
69
+ pipeline.errors.should == []
70
+ end
71
+ end
72
+ end # context 'when all commands within the pipeline are successful'
73
+
74
+ context 'when commands within the pipeline are not successful' do
75
+ before do
76
+ pipeline.instance_variable_set(:@commands, ['first', 'second', 'third'])
77
+ stderr.expects(:read).returns("stderr output\n")
78
+ pipeline.stubs(:stderr_messages).returns('success? should be false')
79
+ end
80
+
81
+ context 'when the commands return in sequence' do
82
+ before do
83
+ stdout.expects(:read).returns("0|0:1|1:2|0:\n")
84
+ end
85
+
86
+ it 'should set @errors and @stderr without logging warnings' do
87
+ Backup::Logger.expects(:warn).never
88
+
89
+ pipeline.run
90
+ pipeline.stderr.should == 'stderr output'
91
+ pipeline.errors.count.should be(1)
92
+ pipeline.errors.first.should be_a_kind_of SystemCallError
93
+ pipeline.errors.first.errno.should be(1)
94
+ pipeline.errors.first.message.should match(
95
+ "'second' returned exit code: 1"
96
+ )
97
+ end
98
+ end # context 'when the commands return in sequence'
99
+
100
+ context 'when the commands return out of sequence' do
101
+ before do
102
+ stdout.expects(:read).returns("1|1:2|0:0|0:\n")
103
+ end
104
+
105
+ it 'should properly associate the exitstatus for each command' do
106
+ Backup::Logger.expects(:warn).never
107
+
108
+ pipeline.run
109
+ pipeline.stderr.should == 'stderr output'
110
+ pipeline.errors.count.should be(1)
111
+ pipeline.errors.first.should be_a_kind_of SystemCallError
112
+ pipeline.errors.first.errno.should be(1)
113
+ pipeline.errors.first.message.should match(
114
+ "'second' returned exit code: 1"
115
+ )
116
+ end
117
+ end # context 'when the commands return out of sequence'
118
+
119
+ context 'when multiple commands fail (out of sequence)' do
120
+ before do
121
+ stdout.expects(:read).returns("1|1:2|0:0|3:\n")
122
+ end
123
+
124
+ it 'should properly associate the exitstatus for each command' do
125
+ Backup::Logger.expects(:warn).never
126
+
127
+ pipeline.run
128
+ pipeline.stderr.should == 'stderr output'
129
+ pipeline.errors.count.should be(2)
130
+ pipeline.errors.each {|err| err.should be_a_kind_of SystemCallError }
131
+ pipeline.errors[0].errno.should be(3)
132
+ pipeline.errors[0].message.should match(
133
+ "'first' returned exit code: 3"
134
+ )
135
+ pipeline.errors[1].errno.should be(1)
136
+ pipeline.errors[1].message.should match(
137
+ "'second' returned exit code: 1"
138
+ )
139
+ end
140
+ end # context 'when the commands return (out of sequence)'
141
+
142
+ end # context 'when commands within the pipeline are not successful'
143
+ end # context 'when pipeline command is successfully executed'
144
+
145
+ context 'when pipeline command fails to execute' do
146
+ before do
147
+ Open4.expects(:popen4).with('foo').raises('exec failed')
148
+ end
149
+
150
+ it 'should raise an error' do
151
+ expect do
152
+ pipeline.run
153
+ end.to raise_error(
154
+ Backup::Errors::Pipeline::ExecutionError,
155
+ "Pipeline::ExecutionError: RuntimeError: exec failed"
156
+ )
157
+ end
158
+ end # context 'when pipeline command fails to execute'
159
+
160
+ end # describe '#run'
161
+
162
+ describe '#success?' do
163
+ it 'returns true when @errors is empty' do
164
+ pipeline.success?.should be_true
165
+ end
166
+
167
+ it 'returns false when @errors is not empty' do
168
+ pipeline.instance_variable_set(:@errors, ['foo'])
169
+ pipeline.success?.should be_false
170
+ end
171
+ end # describe '#success?'
172
+
173
+ describe '#error_messages' do
174
+ before do
175
+ pipeline.instance_variable_set(
176
+ :@errors, [
177
+ StandardError.new('standard error'),
178
+ RuntimeError.new('runtime error')
179
+ ]
180
+ )
181
+ end
182
+
183
+ context 'when #stderr_messages has messages' do
184
+ before do
185
+ pipeline.expects(:stderr_messages).returns('stderr messages')
186
+ end
187
+
188
+ it 'should output #stderr_messages and formatted system error messages' do
189
+ pipeline.error_messages.should == 'stderr messages' +
190
+ "The following system errors were returned:\n" +
191
+ "Error: StandardError: standard error\n" +
192
+ "Error: RuntimeError: runtime error"
193
+ end
194
+ end
195
+
196
+ context 'when #stderr_messages has no messages' do
197
+ before do
198
+ pipeline.expects(:stderr_messages).returns(false)
199
+ end
200
+
201
+ it 'should only output the formatted system error messages' do
202
+ pipeline.error_messages.should ==
203
+ "The following system errors were returned:\n" +
204
+ "Error: StandardError: standard error\n" +
205
+ "Error: RuntimeError: runtime error"
206
+ end
207
+ end
208
+ end # describe '#error_messages'
209
+
210
+ describe '#pipeline' do
211
+ context 'when there are multiple system commands to execute' do
212
+ before do
213
+ pipeline.instance_variable_set(:@commands, %w{ one two three })
214
+ end
215
+
216
+ it 'should build a pipeline with redirected/collected exit codes' do
217
+ pipeline.send(:pipeline).should ==
218
+ '{ { one 2>&4 ; echo "0|$?:" >&3 ; } | ' +
219
+ '{ two 2>&4 ; echo "1|$?:" >&3 ; } | ' +
220
+ '{ three 2>&4 ; echo "2|$?:" >&3 ; } } 3>&1 1>&2 4>&2'
221
+ end
222
+ end
223
+
224
+ context 'when there is only one system command to execute' do
225
+ before do
226
+ pipeline.instance_variable_set(:@commands, ['foo'])
227
+ end
228
+
229
+ it 'should build the command line in the same manner, but without pipes' do
230
+ pipeline.send(:pipeline).should ==
231
+ '{ { foo 2>&4 ; echo "0|$?:" >&3 ; } } 3>&1 1>&2 4>&2'
232
+ end
233
+ end
234
+ end # describe '#pipeline'
235
+
236
+ describe '#stderr_message' do
237
+ context 'when @stderr has messages' do
238
+ before do
239
+ pipeline.instance_variable_set(:@stderr, "stderr message\n output")
240
+ end
241
+
242
+ it 'should return a formatted message with the @stderr messages' do
243
+ pipeline.send(:stderr_messages).should ==
244
+ " Pipeline STDERR Messages:\n" +
245
+ " (Note: may be interleaved if multiple commands returned error messages)\n" +
246
+ "\n" +
247
+ " stderr message\n" +
248
+ " output\n"
249
+ end
250
+ end
251
+
252
+ context 'when @stderr is empty' do
253
+ it 'should return false' do
254
+ pipeline.send(:stderr_messages).should be_false
255
+ end
256
+ end
257
+ end # describe '#stderr_message'
258
+
259
+ end #describe 'Backup::Pipeline'
data/spec/spec_helper.rb CHANGED
@@ -44,16 +44,17 @@ RSpec.configure do |config|
44
44
  # Actions to perform before each example
45
45
  config.before(:each) do
46
46
  FileUtils.collect_method(:noop).each do |method|
47
- FileUtils.stubs(method).raises("Unexpected call to FileUtils.#{method}")
47
+ FileUtils.stubs(method).raises("Unexpected call to FileUtils.#{ method }")
48
48
  end
49
- Open4.stubs(:popen4).raises('Unexpected call to CLI::Helpers.run()')
50
49
 
51
- [:message, :error, :warn, :normal, :silent].each do |message_type|
52
- Backup::Logger.stubs(message_type)
50
+ Open4.stubs(:popen4).raises('Unexpected call to Open4::popen4()')
51
+
52
+ [:message, :error, :warn, :normal, :silent].each do |method|
53
+ Backup::Logger.stubs(method).raises("Unexpected call to Backup::Logger.#{ method }")
53
54
  end
54
55
  end
55
56
  end
56
57
 
57
58
  unless @_put_ruby_version
58
- puts @_put_ruby_version = "\n\nRuby version: #{RUBY_DESCRIPTION}\n\n"
59
+ puts @_put_ruby_version = "\n\nRuby version: #{ RUBY_DESCRIPTION }\n\n"
59
60
  end