1 # Coquelicot: "one-click" file sharing with a focus on users' privacy.
2 # Copyright © 2010-2012 potager.org <jardiniers@potager.org>
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as
6 # published by the Free Software Foundation, either version 3 of the
7 # License, or (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 it 'should record the given path' do
24 depot = Depot.new('/test')
25 depot.path.should == '/test'
30 Dir.mktmpdir('coquelicot') do |tmpdir|
35 let(:depot) { Depot.new(@tmpdir) }
36 let(:pass) { 'secret'}
41 depot.add_file(pass, { 'Expire-at' => Time.now + expire }) do
42 buf, content = content, nil
47 describe '#add_file' do
48 it 'should generate a random file name' do
49 depot.should_receive(:gen_random_file_name).
50 and_return('file', 'link')
53 context 'when it generates a name that is already in use' do
54 it 'should find another name' do
55 FileUtils.touch File.expand_path('file', @tmpdir)
56 depot.should_receive(:gen_random_file_name).
57 and_return('file', 'another', 'link')
61 context 'when it generates the same name with another client' do
62 it 'should find another name' do
63 depot.should_receive(:gen_random_file_name).
64 and_return('file', 'another', 'link')
66 StoredFile.should_receive(:create).ordered.
67 with(/\/file$/, pass, instance_of(Hash)).
68 and_raise(Errno::EEXIST.new(File.expand_path('file', @tmpdir)))
69 StoredFile.should_receive(:create).ordered.
70 with(/\/another$/, pass, instance_of(Hash))
74 context 'when the given block raises an error' do
75 it 'should not add a file to the depot' do
78 depot.add_file(pass, {}) { raise StandardError.new }
82 }.to_not change { depot.size }
84 it 'should cleanup any created files' do
87 depot.add_file(pass, {}) { raise StandardError.new }
91 }.to_not change { Dir.entries(@tmpdir) }
94 context 'when given a fine content provider block' do
95 it 'should add a new file in the depot' do
98 }.to change { depot.size }.by(1)
100 it 'should return a randomly generated link name' do
101 depot.should_receive(:gen_random_file_name).
102 and_return('file', 'link')
104 link.should == 'link'
106 it 'should add the new link to the ".links" file' do
107 depot.should_receive(:gen_random_file_name).
108 and_return('file', 'link')
110 File.read(File.expand_path('.links', @tmpdir)).should =~ /^link\s+file$/
112 context 'when it generates a link name that is already taken' do
114 depot.stub(:gen_random_file_name).
115 and_return('file', 'link', 'another', 'link', 'another_link')
116 # add 'link' pointing to 'file'
118 # now it should add 'another_link' -> 'another'
121 it 'should not overwrite the existing link' do
122 depot.size.should == 2
124 it 'should find another name' do
125 @link.should == 'another_link'
131 describe '#get_file' do
132 context 'when there is no link with the given name' do
133 it 'should return nil' do
134 depot.get_file('link').should be_nil
137 context 'when there is a link with the given name' do
141 it 'should return a StoredFile' do
142 depot.get_file(@link).should be_a(StoredFile)
144 it 'should return the right file' do
145 stored_file = depot.get_file(@link, pass)
147 stored_file.each { |data| buf << data }
148 buf.should == 'Content'
151 context 'when there is a link with no matching file' do
153 depot.should_receive(:gen_random_file_name).
154 and_return('file', 'link')
156 File.unlink File.expand_path('file', @tmpdir)
158 it 'should return nil' do
159 depot.get_file(@link).should be_nil
164 describe '#file_exists?' do
165 subject { depot.file_exists?('link') }
166 context 'when there is no link with the given name' do
167 it { should_not be_true }
169 context 'when there is a link with the given name' do
171 depot.should_receive(:gen_random_file_name).
172 and_return('file', 'link')
175 it { should be_true }
177 context 'when there is a link with no matching file' do
179 depot.should_receive(:gen_random_file_name).
180 and_return('file', 'link')
182 File.unlink File.expand_path('file', @tmpdir)
184 it { should_not be_true }
189 context 'when there is no files' do
190 it 'should do nothing' do
191 expect { depot.gc! }.to_not change { Dir.entries(@tmpdir) }
194 context 'when there is a file' do
196 depot.should_receive(:gen_random_file_name).
197 and_return('file', 'link')
200 context 'before it is expired' do
201 subject { depot.gc! }
202 it 'should not remove links' do
203 expect { subject }.to_not change { depot.size }
205 it 'should not remove files' do
206 expect { subject }.to_not change { Dir.entries(@tmpdir) }
208 it 'should not empty the file' do
211 }.to_not change { File.stat(File.expand_path('file', @tmpdir)).size }
214 context 'after it is expired' do
215 subject { Timecop.travel(Date.today + 2) { depot.gc! } }
216 it 'should not remove links' do
217 expect { subject }.to_not change { depot.size }
219 it 'should not remove files' do
221 to_not change { Dir.entries(@tmpdir) }
223 it 'should empty the file' do
225 to change { File.stat(File.expand_path('file', @tmpdir)).size }.to(0)
228 context 'after the gone period' do
229 let(:now) { Time.now + Coquelicot.settings.gone_period * 61 }
230 subject { Timecop.travel(now) { depot.gc! } }
231 it 'should remove links' do
232 expect { subject }.to change { depot.size }.from(1).to(0)
234 it 'should remove files' do
236 Dir.glob("#{@tmpdir}/file*").should be_empty
240 context 'when there is a link but no associated file' do
242 depot.should_receive(:gen_random_file_name).
243 and_return('file', 'link')
245 File.unlink File.expand_path('file', @tmpdir)
247 it 'should remove the link' do
248 expect { depot.gc! }.to change { depot.size }.from(1).to(0)
254 subject { depot.size }
255 context 'when there is no files' do
258 context 'when there is a file' do
259 before(:each) { add_file }
262 context 'when there is two files' do
263 before(:each) { add_file ; add_file }