backup 3.0.20 → 3.0.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (178) hide show
  1. data/Gemfile +1 -5
  2. data/Gemfile.lock +46 -50
  3. data/README.md +54 -27
  4. data/lib/backup.rb +16 -39
  5. data/lib/backup/archive.rb +42 -18
  6. data/lib/backup/cleaner.rb +110 -25
  7. data/lib/backup/cli/helpers.rb +17 -32
  8. data/lib/backup/cli/utility.rb +46 -107
  9. data/lib/backup/compressor/base.rb +14 -2
  10. data/lib/backup/compressor/bzip2.rb +10 -24
  11. data/lib/backup/compressor/gzip.rb +10 -24
  12. data/lib/backup/compressor/lzma.rb +10 -23
  13. data/lib/backup/compressor/pbzip2.rb +12 -32
  14. data/lib/backup/config.rb +171 -0
  15. data/lib/backup/configuration/compressor/base.rb +1 -2
  16. data/lib/backup/configuration/compressor/pbzip2.rb +4 -4
  17. data/lib/backup/configuration/database/base.rb +2 -1
  18. data/lib/backup/configuration/database/mongodb.rb +8 -0
  19. data/lib/backup/configuration/database/mysql.rb +4 -0
  20. data/lib/backup/configuration/database/postgresql.rb +4 -0
  21. data/lib/backup/configuration/database/redis.rb +4 -0
  22. data/lib/backup/configuration/database/riak.rb +5 -1
  23. data/lib/backup/configuration/encryptor/base.rb +1 -2
  24. data/lib/backup/configuration/encryptor/open_ssl.rb +1 -1
  25. data/lib/backup/configuration/helpers.rb +7 -2
  26. data/lib/backup/configuration/notifier/base.rb +4 -28
  27. data/lib/backup/configuration/storage/base.rb +1 -1
  28. data/lib/backup/configuration/storage/dropbox.rb +14 -4
  29. data/lib/backup/configuration/syncer/base.rb +10 -0
  30. data/lib/backup/configuration/syncer/rsync/base.rb +28 -0
  31. data/lib/backup/configuration/syncer/rsync/local.rb +11 -0
  32. data/lib/backup/configuration/syncer/rsync/pull.rb +11 -0
  33. data/lib/backup/configuration/syncer/rsync/push.rb +31 -0
  34. data/lib/backup/configuration/syncer/s3.rb +0 -4
  35. data/lib/backup/database/base.rb +25 -7
  36. data/lib/backup/database/mongodb.rb +112 -75
  37. data/lib/backup/database/mysql.rb +54 -29
  38. data/lib/backup/database/postgresql.rb +60 -42
  39. data/lib/backup/database/redis.rb +61 -39
  40. data/lib/backup/database/riak.rb +35 -11
  41. data/lib/backup/dependency.rb +4 -5
  42. data/lib/backup/encryptor/base.rb +13 -1
  43. data/lib/backup/encryptor/gpg.rb +39 -39
  44. data/lib/backup/encryptor/open_ssl.rb +28 -38
  45. data/lib/backup/logger.rb +20 -11
  46. data/lib/backup/model.rb +206 -163
  47. data/lib/backup/notifier/base.rb +27 -25
  48. data/lib/backup/notifier/campfire.rb +7 -13
  49. data/lib/backup/notifier/hipchat.rb +28 -28
  50. data/lib/backup/notifier/mail.rb +24 -26
  51. data/lib/backup/notifier/presently.rb +10 -18
  52. data/lib/backup/notifier/prowl.rb +9 -17
  53. data/lib/backup/notifier/twitter.rb +11 -18
  54. data/lib/backup/package.rb +47 -0
  55. data/lib/backup/packager.rb +81 -16
  56. data/lib/backup/splitter.rb +48 -35
  57. data/lib/backup/storage/base.rb +44 -172
  58. data/lib/backup/storage/cloudfiles.rb +31 -46
  59. data/lib/backup/storage/cycler.rb +117 -0
  60. data/lib/backup/storage/dropbox.rb +92 -76
  61. data/lib/backup/storage/ftp.rb +30 -40
  62. data/lib/backup/storage/local.rb +44 -45
  63. data/lib/backup/storage/ninefold.rb +55 -49
  64. data/lib/backup/storage/rsync.rb +49 -56
  65. data/lib/backup/storage/s3.rb +33 -44
  66. data/lib/backup/storage/scp.rb +21 -48
  67. data/lib/backup/storage/sftp.rb +26 -40
  68. data/lib/backup/syncer/base.rb +7 -0
  69. data/lib/backup/syncer/rsync/base.rb +78 -0
  70. data/lib/backup/syncer/rsync/local.rb +53 -0
  71. data/lib/backup/syncer/rsync/pull.rb +38 -0
  72. data/lib/backup/syncer/rsync/push.rb +113 -0
  73. data/lib/backup/syncer/s3.rb +42 -32
  74. data/lib/backup/version.rb +1 -1
  75. data/spec/archive_spec.rb +235 -69
  76. data/spec/cleaner_spec.rb +304 -0
  77. data/spec/cli/helpers_spec.rb +142 -1
  78. data/spec/cli/utility_spec.rb +338 -13
  79. data/spec/compressor/base_spec.rb +31 -0
  80. data/spec/compressor/bzip2_spec.rb +60 -35
  81. data/spec/compressor/gzip_spec.rb +60 -35
  82. data/spec/compressor/lzma_spec.rb +60 -35
  83. data/spec/compressor/pbzip2_spec.rb +98 -37
  84. data/spec/config_spec.rb +321 -0
  85. data/spec/configuration/base_spec.rb +4 -4
  86. data/spec/configuration/compressor/bzip2_spec.rb +1 -0
  87. data/spec/configuration/compressor/gzip_spec.rb +1 -0
  88. data/spec/configuration/compressor/lzma_spec.rb +1 -0
  89. data/spec/configuration/compressor/pbzip2_spec.rb +32 -0
  90. data/spec/configuration/database/base_spec.rb +2 -1
  91. data/spec/configuration/database/mongodb_spec.rb +26 -16
  92. data/spec/configuration/database/mysql_spec.rb +4 -0
  93. data/spec/configuration/database/postgresql_spec.rb +4 -0
  94. data/spec/configuration/database/redis_spec.rb +4 -0
  95. data/spec/configuration/database/riak_spec.rb +4 -0
  96. data/spec/configuration/encryptor/gpg_spec.rb +1 -0
  97. data/spec/configuration/encryptor/open_ssl_spec.rb +1 -0
  98. data/spec/configuration/notifier/base_spec.rb +32 -0
  99. data/spec/configuration/notifier/campfire_spec.rb +1 -0
  100. data/spec/configuration/notifier/hipchat_spec.rb +1 -0
  101. data/spec/configuration/notifier/mail_spec.rb +1 -0
  102. data/spec/configuration/notifier/presently_spec.rb +1 -0
  103. data/spec/configuration/notifier/prowl_spec.rb +1 -0
  104. data/spec/configuration/notifier/twitter_spec.rb +1 -0
  105. data/spec/configuration/storage/cloudfiles_spec.rb +1 -0
  106. data/spec/configuration/storage/dropbox_spec.rb +4 -3
  107. data/spec/configuration/storage/ftp_spec.rb +1 -0
  108. data/spec/configuration/storage/local_spec.rb +1 -0
  109. data/spec/configuration/storage/ninefold_spec.rb +1 -0
  110. data/spec/configuration/storage/rsync_spec.rb +3 -1
  111. data/spec/configuration/storage/s3_spec.rb +1 -0
  112. data/spec/configuration/storage/scp_spec.rb +1 -0
  113. data/spec/configuration/storage/sftp_spec.rb +1 -0
  114. data/spec/configuration/syncer/rsync/base_spec.rb +33 -0
  115. data/spec/configuration/syncer/rsync/local_spec.rb +10 -0
  116. data/spec/configuration/syncer/rsync/pull_spec.rb +10 -0
  117. data/spec/configuration/syncer/{rsync_spec.rb → rsync/push_spec.rb} +12 -15
  118. data/spec/configuration/syncer/s3_spec.rb +2 -3
  119. data/spec/database/base_spec.rb +35 -20
  120. data/spec/database/mongodb_spec.rb +298 -119
  121. data/spec/database/mysql_spec.rb +147 -72
  122. data/spec/database/postgresql_spec.rb +155 -100
  123. data/spec/database/redis_spec.rb +200 -97
  124. data/spec/database/riak_spec.rb +82 -24
  125. data/spec/dependency_spec.rb +49 -0
  126. data/spec/encryptor/base_spec.rb +30 -0
  127. data/spec/encryptor/gpg_spec.rb +105 -28
  128. data/spec/encryptor/open_ssl_spec.rb +85 -114
  129. data/spec/logger_spec.rb +74 -8
  130. data/spec/model_spec.rb +528 -220
  131. data/spec/notifier/base_spec.rb +89 -0
  132. data/spec/notifier/campfire_spec.rb +147 -119
  133. data/spec/notifier/hipchat_spec.rb +140 -145
  134. data/spec/notifier/mail_spec.rb +190 -248
  135. data/spec/notifier/presently_spec.rb +147 -282
  136. data/spec/notifier/prowl_spec.rb +79 -111
  137. data/spec/notifier/twitter_spec.rb +87 -106
  138. data/spec/package_spec.rb +61 -0
  139. data/spec/packager_spec.rb +154 -0
  140. data/spec/spec_helper.rb +36 -13
  141. data/spec/splitter_spec.rb +90 -41
  142. data/spec/storage/base_spec.rb +95 -239
  143. data/spec/storage/cloudfiles_spec.rb +185 -75
  144. data/spec/storage/cycler_spec.rb +239 -0
  145. data/spec/storage/dropbox_spec.rb +318 -87
  146. data/spec/storage/ftp_spec.rb +165 -152
  147. data/spec/storage/local_spec.rb +206 -54
  148. data/spec/storage/ninefold_spec.rb +264 -128
  149. data/spec/storage/rsync_spec.rb +244 -163
  150. data/spec/storage/s3_spec.rb +175 -64
  151. data/spec/storage/scp_spec.rb +156 -150
  152. data/spec/storage/sftp_spec.rb +153 -135
  153. data/spec/syncer/base_spec.rb +22 -0
  154. data/spec/syncer/rsync/base_spec.rb +118 -0
  155. data/spec/syncer/rsync/local_spec.rb +121 -0
  156. data/spec/syncer/rsync/pull_spec.rb +90 -0
  157. data/spec/syncer/rsync/push_spec.rb +327 -0
  158. data/spec/syncer/s3_spec.rb +180 -91
  159. data/templates/cli/utility/config +1 -1
  160. data/templates/cli/utility/database/mongodb +4 -0
  161. data/templates/cli/utility/database/mysql +3 -0
  162. data/templates/cli/utility/database/postgresql +3 -0
  163. data/templates/cli/utility/database/redis +3 -0
  164. data/templates/cli/utility/database/riak +3 -0
  165. data/templates/cli/utility/storage/dropbox +4 -1
  166. data/templates/cli/utility/syncer/rsync_local +12 -0
  167. data/templates/cli/utility/syncer/{rsync → rsync_pull} +2 -2
  168. data/templates/cli/utility/syncer/rsync_push +17 -0
  169. data/templates/storage/dropbox/authorization_url.erb +1 -1
  170. metadata +42 -17
  171. data/lib/backup/configuration/syncer/rsync.rb +0 -45
  172. data/lib/backup/finder.rb +0 -87
  173. data/lib/backup/storage/object.rb +0 -47
  174. data/lib/backup/syncer/rsync.rb +0 -152
  175. data/spec/backup_spec.rb +0 -11
  176. data/spec/finder_spec.rb +0 -91
  177. data/spec/storage/object_spec.rb +0 -74
  178. data/spec/syncer/rsync_spec.rb +0 -195
