1 | /** |
---|
2 | * Licensed to the Apache Software Foundation (ASF) under one |
---|
3 | * or more contributor license agreements. See the NOTICE file |
---|
4 | * distributed with this work for additional information |
---|
5 | * regarding copyright ownership. The ASF licenses this file |
---|
6 | * to you under the Apache License, Version 2.0 (the |
---|
7 | * "License"); you may not use this file except in compliance |
---|
8 | * with the License. You may obtain a copy of the License at |
---|
9 | * |
---|
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
---|
11 | * |
---|
12 | * Unless required by applicable law or agreed to in writing, software |
---|
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
---|
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
---|
15 | * See the License for the specific language governing permissions and |
---|
16 | * limitations under the License. |
---|
17 | */ |
---|
18 | package org.apache.hadoop.fs; |
---|
19 | |
---|
20 | |
---|
21 | import junit.framework.TestCase; |
---|
22 | import java.io.File; |
---|
23 | import java.io.IOException; |
---|
24 | import java.io.DataOutputStream; |
---|
25 | import java.net.URI; |
---|
26 | |
---|
27 | import org.apache.hadoop.conf.Configuration; |
---|
28 | import org.apache.hadoop.fs.FileSystem; |
---|
29 | import org.apache.hadoop.fs.FsShell; |
---|
30 | import org.apache.hadoop.fs.Path; |
---|
31 | import org.apache.hadoop.fs.Trash; |
---|
32 | import org.apache.hadoop.fs.LocalFileSystem; |
---|
33 | |
---|
34 | /** |
---|
35 | * This class tests commands from Trash. |
---|
36 | */ |
---|
37 | public class TestTrash extends TestCase { |
---|
38 | |
---|
39 | private final static Path TEST_DIR = |
---|
40 | new Path(new File(System.getProperty("test.build.data","/tmp") |
---|
41 | ).toURI().toString().replace(' ', '+'), "testTrash"); |
---|
42 | |
---|
43 | protected static Path writeFile(FileSystem fs, Path f) throws IOException { |
---|
44 | DataOutputStream out = fs.create(f); |
---|
45 | out.writeBytes("dhruba: " + f); |
---|
46 | out.close(); |
---|
47 | assertTrue(fs.exists(f)); |
---|
48 | return f; |
---|
49 | } |
---|
50 | |
---|
51 | protected static Path mkdir(FileSystem fs, Path p) throws IOException { |
---|
52 | assertTrue(fs.mkdirs(p)); |
---|
53 | assertTrue(fs.exists(p)); |
---|
54 | assertTrue(fs.getFileStatus(p).isDir()); |
---|
55 | return p; |
---|
56 | } |
---|
57 | |
---|
58 | // check that the specified file is in Trash |
---|
59 | protected static void checkTrash(FileSystem fs, Path trashRoot, |
---|
60 | Path path) throws IOException { |
---|
61 | Path p = new Path(trashRoot+"/"+ path.toUri().getPath()); |
---|
62 | assertTrue(fs.exists(p)); |
---|
63 | } |
---|
64 | |
---|
65 | // check that the specified file is not in Trash |
---|
66 | static void checkNotInTrash(FileSystem fs, Path trashRoot, String pathname) |
---|
67 | throws IOException { |
---|
68 | Path p = new Path(trashRoot+"/"+ new Path(pathname).getName()); |
---|
69 | assertTrue(!fs.exists(p)); |
---|
70 | } |
---|
71 | |
---|
72 | protected static void trashShell(final FileSystem fs, final Path base) |
---|
73 | throws IOException { |
---|
74 | Configuration conf = new Configuration(); |
---|
75 | conf.set("fs.trash.interval", "10"); // 10 minute |
---|
76 | conf.set("fs.default.name", fs.getUri().toString()); |
---|
77 | FsShell shell = new FsShell(); |
---|
78 | shell.setConf(conf); |
---|
79 | Path trashRoot = null; |
---|
80 | |
---|
81 | // First create a new directory with mkdirs |
---|
82 | Path myPath = new Path(base, "test/mkdirs"); |
---|
83 | mkdir(fs, myPath); |
---|
84 | |
---|
85 | // Second, create a file in that directory. |
---|
86 | Path myFile = new Path(base, "test/mkdirs/myFile"); |
---|
87 | writeFile(fs, myFile); |
---|
88 | |
---|
89 | // Verify that expunge without Trash directory |
---|
90 | // won't throw Exception |
---|
91 | { |
---|
92 | String[] args = new String[1]; |
---|
93 | args[0] = "-expunge"; |
---|
94 | int val = -1; |
---|
95 | try { |
---|
96 | val = shell.run(args); |
---|
97 | } catch (Exception e) { |
---|
98 | System.err.println("Exception raised from Trash.run " + |
---|
99 | e.getLocalizedMessage()); |
---|
100 | } |
---|
101 | assertTrue(val == 0); |
---|
102 | } |
---|
103 | |
---|
104 | // Verify that we succeed in removing the file we created. |
---|
105 | // This should go into Trash. |
---|
106 | { |
---|
107 | String[] args = new String[2]; |
---|
108 | args[0] = "-rm"; |
---|
109 | args[1] = myFile.toString(); |
---|
110 | int val = -1; |
---|
111 | try { |
---|
112 | val = shell.run(args); |
---|
113 | } catch (Exception e) { |
---|
114 | System.err.println("Exception raised from Trash.run " + |
---|
115 | e.getLocalizedMessage()); |
---|
116 | } |
---|
117 | assertTrue(val == 0); |
---|
118 | |
---|
119 | trashRoot = shell.getCurrentTrashDir(); |
---|
120 | checkTrash(fs, trashRoot, myFile); |
---|
121 | } |
---|
122 | |
---|
123 | // Verify that we can recreate the file |
---|
124 | writeFile(fs, myFile); |
---|
125 | |
---|
126 | // Verify that we succeed in removing the file we re-created |
---|
127 | { |
---|
128 | String[] args = new String[2]; |
---|
129 | args[0] = "-rm"; |
---|
130 | args[1] = new Path(base, "test/mkdirs/myFile").toString(); |
---|
131 | int val = -1; |
---|
132 | try { |
---|
133 | val = shell.run(args); |
---|
134 | } catch (Exception e) { |
---|
135 | System.err.println("Exception raised from Trash.run " + |
---|
136 | e.getLocalizedMessage()); |
---|
137 | } |
---|
138 | assertTrue(val == 0); |
---|
139 | } |
---|
140 | |
---|
141 | // Verify that we can recreate the file |
---|
142 | writeFile(fs, myFile); |
---|
143 | |
---|
144 | // Verify that we succeed in removing the whole directory |
---|
145 | // along with the file inside it. |
---|
146 | { |
---|
147 | String[] args = new String[2]; |
---|
148 | args[0] = "-rmr"; |
---|
149 | args[1] = new Path(base, "test/mkdirs").toString(); |
---|
150 | int val = -1; |
---|
151 | try { |
---|
152 | val = shell.run(args); |
---|
153 | } catch (Exception e) { |
---|
154 | System.err.println("Exception raised from Trash.run " + |
---|
155 | e.getLocalizedMessage()); |
---|
156 | } |
---|
157 | assertTrue(val == 0); |
---|
158 | } |
---|
159 | |
---|
160 | // recreate directory |
---|
161 | mkdir(fs, myPath); |
---|
162 | |
---|
163 | // Verify that we succeed in removing the whole directory |
---|
164 | { |
---|
165 | String[] args = new String[2]; |
---|
166 | args[0] = "-rmr"; |
---|
167 | args[1] = new Path(base, "test/mkdirs").toString(); |
---|
168 | int val = -1; |
---|
169 | try { |
---|
170 | val = shell.run(args); |
---|
171 | } catch (Exception e) { |
---|
172 | System.err.println("Exception raised from Trash.run " + |
---|
173 | e.getLocalizedMessage()); |
---|
174 | } |
---|
175 | assertTrue(val == 0); |
---|
176 | } |
---|
177 | |
---|
178 | // Check that we can delete a file from the trash |
---|
179 | { |
---|
180 | Path toErase = new Path(trashRoot, "toErase"); |
---|
181 | int retVal = -1; |
---|
182 | writeFile(fs, toErase); |
---|
183 | try { |
---|
184 | retVal = shell.run(new String[] {"-rm", toErase.toString()}); |
---|
185 | } catch (Exception e) { |
---|
186 | System.err.println("Exception raised from Trash.run " + |
---|
187 | e.getLocalizedMessage()); |
---|
188 | } |
---|
189 | assertTrue(retVal == 0); |
---|
190 | checkNotInTrash (fs, trashRoot, toErase.toString()); |
---|
191 | checkNotInTrash (fs, trashRoot, toErase.toString()+".1"); |
---|
192 | } |
---|
193 | |
---|
194 | // simulate Trash removal |
---|
195 | { |
---|
196 | String[] args = new String[1]; |
---|
197 | args[0] = "-expunge"; |
---|
198 | int val = -1; |
---|
199 | try { |
---|
200 | val = shell.run(args); |
---|
201 | } catch (Exception e) { |
---|
202 | System.err.println("Exception raised from Trash.run " + |
---|
203 | e.getLocalizedMessage()); |
---|
204 | } |
---|
205 | assertTrue(val == 0); |
---|
206 | } |
---|
207 | |
---|
208 | // verify that after expunging the Trash, it really goes away |
---|
209 | checkNotInTrash(fs, trashRoot, new Path(base, "test/mkdirs/myFile").toString()); |
---|
210 | |
---|
211 | // recreate directory and file |
---|
212 | mkdir(fs, myPath); |
---|
213 | writeFile(fs, myFile); |
---|
214 | |
---|
215 | // remove file first, then remove directory |
---|
216 | { |
---|
217 | String[] args = new String[2]; |
---|
218 | args[0] = "-rm"; |
---|
219 | args[1] = myFile.toString(); |
---|
220 | int val = -1; |
---|
221 | try { |
---|
222 | val = shell.run(args); |
---|
223 | } catch (Exception e) { |
---|
224 | System.err.println("Exception raised from Trash.run " + |
---|
225 | e.getLocalizedMessage()); |
---|
226 | } |
---|
227 | assertTrue(val == 0); |
---|
228 | checkTrash(fs, trashRoot, myFile); |
---|
229 | |
---|
230 | args = new String[2]; |
---|
231 | args[0] = "-rmr"; |
---|
232 | args[1] = myPath.toString(); |
---|
233 | val = -1; |
---|
234 | try { |
---|
235 | val = shell.run(args); |
---|
236 | } catch (Exception e) { |
---|
237 | System.err.println("Exception raised from Trash.run " + |
---|
238 | e.getLocalizedMessage()); |
---|
239 | } |
---|
240 | assertTrue(val == 0); |
---|
241 | checkTrash(fs, trashRoot, myPath); |
---|
242 | } |
---|
243 | |
---|
244 | // attempt to remove parent of trash |
---|
245 | { |
---|
246 | String[] args = new String[2]; |
---|
247 | args[0] = "-rmr"; |
---|
248 | args[1] = trashRoot.getParent().getParent().toString(); |
---|
249 | int val = -1; |
---|
250 | try { |
---|
251 | val = shell.run(args); |
---|
252 | } catch (Exception e) { |
---|
253 | System.err.println("Exception raised from Trash.run " + |
---|
254 | e.getLocalizedMessage()); |
---|
255 | } |
---|
256 | assertTrue(val == -1); |
---|
257 | assertTrue(fs.exists(trashRoot)); |
---|
258 | } |
---|
259 | |
---|
260 | // Verify skip trash option really works |
---|
261 | |
---|
262 | // recreate directory and file |
---|
263 | mkdir(fs, myPath); |
---|
264 | writeFile(fs, myFile); |
---|
265 | |
---|
266 | // Verify that skip trash option really skips the trash for files (rm) |
---|
267 | { |
---|
268 | String[] args = new String[3]; |
---|
269 | args[0] = "-rm"; |
---|
270 | args[1] = "-skipTrash"; |
---|
271 | args[2] = myFile.toString(); |
---|
272 | int val = -1; |
---|
273 | try { |
---|
274 | // Clear out trash |
---|
275 | assertEquals(0, shell.run(new String [] { "-expunge" } )); |
---|
276 | |
---|
277 | val = shell.run(args); |
---|
278 | |
---|
279 | }catch (Exception e) { |
---|
280 | System.err.println("Exception raised from Trash.run " + |
---|
281 | e.getLocalizedMessage()); |
---|
282 | } |
---|
283 | |
---|
284 | assertFalse(fs.exists(trashRoot)); // No new Current should be created |
---|
285 | assertFalse(fs.exists(myFile)); |
---|
286 | assertTrue(val == 0); |
---|
287 | } |
---|
288 | |
---|
289 | // recreate directory and file |
---|
290 | mkdir(fs, myPath); |
---|
291 | writeFile(fs, myFile); |
---|
292 | |
---|
293 | // Verify that skip trash option really skips the trash for rmr |
---|
294 | { |
---|
295 | String[] args = new String[3]; |
---|
296 | args[0] = "-rmr"; |
---|
297 | args[1] = "-skipTrash"; |
---|
298 | args[2] = myPath.toString(); |
---|
299 | |
---|
300 | int val = -1; |
---|
301 | try { |
---|
302 | // Clear out trash |
---|
303 | assertEquals(0, shell.run(new String [] { "-expunge" } )); |
---|
304 | |
---|
305 | val = shell.run(args); |
---|
306 | |
---|
307 | }catch (Exception e) { |
---|
308 | System.err.println("Exception raised from Trash.run " + |
---|
309 | e.getLocalizedMessage()); |
---|
310 | } |
---|
311 | |
---|
312 | assertFalse(fs.exists(trashRoot)); // No new Current should be created |
---|
313 | assertFalse(fs.exists(myPath)); |
---|
314 | assertFalse(fs.exists(myFile)); |
---|
315 | assertTrue(val == 0); |
---|
316 | } |
---|
317 | } |
---|
318 | |
---|
319 | public static void trashNonDefaultFS(Configuration conf) throws IOException { |
---|
320 | conf.set("fs.trash.interval", "10"); // 10 minute |
---|
321 | // attempt non-default FileSystem trash |
---|
322 | { |
---|
323 | final FileSystem lfs = FileSystem.getLocal(conf); |
---|
324 | Path p = TEST_DIR; |
---|
325 | Path f = new Path(p, "foo/bar"); |
---|
326 | if (lfs.exists(p)) { |
---|
327 | lfs.delete(p, true); |
---|
328 | } |
---|
329 | try { |
---|
330 | f = writeFile(lfs, f); |
---|
331 | |
---|
332 | FileSystem.closeAll(); |
---|
333 | FileSystem localFs = FileSystem.get(URI.create("file:///"), conf); |
---|
334 | Trash lTrash = new Trash(localFs, conf); |
---|
335 | lTrash.moveToTrash(f.getParent()); |
---|
336 | checkTrash(localFs, lTrash.getCurrentTrashDir(), f); |
---|
337 | } finally { |
---|
338 | if (lfs.exists(p)) { |
---|
339 | lfs.delete(p, true); |
---|
340 | } |
---|
341 | } |
---|
342 | } |
---|
343 | } |
---|
344 | |
---|
345 | public void testTrash() throws IOException { |
---|
346 | Configuration conf = new Configuration(); |
---|
347 | conf.setClass("fs.file.impl", TestLFS.class, FileSystem.class); |
---|
348 | trashShell(FileSystem.getLocal(conf), TEST_DIR); |
---|
349 | } |
---|
350 | |
---|
351 | public void testNonDefaultFS() throws IOException { |
---|
352 | Configuration conf = new Configuration(); |
---|
353 | conf.setClass("fs.file.impl", TestLFS.class, FileSystem.class); |
---|
354 | conf.set("fs.default.name", "invalid://host/bar/foo"); |
---|
355 | trashNonDefaultFS(conf); |
---|
356 | } |
---|
357 | |
---|
358 | static class TestLFS extends LocalFileSystem { |
---|
359 | Path home; |
---|
360 | TestLFS() { |
---|
361 | this(TEST_DIR); |
---|
362 | } |
---|
363 | TestLFS(Path home) { |
---|
364 | super(); |
---|
365 | this.home = home; |
---|
366 | } |
---|
367 | public Path getHomeDirectory() { |
---|
368 | return home; |
---|
369 | } |
---|
370 | } |
---|
371 | } |
---|