@@ -3,181 +3,317 @@
3
3
  require File.expand_path('../../spec_helper.rb', __FILE__)
4
4
 
5
5
  describe Backup::Storage::Ninefold do
6
-
7
- let(:ninefold) do
8
- Backup::Storage::Ninefold.new do |nf|
9
- nf.storage_token = 'my_storage_token'
10
- nf.storage_secret = 'my_storage_secret'
11
- nf.path = 'backups'
12
- nf.keep = 20
6
+ let(:model) { Backup::Model.new(:test_trigger, 'test label') }
7
+ let(:storage) do
8
+ Backup::Storage::Ninefold.new(model) do |nf|
9
+ nf.storage_token = 'my_token'
10
+ nf.storage_secret = 'my_secret'
11
+ nf.keep = 5
13
12
  end
14
13
  end
15
14
 
16
- before do
17
- Backup::Configuration::Storage::Ninefold.clear_defaults!
18
- end
19
-
20
- it 'should have defined the configuration properly' do
21
- ninefold.storage_token.should == 'my_storage_token'
22
- ninefold.storage_secret.should == 'my_storage_secret'
23
- ninefold.keep.should == 20
24
- end
15
+ describe '#initialize' do
16
+ it 'should set the correct values' do
17
+ storage.storage_token.should == 'my_token'
18
+ storage.storage_secret.should == 'my_secret'
19
+ storage.path.should == 'backups'
25
20
 
26
- it 'should use the defaults if a particular attribute has not been defined' do
27
- Backup::Configuration::Storage::Ninefold.defaults do |nf|
28
- nf.storage_token = 'my_storage_token'
29
- nf.keep = 500
21
+ storage.storage_id.should be_nil
22
+ storage.keep.should == 5
30
23
  end
31
24
 
32
- ninefold = Backup::Storage::Ninefold.new do |nf|
33
- nf.path = 'my/backups'
25
+ it 'should set a storage_id if given' do
26
+ nf = Backup::Storage::Ninefold.new(model, 'my storage_id')
27
+ nf.storage_id.should == 'my storage_id'
34
28
  end
35
29
 
36
- ninefold.storage_token.should == 'my_storage_token' # not defined, uses default
37
- ninefold.storage_secret.should == nil # not defined, no default
38
- ninefold.path.should == 'my/backups' # overwritten from Backup::Storage::Ninefold
39
- ninefold.keep.should == 500 # comes from the default configuration
40
- end
30
+ context 'when setting configuration defaults' do
31
+ after { Backup::Configuration::Storage::Ninefold.clear_defaults! }
41
32
 
42
- describe '#provider' do
43
- it 'should be Ninefold' do
44
- ninefold.provider.should == 'Ninefold'
45
- end
46
- end
33
+ it 'should use the configured defaults' do
34
+ Backup::Configuration::Storage::Ninefold.defaults do |nf|
35
+ nf.storage_token = 'some_token'
36
+ nf.storage_secret = 'some_secret'
37
+ nf.path = 'some_path'
38
+ nf.keep = 15
39
+ end
40
+ storage = Backup::Storage::Ninefold.new(model)
41
+ storage.storage_token.should == 'some_token'
42
+ storage.storage_secret.should == 'some_secret'
43
+ storage.path.should == 'some_path'
44
+
45
+ storage.storage_id.should be_nil
46
+ storage.keep.should == 15
47
+ end
48
+
49
+ it 'should override the configured defaults' do
50
+ Backup::Configuration::Storage::Ninefold.defaults do |nf|
51
+ nf.storage_token = 'old_token'
52
+ nf.storage_secret = 'old_secret'
53
+ nf.path = 'old_path'
54
+ nf.keep = 15
55
+ end
56
+ storage = Backup::Storage::Ninefold.new(model) do |nf|
57
+ nf.storage_token = 'new_token'
58
+ nf.storage_secret = 'new_secret'
59
+ nf.path = 'new_path'
60
+ nf.keep = 10
61
+ end
62
+
63
+ storage.storage_token.should == 'new_token'
64
+ storage.storage_secret.should == 'new_secret'
65
+ storage.path.should == 'new_path'
66
+
67
+ storage.storage_id.should be_nil
68
+ storage.keep.should == 10
69
+ end
70
+ end # context 'when setting configuration defaults'
71
+
72
+ end # describe '#initialize'
47
73
 
48
- describe '#perform' do
49
- it 'should invoke transfer! and cycle!' do
50
- ninefold.expects(:transfer!)
51
- ninefold.expects(:cycle!)
52
- ninefold.perform!
74
+ describe '#provider' do
75
+ it 'should set the Fog provider' do
76
+ storage.send(:provider).should == 'Ninefold'
53
77
  end
54
78
  end
55
79
 
56
80
  describe '#connection' do
57
- it 'should establish and re-use a connection to Ninefold' do
58
- Fog::Storage.expects(:new).once.with({
81
+ let(:connection) { mock }
82
+
83
+ it 'should create a new connection' do
84
+ Fog::Storage.expects(:new).once.with(
59
85
  :provider => 'Ninefold',
60
- :ninefold_storage_token => 'my_storage_token',
61
- :ninefold_storage_secret => 'my_storage_secret'
62
- }).returns(true)
86
+ :ninefold_storage_token => 'my_token',
87
+ :ninefold_storage_secret => 'my_secret'
88
+ ).returns(connection)
89
+ storage.send(:connection).should == connection
90
+ end
63
91
 
64
- ninefold.send(:connection)
65
- ninefold.send(:connection)
92
+ it 'should return an existing connection' do
93
+ Fog::Storage.expects(:new).once.returns(connection)
94
+ storage.send(:connection).should == connection
95
+ storage.send(:connection).should == connection
66
96
  end
67
- end
97
+ end # describe '#connection'
68
98
 
69
- describe '#transfer!' do
70
- let(:connection) { mock('Fog::Storage') }
71
- let(:directories) { mock('Fog::Storage::Ninefold::Directories') }
72
- let(:directory) { mock('Fog::Storage::Ninefold::Directory') }
73
- let(:files) { mock('Fog::Storage::Ninefold::Files') }
99
+ describe '#directory_for' do
100
+ let(:connection) { mock }
101
+ let(:directories) { mock }
102
+ let(:directory) { mock }
74
103
 
75
104
  before do
76
- Fog::Storage.expects(:new).once.returns(connection)
105
+ storage.stubs(:connection).returns(connection)
77
106
  connection.stubs(:directories).returns(directories)
78
- directory.stubs(:files).returns(files)
79
107
  end
80
108
 
81
- context 'directory already exists' do
82
- it 'should transfer the provided file to the directory' do
83
- Backup::Model.new('blah', 'blah') {}
84
- file = mock("Backup::Storage::Ninefold::File")
85
- File.expects(:open).with("#{File.join(Backup::TMP_PATH, "#{ Backup::TIME }.#{ Backup::TRIGGER}")}.tar").returns(file)
86
-
87
- directories.expects(:get).with("backups/myapp/#{ Backup::TIME }").returns(directory)
88
- files.expects(:create) do |options|
89
- options[:key].should == "#{ Backup::TRIGGER }.tar"
90
- options[:body].should == file
91
- end
92
-
93
- ninefold.send(:transfer!)
109
+ context 'when the directory for the remote_path exists' do
110
+ it 'should return the directory' do
111
+ directories.expects(:get).with('remote_path').returns(directory)
112
+ storage.send(:directory_for, 'remote_path').should be(directory)
94
113
  end
95
114
  end
96
115
 
97
- context 'directory does not yet exist' do
98
- it 'should transfer the provided file to the directory' do
99
- Backup::Model.new('blah', 'blah') {}
100
- file = mock("Backup::Storage::Ninefold::File")
101
- File.expects(:open).with("#{File.join(Backup::TMP_PATH, "#{ Backup::TIME }.#{ Backup::TRIGGER}")}.tar").returns(file)
102
-
103
- directories.expects(:get).with("backups/myapp/#{ Backup::TIME }").returns(nil)
104
- directories.expects(:create) { |options|
105
- options[:key].should == "backups/myapp/#{ Backup::TIME }"
106
- }.returns(directory)
116
+ context 'when the directory for the remote_path does not exist' do
117
+ before do
118
+ directories.expects(:get).with('remote_path').returns(nil)
119
+ end
107
120
 
108
- files.expects(:create) do |options|
109
- options[:key].should == "#{ Backup::TRIGGER }.tar"
110
- options[:body].should == file
121
+ context 'when create is set to false' do
122
+ it 'should return nil' do
123
+ storage.send(:directory_for, 'remote_path').should be_nil
111
124
  end
125
+ end
112
126
 
113
- ninefold.send(:transfer!)
127
+ context 'when create is set to true' do
128
+ it 'should create and return the directory' do
129
+ directories.expects(:create).with(:key => 'remote_path').returns(directory)
130
+ storage.send(:directory_for, 'remote_path', true).should be(directory)
131
+ end
114
132
  end
115
133
  end
116
- end
134
+ end # describe '#directory_for'
117
135
 
118
- describe '#remove!' do
119
- let(:connection) { mock('Fog::Storage') }
120
- let(:directories) { mock('Fog::Storage::Ninefold::Directories') }
121
- let(:directory) { mock('Fog::Storage::Ninefold::Directory') }
122
- let(:files) { mock('Fog::Storage::Ninefold::Files') }
123
- let(:file) { mock('Fog::Storage::Ninefold::File') }
136
+ describe '#remote_path_for' do
137
+ let(:package) { mock }
124
138
 
125
139
  before do
126
- Fog::Storage.expects(:new).once.returns(connection)
127
- connection.stubs(:directories).returns(directories)
128
- directory.stubs(:files).returns(files)
140
+ # for superclass method
141
+ package.expects(:trigger).returns('trigger')
142
+ package.expects(:time).returns('time')
129
143
  end
130
144
 
131
- it 'should remove the file from the bucket' do
132
- directories.expects(:get).
133
- with("backups/myapp/#{ Backup::TIME }").
134
- returns(directory)
135
- files.expects(:get).
136
- with("#{ Backup::TRIGGER }.tar").
137
- returns(file)
138
- file.expects(:destroy)
139
- directory.expects(:destroy)
145
+ it 'should remove any preceeding slash from the remote path' do
146
+ storage.path = '/backups'
147
+ storage.send(:remote_path_for, package).should == 'backups/trigger/time'
148
+ end
149
+ end
150
+
151
+ describe '#transfer!' do
152
+ let(:package) { mock }
153
+ let(:directory) { mock }
154
+ let(:directory_files) { mock }
155
+ let(:file) { mock }
156
+ let(:s) { sequence '' }
140
157
 
141
- ninefold.send(:remove!)
158
+ before do
159
+ storage.instance_variable_set(:@package, package)
160
+ storage.stubs(:storage_name).returns('Storage::Ninefold')
161
+ storage.stubs(:local_path).returns('/local/path')
162
+ directory.stubs(:files).returns(directory_files)
142
163
  end
143
164
 
144
- it 'should raise an error if remote_path does not exist' do
145
- directories.expects(:get).
146
- with("backups/myapp/#{ Backup::TIME }").
147
- returns(nil)
148
- files.expects(:get).never
149
- file.expects(:destroy).never
150
- directory.expects(:destroy).never
165
+ it 'should transfer the package files' do
166
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
167
+ returns('remote/path')
168
+ storage.expects(:directory_for).with('remote/path', true).returns(directory)
151
169
 
152
- expect do
153
- ninefold.send(:remove!)
154
- end.to raise_error(
155
- Backup::Errors::Storage::Ninefold::NotFoundError,
156
- "Storage::Ninefold::NotFoundError: " +
157
- "Directory at 'backups/myapp/#{Backup::TIME}' not found"
170
+ storage.expects(:files_to_transfer_for).in_sequence(s).with(package).
171
+ multiple_yields(
172
+ ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
173
+ ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
174
+ )
175
+ # first yield
176
+ Backup::Logger.expects(:message).in_sequence(s).with(
177
+ "Storage::Ninefold started transferring " +
178
+ "'2011.12.31.11.00.02.backup.tar.enc-aa'."
179
+ )
180
+ File.expects(:open).in_sequence(s).with(
181
+ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-aa'), 'r'
182
+ ).yields(file)
183
+ directory_files.expects(:create).in_sequence(s).with(
184
+ :key => 'backup.tar.enc-aa', :body => file
185
+ )
186
+ # second yield
187
+ Backup::Logger.expects(:message).in_sequence(s).with(
188
+ "Storage::Ninefold started transferring " +
189
+ "'2011.12.31.11.00.02.backup.tar.enc-ab'."
190
+ )
191
+ File.expects(:open).in_sequence(s).with(
192
+ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-ab'), 'r'
193
+ ).yields(file)
194
+ directory_files.expects(:create).in_sequence(s).with(
195
+ :key => 'backup.tar.enc-ab', :body => file
158
196
  )
159
197
 
198
+ storage.send(:transfer!)
160
199
  end
200
+ end # describe '#transfer!'
161
201
 
162
- it 'should raise an error if remote_file does not exist' do
163
- directories.expects(:get).
164
- with("backups/myapp/#{ Backup::TIME }").
165
- returns(directory)
166
- files.expects(:get).
167
- with("#{ Backup::TRIGGER }.tar").
168
- returns(nil)
169
- file.expects(:destroy).never
170
- directory.expects(:destroy).never
202
+ describe '#remove!' do
203
+ let(:package) { mock }
204
+ let(:directory) { mock }
205
+ let(:directory_files) { mock }
206
+ let(:file) { mock }
207
+ let(:s) { sequence '' }
171
208
 
172
- expect do
173
- ninefold.send(:remove!)
174
- end.to raise_error(
175
- Backup::Errors::Storage::Ninefold::NotFoundError,
176
- "Storage::Ninefold::NotFoundError: " +
177
- "'#{Backup::TRIGGER}.tar' not found in 'backups/myapp/#{Backup::TIME}'"
209
+ before do
210
+ storage.stubs(:storage_name).returns('Storage::Ninefold')
211
+ directory.stubs(:files).returns(directory_files)
212
+ end
213
+
214
+ it 'should remove the package files' do
215
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
216
+ returns('remote/path')
217
+ storage.expects(:directory_for).with('remote/path').returns(directory)
218
+
219
+ storage.expects(:transferred_files_for).in_sequence(s).with(package).
220
+ multiple_yields(
221
+ ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
222
+ ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
178
223
  )
224
+ # first yield
225
+ Backup::Logger.expects(:message).in_sequence(s).with(
226
+ "Storage::Ninefold started removing " +
227
+ "'2011.12.31.11.00.02.backup.tar.enc-aa' from Ninefold."
228
+ )
229
+ directory_files.expects(:get).in_sequence(s).
230
+ with('backup.tar.enc-aa').returns(file)
231
+ file.expects(:destroy).in_sequence(s)
232
+ # second yield
233
+ Backup::Logger.expects(:message).in_sequence(s).with(
234
+ "Storage::Ninefold started removing " +
235
+ "'2011.12.31.11.00.02.backup.tar.enc-ab' from Ninefold."
236
+ )
237
+ directory_files.expects(:get).in_sequence(s).
238
+ with('backup.tar.enc-ab').returns(file)
239
+ file.expects(:destroy).in_sequence(s)
179
240
 
241
+ directory.expects(:destroy).in_sequence(s)
242
+
243
+ expect do
244
+ storage.send(:remove!, package)
245
+ end.not_to raise_error
180
246
  end
181
- end
247
+
248
+ context 'when the remote directory does not exist' do
249
+ it 'should raise an error' do
250
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
251
+ returns('remote/path')
252
+ storage.expects(:directory_for).with('remote/path').returns(nil)
253
+
254
+ storage.expects(:transferred_files_for).never
255
+ directory_files.expects(:get).never
256
+ file.expects(:destroy).never
257
+ directory.expects(:destroy).never
258
+
259
+ expect do
260
+ storage.send(:remove!, package)
261
+ end.to raise_error {|err|
262
+ err.should be_an_instance_of Backup::Errors::Storage::Ninefold::NotFoundError
263
+ err.message.should == 'Storage::Ninefold::NotFoundError: ' +
264
+ "Directory at 'remote/path' not found"
265
+ }
266
+ end
267
+ end
268
+
269
+ context 'when remote files do not exist' do
270
+ it 'should collect their names and raise an error after proceeding' do
271
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
272
+ returns('remote/path')
273
+ storage.expects(:directory_for).with('remote/path').returns(directory)
274
+
275
+ storage.expects(:transferred_files_for).in_sequence(s).with(package).
276
+ multiple_yields(
277
+ ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
278
+ ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab'],
279
+ ['2011.12.31.11.00.02.backup.tar.enc-ac', 'backup.tar.enc-ac']
280
+ )
281
+ # first yield (file not found)
282
+ Backup::Logger.expects(:message).in_sequence(s).with(
283
+ "Storage::Ninefold started removing " +
284
+ "'2011.12.31.11.00.02.backup.tar.enc-aa' from Ninefold."
285
+ )
286
+ directory_files.expects(:get).in_sequence(s).
287
+ with('backup.tar.enc-aa').returns(nil)
288
+ # second yield (file found and removed)
289
+ Backup::Logger.expects(:message).in_sequence(s).with(
290
+ "Storage::Ninefold started removing " +
291
+ "'2011.12.31.11.00.02.backup.tar.enc-ab' from Ninefold."
292
+ )
293
+ directory_files.expects(:get).in_sequence(s).
294
+ with('backup.tar.enc-ab').returns(file)
295
+ file.expects(:destroy).in_sequence(s)
296
+ # third yield (file not found)
297
+ Backup::Logger.expects(:message).in_sequence(s).with(
298
+ "Storage::Ninefold started removing " +
299
+ "'2011.12.31.11.00.02.backup.tar.enc-ac' from Ninefold."
300
+ )
301
+ directory_files.expects(:get).in_sequence(s).
302
+ with('backup.tar.enc-ac').returns(nil)
303
+
304
+ # directory removed
305
+ directory.expects(:destroy).in_sequence(s)
306
+
307
+ expect do
308
+ storage.send(:remove!, package)
309
+ end.to raise_error {|err|
310
+ err.should be_an_instance_of Backup::Errors::Storage::Ninefold::NotFoundError
311
+ err.message.should == 'Storage::Ninefold::NotFoundError: ' +
312
+ "The following file(s) were not found in 'remote/path'\n" +
313
+ " backup.tar.enc-aa\n backup.tar.enc-ac"
314
+ }
315
+ end
316
+ end
317
+ end # describe '#remove!'
182
318
 
183
319
  end
@@ -3,261 +3,342 @@
3
3
  require File.expand_path('../../spec_helper.rb', __FILE__)
4
4
 
5
5
  describe Backup::Storage::RSync do
6
-
7
- let(:rsync) do
8
- Backup::Storage::RSync.new do |rsync|
6
+ let(:model) { Backup::Model.new(:test_trigger, 'test label') }
7
+ let(:storage) do
8
+ Backup::Storage::RSync.new(model) do |rsync|
9
9
  rsync.username = 'my_username'
10
10
  rsync.password = 'my_password'
11
11
  rsync.ip = '123.45.678.90'
12
- rsync.port = 22
13
- rsync.path = '~/backups/'
12
+ rsync.keep = 5
14
13
  end
15
14
  end
16
15
 
17
- before do
18
- Backup::Configuration::Storage::RSync.clear_defaults!
19
- end
20
-
21
- it 'should have defined the configuration properly' do
22
- rsync.username.should == 'my_username'
23
- rsync.password.should == 'my_password'
24
- rsync.ip.should == '123.45.678.90'
25
- rsync.port.should == 22
26
- rsync.path.should == 'backups/'
27
- rsync.send(:rsync_port).should == "-e 'ssh -p 22'"
28
- end
16
+ describe '#initialize' do
17
+ it 'should set the correct values' do
18
+ storage.username.should == 'my_username'
19
+ storage.password.should == 'my_password'
20
+ storage.ip.should == '123.45.678.90'
21
+ storage.port.should == 22
22
+ storage.path.should == 'backups'
23
+ storage.local.should == false
24
+
25
+ storage.storage_id.should be_nil
26
+ storage.keep.should == 5
27
+ end
29
28
 
30
- it 'should use the defaults if a particular attribute has not been defined' do
31
- Backup::Configuration::Storage::RSync.defaults do |rsync|
32
- rsync.username = 'my_default_username'
33
- rsync.password = 'my_default_password'
34
- rsync.path = '~/backups'
29
+ it 'should set a storage_id if given' do
30
+ rsync = Backup::Storage::RSync.new(model, 'my storage_id')
31
+ rsync.storage_id.should == 'my storage_id'
35
32
  end
36
33
 
37
- rsync = Backup::Storage::RSync.new do |rsync|
38
- rsync.password = 'my_password'
39
- rsync.ip = '123.45.678.90'
34
+ it 'should remove any preceeding tilde and slash from the path' do
35
+ storage = Backup::Storage::RSync.new(model) do |rsync|
36
+ rsync.path = '~/my_backups/path'
37
+ end
38
+ storage.path.should == 'my_backups/path'
40
39
  end
41
40
 
42
- rsync.username.should == 'my_default_username'
43
- rsync.password.should == 'my_password'
44
- rsync.ip.should == '123.45.678.90'
45
- rsync.port.should == 22
46
- rsync.send(:rsync_port).should == "-e 'ssh -p 22'"
47
- end
41
+ context 'when setting configuration defaults' do
42
+ after { Backup::Configuration::Storage::RSync.clear_defaults! }
43
+
44
+ it 'should use the configured defaults' do
45
+ Backup::Configuration::Storage::RSync.defaults do |rsync|
46
+ rsync.username = 'some_username'
47
+ rsync.password = 'some_password'
48
+ rsync.ip = 'some_ip'
49
+ rsync.port = 'some_port'
50
+ rsync.path = 'some_path'
51
+ rsync.local = 'some_local'
52
+ rsync.keep = 'some_keep'
53
+ end
54
+ storage = Backup::Storage::RSync.new(model)
55
+ storage.username.should == 'some_username'
56
+ storage.password.should == 'some_password'
57
+ storage.ip.should == 'some_ip'
58
+ storage.port.should == 'some_port'
59
+ storage.path.should == 'some_path'
60
+ storage.local.should == 'some_local'
61
+
62
+ storage.storage_id.should be_nil
63
+ storage.keep.should == 'some_keep'
64
+ end
48
65
 
49
- it 'should have its own defaults' do
50
- rsync = Backup::Storage::RSync.new
51
- rsync.port.should == 22
52
- rsync.path.should == 'backups'
53
- rsync.local.should == false
54
- rsync.send(:rsync_port).should == "-e 'ssh -p 22'"
55
- end
66
+ it 'should override the configured defaults' do
67
+ Backup::Configuration::Storage::RSync.defaults do |rsync|
68
+ rsync.username = 'old_username'
69
+ rsync.password = 'old_password'
70
+ rsync.ip = 'old_ip'
71
+ rsync.port = 'old_port'
72
+ rsync.path = 'old_path'
73
+ rsync.local = 'old_local'
74
+ rsync.keep = 'old_keep'
75
+ end
76
+ storage = Backup::Storage::RSync.new(model) do |rsync|
77
+ rsync.username = 'new_username'
78
+ rsync.password = 'new_password'
79
+ rsync.ip = 'new_ip'
80
+ rsync.port = 'new_port'
81
+ rsync.path = 'new_path'
82
+ rsync.local = 'new_local'
83
+ rsync.keep = 'new_keep'
84
+ end
56
85
 
57
- describe '#perform' do
58
- it 'should invoke transfer!' do
59
- s = sequence ''
60
- rsync.expects(:write_password_file!).in_sequence(s)
61
- rsync.expects(:transfer!).in_sequence(s)
62
- rsync.expects(:remove_password_file!).in_sequence(s)
86
+ storage.username.should == 'new_username'
87
+ storage.password.should == 'new_password'
88
+ storage.ip.should == 'new_ip'
89
+ storage.port.should == 'new_port'
90
+ storage.path.should == 'new_path'
91
+ storage.local.should == 'new_local'
63
92
 
64
- rsync.perform!
65
- end
93
+ storage.storage_id.should be_nil
94
+ storage.keep.should == 'new_keep'
95
+ end
96
+ end # context 'when setting configuration defaults'
97
+
98
+ end # describe '#initialize'
66
99
 
67
- it 'should ensure any password file is removed' do
68
- s = sequence ''
69
- rsync.expects(:write_password_file!).in_sequence(s)
70
- rsync.expects(:transfer!).in_sequence(s).raises(Exception)
71
- rsync.expects(:remove_password_file!).in_sequence(s)
100
+ describe '#remote_path_for' do
101
+ let(:package) { mock }
102
+ before do
103
+ storage.instance_variable_set(:@package, package)
104
+ package.expects(:trigger).returns(model.trigger)
105
+ end
72
106
 
73
- expect do
74
- rsync.perform!
75
- end.to raise_error
107
+ it 'should override superclass so the time folder is not used' do
108
+ storage.send(:remote_path_for, package).should ==
109
+ File.join('backups', 'test_trigger')
76
110
  end
77
111
  end
78
112
 
79
113
  describe '#connection' do
80
- it 'should establish a connection to the remote server' do
81
- connection = mock
114
+ let(:connection) { mock }
115
+ it 'should yield a Net::SSH connection' do
82
116
  Net::SSH.expects(:start).with(
83
- '123.45.678.90',
84
- 'my_username',
85
- :password => 'my_password',
86
- :port => 22
117
+ '123.45.678.90', 'my_username', :password => 'my_password', :port => 22
87
118
  ).yields(connection)
88
119
 
89
- rsync.send(:connection) do |ssh|
90
- ssh.should be connection
120
+ storage.send(:connection) do |ssh|
121
+ ssh.should be(connection)
91
122
  end
92
123
  end
93
124
  end
94
125
 
95
126
  describe '#transfer!' do
96
- let(:local_file) { File.join(Backup::TMP_PATH, "#{ Backup::TIME }.#{ Backup::TRIGGER }.tar") }
97
- let(:remote_file) { "#{ Backup::TRIGGER }/#{ Backup::TRIGGER }.tar" }
98
- let(:pwdfile) { stub(:path => 'path/to/password/file') }
127
+ let(:package) { mock }
128
+ let(:s) { sequence '' }
99
129
 
100
130
  before do
101
- rsync.expects(:create_remote_directories!)
102
- rsync.expects(:utility).returns('rsync')
103
- Backup::Logger.expects(:message).with(
104
- "Storage::RSync started transferring '#{rsync.filename}' to '#{rsync.ip}'."
105
- )
131
+ storage.instance_variable_set(:@package, package)
132
+ storage.stubs(:storage_name).returns('Storage::RSync')
133
+ storage.stubs(:local_path).returns('/local/path')
134
+ storage.stubs(:rsync_options).returns(:rsync_options)
135
+ storage.stubs(:rsync_port).returns(:rsync_port)
136
+ storage.stubs(:rsync_password_file).returns(:rsync_password_file)
137
+ storage.expects(:utility).with(:rsync).times(0..2).returns('rsync')
106
138
  end
107
139
 
108
- context 'when performing a remote transfer' do
109
- context 'when a password is set' do
110
- before do
111
- rsync.stubs(:write_password_file!)
112
- rsync.instance_variable_set(:@password_file, pwdfile)
113
- end
140
+ context 'when @local is set to false' do
141
+ it 'should transfer the package files to the remote' do
142
+ storage.expects(:write_password_file!).in_sequence(s)
114
143
 
115
- it 'should transfer the provided file to the path' do
116
- rsync.expects(:run).with(
117
- "rsync -z -e 'ssh -p 22' --password-file='path/to/password/file' " +
118
- "'#{local_file}' " +
119
- "'my_username@123.45.678.90:backups/#{remote_file}'"
120
- )
144
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
145
+ returns('remote/path')
121
146
 
122
- rsync.send(:transfer!)
123
- end
124
- end
147
+ storage.expects(:create_remote_path!).in_sequence(s).with('remote/path')
125
148
 
126
- context 'when no password is set' do
127
- before { rsync.password = nil }
149
+ storage.expects(:files_to_transfer_for).in_sequence(s).with(package).
150
+ multiple_yields(
151
+ ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
152
+ ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
153
+ )
154
+ # first yield
155
+ Backup::Logger.expects(:message).in_sequence(s).with(
156
+ "Storage::RSync started transferring " +
157
+ "'2011.12.31.11.00.02.backup.tar.enc-aa' to '123.45.678.90'."
158
+ )
159
+ storage.expects(:run).in_sequence(s).with(
160
+ "rsync rsync_options rsync_port rsync_password_file " +
161
+ "'#{ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-aa') }' " +
162
+ "'my_username@123.45.678.90:#{ File.join('remote/path', 'backup.tar.enc-aa') }'"
163
+ )
164
+ # second yield
165
+ Backup::Logger.expects(:message).in_sequence(s).with(
166
+ "Storage::RSync started transferring " +
167
+ "'2011.12.31.11.00.02.backup.tar.enc-ab' to '123.45.678.90'."
168
+ )
169
+ storage.expects(:run).in_sequence(s).with(
170
+ "rsync rsync_options rsync_port rsync_password_file " +
171
+ "'#{ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-ab') }' " +
172
+ "'my_username@123.45.678.90:#{ File.join('remote/path', 'backup.tar.enc-ab') }'"
173
+ )
128
174
 
129
- it 'should not provide the --password-file option' do
130
- rsync.expects(:run).with(
131
- "rsync -z -e 'ssh -p 22' " +
132
- "'#{local_file}' " +
133
- "'my_username@123.45.678.90:backups/#{remote_file}'"
134
- )
175
+ storage.expects(:remove_password_file!).in_sequence(s)
135
176
 
136
- rsync.send(:transfer!)
137
- end
177
+ storage.send(:transfer!)
138
178
  end
139
179
 
140
- end # context 'when performing a remote transfer'
180
+ it 'should ensure password file removal' do
181
+ storage.expects(:write_password_file!).raises('error message')
182
+ storage.expects(:remove_password_file!)
183
+
184
+ expect do
185
+ storage.send(:transfer!)
186
+ end.to raise_error(RuntimeError, 'error message')
187
+ end
188
+ end # context 'when @local is set to false'
189
+
190
+ context 'when @local is set to true' do
191
+ before { storage.local = true }
192
+
193
+ it 'should transfer the package files locally' do
194
+ storage.expects(:write_password_file!).never
141
195
 
142
- context 'when performing a local transfer' do
143
- before { rsync.local = true }
196
+ storage.expects(:remote_path_for).in_sequence(s).with(package).
197
+ returns('remote/path')
144
198
 
145
- it 'should save a local copy of backups' do
146
- rsync.expects(:run).with(
147
- "rsync '#{local_file}' 'backups/#{remote_file}'"
199
+ storage.expects(:create_remote_path!).in_sequence(s).with('remote/path')
200
+
201
+ storage.expects(:files_to_transfer_for).in_sequence(s).with(package).
202
+ multiple_yields(
203
+ ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'],
204
+ ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab']
205
+ )
206
+ # first yield
207
+ Backup::Logger.expects(:message).in_sequence(s).with(
208
+ "Storage::RSync started transferring " +
209
+ "'2011.12.31.11.00.02.backup.tar.enc-aa' to 'remote/path'."
210
+ )
211
+ storage.expects(:run).in_sequence(s).with(
212
+ "rsync " +
213
+ "'#{ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-aa') }' " +
214
+ "'#{ File.join('remote/path', 'backup.tar.enc-aa') }'"
215
+ )
216
+ # second yield
217
+ Backup::Logger.expects(:message).in_sequence(s).with(
218
+ "Storage::RSync started transferring " +
219
+ "'2011.12.31.11.00.02.backup.tar.enc-ab' to 'remote/path'."
148
220
  )
149
- rsync.send(:transfer!)
221
+ storage.expects(:run).in_sequence(s).with(
222
+ "rsync " +
223
+ "'#{ File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-ab') }' " +
224
+ "'#{ File.join('remote/path', 'backup.tar.enc-ab') }'"
225
+ )
226
+
227
+ storage.expects(:remove_password_file!).never
228
+
229
+ storage.send(:transfer!)
150
230
  end
151
- end # context 'when performing a local transfer'
152
- end
153
231
 
232
+ end # context 'when @local is set to true'
233
+
234
+ end # describe '#transfer!'
235
+
236
+ ##
237
+ # Note: Storage::RSync doesn't cycle
154
238
  describe '#remove!' do
155
- it 'should return nil' do
156
- rsync.send(:remove!).should == nil
239
+ it 'should never even be called' do
240
+ storage.send(:remove!).should be_nil
157
241
  end
158
242
  end
159
243
 
160
- describe '#create_remote_directories!' do
244
+ describe '#create_remote_path!' do
245
+ let(:connection) { mock }
161
246
 
162
- context 'when rsync.local is false' do
163
- it 'should create directories on the remote server' do
164
- ssh = mock
165
- rsync.expects(:mkdir).never
166
- rsync.expects(:connection).yields(ssh)
167
- ssh.expects(:exec!).with("mkdir -p '#{rsync.remote_path}'")
247
+ context 'when @local is set to false' do
248
+ it 'should create the remote_path on the remote' do
249
+ FileUtils.expects(:mkdir_p).never
168
250
 
169
- rsync.send(:create_remote_directories!)
251
+ storage.expects(:connection).yields(connection)
252
+ connection.expects(:exec!).with("mkdir -p 'remote/path'")
253
+
254
+ storage.send(:create_remote_path!, 'remote/path')
170
255
  end
171
256
  end
172
257
 
173
- context 'when rsync.local is true' do
174
- before { rsync.local = true }
175
- it 'should create directories locally' do
176
- rsync.expects(:mkdir).with(rsync.remote_path)
177
- rsync.expects(:connection).never
258
+ context 'when @local is set to true' do
259
+ before { storage.local = true }
260
+ it 'should create the remote_path locally' do
261
+ storage.expects(:connection).never
262
+
263
+ FileUtils.expects(:mkdir_p).with('remote/path')
178
264
 
179
- rsync.send(:create_remote_directories!)
265
+ storage.send(:create_remote_path!, 'remote/path')
180
266
  end
181
267
  end
182
-
183
268
  end
184
269
 
185
270
  describe '#write_password_file!' do
271
+ let(:file) { mock }
186
272
 
187
- before do
188
- rsync.instance_variable_defined?(:@password_file).should be_false
189
- end
273
+ context 'when a @password is set' do
274
+ it 'should write the password to file and set @password_file' do
275
+ Tempfile.expects(:new).with('backup-rsync-password').returns(file)
276
+ file.expects(:write).with('my_password')
277
+ file.expects(:close)
190
278
 
191
- context 'when a password is set' do
192
- it 'should write the password file' do
193
- rsync.send(:write_password_file!)
194
- password_file = rsync.instance_variable_get(:@password_file)
195
- password_file.should respond_to(:path)
196
- File.read(password_file.path).should == 'my_password'
279
+ storage.send(:write_password_file!)
280
+ storage.instance_variable_get(:@password_file).should be(file)
197
281
  end
198
282
  end
199
283
 
200
- context 'when a password is not set' do
201
- before { rsync.password = nil }
202
- it 'should return nil' do
203
- rsync.send(:write_password_file!).should be_nil
284
+ context 'when a @password is not set' do
285
+ before { storage.password = nil }
286
+ it 'should do nothing' do
287
+ Tempfile.expects(:new).never
288
+
289
+ storage.send(:write_password_file!)
290
+ storage.instance_variable_get(:@password_file).should be_nil
204
291
  end
205
292
  end
206
-
207
- end # describe '#write_password_file!'
293
+ end
208
294
 
209
295
  describe '#remove_password_file!' do
210
- let(:pwdfile) { mock }
296
+ let(:file) { mock }
211
297
 
212
298
  context 'when @password_file is set' do
213
- before do
214
- rsync.instance_variable_set(:@password_file, pwdfile)
215
- end
216
-
217
- it 'should remove the password file' do
218
- pwdfile.expects(:delete)
219
- rsync.send(:remove_password_file!)
299
+ before { storage.instance_variable_set(:@password_file, file) }
300
+ it 'should delete the file and clear @password_file' do
301
+ file.expects(:delete)
302
+ storage.send(:remove_password_file!)
303
+ storage.instance_variable_get(:@password_file).should be_nil
220
304
  end
221
305
  end
222
306
 
223
307
  context 'when @password_file is not set' do
224
- it 'should return nil' do
225
- rsync.send(:remove_password_file!).should be_nil
308
+ it 'should do nothing' do
309
+ file.expects(:delete).never
310
+ storage.send(:remove_password_file!)
226
311
  end
227
312
  end
228
-
229
- end # describe '#remove_password_file!'
313
+ end
230
314
 
231
315
  describe '#rsync_password_file' do
232
- let(:pwdfile) { stub(:path => 'path/to/password/file') }
316
+ let(:file) { mock }
233
317
 
234
318
  context 'when @password_file is set' do
235
- before do
236
- rsync.instance_variable_set(:@password_file, pwdfile)
237
- end
238
-
239
- it 'should return the password file string for the rsync command' do
240
- rsync.send(:rsync_password_file).should == "--password-file='path/to/password/file'"
319
+ before { storage.instance_variable_set(:@password_file, file) }
320
+ it 'should return the syntax for rsync to use the password file' do
321
+ file.expects(:path).returns('/path/to/file')
322
+ storage.send(:rsync_password_file).should == "--password-file='/path/to/file'"
241
323
  end
242
324
  end
243
325
 
244
- context 'when a password is not set' do
326
+ context 'when @password_file is not set' do
245
327
  it 'should return nil' do
246
- rsync.send(:rsync_password_file).should be_nil
328
+ storage.send(:rsync_password_file).should be_nil
247
329
  end
248
330
  end
249
-
250
- end # describe '#password_file'
331
+ end
251
332
 
252
333
  describe '#rsync_port' do
253
- it 'should return the port string for the rsync command' do
254
- rsync.send(:rsync_port).should == "-e 'ssh -p 22'"
334
+ it 'should return the syntax for rsync to set the port' do
335
+ storage.send(:rsync_port).should == "-e 'ssh -p 22'"
255
336
  end
256
337
  end
257
338
 
258
339
  describe '#rsync_options' do
259
- it 'should return the options string for the rsync command' do
260
- rsync.send(:rsync_options).should == "-z"
340
+ it 'should return the syntax for rsync to set other options' do
341
+ storage.send(:rsync_options).should == '-z'
261
342
  end
262
343
  end
263
344