initial code repo
[stor4nfv.git] / src / ceph / src / java / test / com / ceph / fs / CephMountTest.java
1 /*
2  * Permission is hereby granted, free of charge, to any person obtaining a
3  * copy of this software and associated documentation files (the "Software"),
4  * to deal in the Software without restriction, including without limitation
5  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
6  * and/or sell copies of the Software, and to permit persons to whom the
7  * Software is furnished to do so, subject to the following conditions:
8  *
9  * The above copyright notice and this permission notice shall be included in
10  * all copies or substantial portions of the Software.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18  * DEALINGS IN THE SOFTWARE.
19  */
20
21 package com.ceph.fs;
22
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.net.InetAddress;
26 import java.util.UUID;
27 import org.junit.*;
28 import static org.junit.Assert.*;
29
30 import com.ceph.crush.Bucket;
31
32 /*
33  * Coverage
34  *  - Everything is covered in at least success cases.
35  *  - l[set,get,remove]xattr are not working
36  */
37
38 public class CephMountTest {
39
40   private static CephMount mount;
41   private static String basedir = null;
42
43   @BeforeClass
44   public static void setup() throws Exception {
45     mount = new CephMount("admin");
46
47     String conf_file = System.getProperty("CEPH_CONF_FILE");
48     if (conf_file != null)
49       mount.conf_read_file(conf_file);
50     mount.conf_set("client_permissions", "0");
51
52     mount.mount(null);
53
54     basedir = "/libcephfs_junit_" + UUID.randomUUID();
55     mount.mkdir(basedir, 0777);
56   }
57
58   @AfterClass
59   public static void destroy() throws Exception {
60     String[] list = mount.listdir(basedir);
61     for (String l : list)
62       System.out.println(l);
63     mount.rmdir(basedir);
64     mount.unmount();
65   }
66
67   /*
68    * Helper function to construct a unique path.
69    */
70   public String makePath() {
71     String path = basedir + "/" + UUID.randomUUID();
72     return path;
73   }
74
75   /*
76    * Helper to learn the data pool name, by reading it
77    * from the '/' dir inode.
78    */
79   public String getRootPoolName() throws Exception
80   {
81     int fd = mount.open("/", CephMount.O_DIRECTORY, 0600);
82     String pool = mount.get_file_pool_name(fd);
83     mount.close(fd);
84     return pool;
85   }
86
87   /*
88    * Helper function to create a file with the given path and size. The file
89    * is filled with size bytes and the file descriptor is returned.
90    */
91   public int createFile(String path, int size) throws Exception {
92     int fd = mount.open(path, CephMount.O_RDWR|CephMount.O_CREAT, 0600);
93     byte[] buf = new byte[4096];
94     int left = size;
95     while (left > 0) {
96       size = Math.min(buf.length, left);
97       long ret = mount.write(fd, buf, size, -1);
98       left -= ret;
99     }
100     return fd;
101   }
102
103   /*
104    * Helper function to create a unique file and fill it with size bytes. The
105    * file descriptor is returned.
106    */
107   public int createFile(int size) throws Exception {
108     return createFile(makePath(), size);
109   }
110
111   @Test(expected=FileNotFoundException.class)
112   public void test_mount_dne() throws Exception {
113     CephMount mount2 = new CephMount("admin");
114     String conf_file = System.getProperty("CEPH_CONF_FILE");
115     if (conf_file != null)
116       mount2.conf_read_file(conf_file);
117     mount2.mount("/wlfkjwlekfjwlejfwe");
118     mount2.unmount();
119   }
120
121   /*
122    * Test loading of conf file that doesn't exist.
123    *
124    * FIXME:
125    * Ceph returns -ENOSYS rather than -ENOENT. Correct?
126    */
127   //@Test(expected=FileNotFoundException.class)
128   @Test
129   public void test_conf_read_file_dne() throws Exception {
130     //mount.conf_read_file("/this_file_does_not_exist");
131   }
132
133   /*
134    * Test loading of conf file that isn't valid
135    *
136    * FIXME: implement
137    */
138   @Test
139   public void test_conf_read_file_invalid() throws Exception {
140   }
141
142   @Test(expected=NullPointerException.class)
143   public void test_conf_read_file_null() throws Exception {
144     mount.conf_read_file(null);
145   }
146
147   /*
148    * conf_set/conf_get
149    */
150
151   @Test(expected=NullPointerException.class)
152   public void test_conf_set_null_opt() throws Exception {
153     mount.conf_set(null, "value");
154   }
155
156   @Test(expected=NullPointerException.class)
157   public void test_conf_set_null_val() throws Exception {
158     mount.conf_set("option", null);
159   }
160
161   @Test(expected=NullPointerException.class)
162   public void test_conf_get_null_opt() throws Exception {
163     mount.conf_get(null);
164   }
165
166   @Test
167   public void test_conf() throws Exception {
168     String opt = "log to stderr";
169     String val1, val2, val3;
170
171     /* get the current value */
172     val1 = mount.conf_get(opt);
173
174     /*
175      * flip the value. this may make some debug information be dumped to the
176      * console when the value becomes true. TODO: find a better config option
177      * to toggle.
178      */
179     if (val1.compareTo("true") == 0)
180       val2 = "false";
181     else
182       val2 = "true";
183     mount.conf_set(opt, val2);
184
185     /* verify the change */
186     val3 = mount.conf_get(opt);
187     assertTrue(val3.compareTo(val2) == 0);
188
189     /* reset to original value */
190     mount.conf_set(opt, val1);
191     val3 = mount.conf_get(opt);
192     assertTrue(val3.compareTo(val1) == 0);
193   }
194
195   /*
196    * statfs
197    */
198
199   @Test
200   public void test_statfs() throws Exception {
201     CephStatVFS st1 = new CephStatVFS();
202     mount.statfs("/", st1);
203
204     /*
205      * FIXME: a better test here is to see if changes to the file system are
206      * reflected through statfs (e.g. increasing number of files). However, it
207      * appears that the updates aren't immediately visible.
208      */
209     assertTrue(st1.bsize > 0);
210     assertTrue(st1.frsize > 0);
211     assertTrue(st1.blocks > 0);
212     assertTrue(st1.bavail > 0);
213     assertTrue(st1.namemax > 0);
214   }
215
216   /*
217    * getcwd/chdir
218    */
219
220   @Test
221   public void test_getcwd() throws Exception {
222     mount.chdir(basedir);
223     String cwd = mount.getcwd();
224     assertTrue(cwd.compareTo(basedir) == 0);
225
226     /* Make sure to reset cwd to root */
227     mount.chdir("/");
228     cwd = mount.getcwd();
229     assertTrue(cwd.compareTo("/") == 0);
230   }
231
232   @Test(expected=NullPointerException.class)
233   public void test_chdir_null() throws Exception {
234     mount.chdir(null);
235   }
236
237   @Test(expected=FileNotFoundException.class)
238   public void test_chdir_dne() throws Exception {
239     mount.chdir("/this/path/does/not/exist/");
240   }
241
242   /*
243    * FIXME: this test should throw an error (but does not)?
244    */
245   //@Test(expected=IOException.class)
246   @Test
247   public void test_chdir_not_dir() throws Exception {
248     String path = makePath();
249     int fd = createFile(path, 1);
250     mount.close(fd);
251     //mount.chdir(path); shouldn't be able to do this?
252     mount.unlink(path);
253
254     /*
255      * Switch back. Other tests seem to be sensitive to the current directory
256      * being something other than "/". This shouldn't happen once this tests
257      * passes and the call to chdir fails anyway.
258      */
259     mount.chdir("/");
260   }
261
262   /*
263    * listdir
264    */
265
266   @Test(expected=NullPointerException.class)
267   public void test_listdir_null() throws Exception {
268     mount.listdir(null);
269   }
270
271   @Test(expected=FileNotFoundException.class)
272   public void test_listdir_dne() throws Exception {
273     mount.listdir("/this/path/does/not/exist/");
274   }
275
276   @Test(expected=IOException.class)
277   public void test_listdir_not_dir() throws Exception {
278     String path = makePath();
279     int fd = createFile(path, 1);
280     mount.close(fd);
281     try {
282       mount.listdir(path);
283     } finally {
284       mount.unlink(path);
285     }
286   }
287
288   @Test
289   public void test_listdir() throws Exception {
290     String dir = makePath();
291     mount.mkdir(dir, 0777);
292     /* test that new directory is empty */
293     String[] list = mount.listdir(dir);
294     assertTrue(list.length == 0);
295     /* test that new directories are seen */
296     for (int i = 0; i < 3; i++)
297       mount.mkdir(dir + "/" + i, 777);
298     list = mount.listdir(dir);
299     assertTrue(list.length == 3);
300     /* test that more new directories are seen */
301     for (int i = 0; i < 30; i++)
302       mount.mkdir(dir + "/x" + i, 777);
303     list = mount.listdir(dir);
304     assertTrue(list.length == 33);
305
306     /* remove */
307     for (int i = 0; i < 30; i++)
308       mount.rmdir(dir + "/x" + i);
309     for (int i = 0; i < 3; i++)
310       mount.rmdir(dir + "/" + i);
311     mount.rmdir(dir);
312   }
313
314   /*
315    * Missing
316    *
317    * ceph_link
318    * ceph_unlink
319    */
320
321   /*
322    * rename
323    */
324
325   @Test(expected=NullPointerException.class)
326   public void test_rename_null_from() throws Exception {
327     mount.rename(null, "to");
328   }
329
330   @Test(expected=NullPointerException.class)
331   public void test_rename_null_to() throws Exception {
332     mount.rename("from", null);
333   }
334
335   @Test(expected=FileNotFoundException.class)
336   public void test_rename_dne() throws Exception {
337     mount.rename("/this/doesnt/exist", "/this/neither");
338   }
339
340   @Test
341   public void test_rename() throws Exception {
342     /* create a file */
343     String path = makePath();
344     int fd = createFile(path, 1);
345     mount.close(fd);
346
347     /* move it to a new name */
348     String newpath = makePath();
349     mount.rename(path, newpath);
350
351     /* verfiy the sizes are the same */
352     CephStat st = new CephStat();
353     mount.lstat(newpath, st);
354     assertTrue(st.size == 1);
355
356     /* remove the file */
357     mount.unlink(newpath);
358   }
359
360   /*
361    * mkdir/mkdirs/rmdir
362    */
363
364   @Test(expected=IOException.class)
365   public void test_mkdir_exists() throws Exception {
366     String path = makePath();
367     mount.mkdir(path, 0777);
368     try {
369       mount.mkdir(path, 0777);
370     } finally {
371       mount.rmdir(path);
372     }
373   }
374
375   @Test(expected=IOException.class)
376   public void test_mkdirs_exists() throws Exception {
377     String path = makePath();
378     mount.mkdirs(path, 0777);
379     try {
380       mount.mkdirs(path, 0777);
381     } finally {
382       mount.rmdir(path);
383     }
384   }
385
386   @Test
387   public void test_mkdir() throws Exception {
388     String path = makePath();
389     mount.mkdir(path, 0777);
390     CephStat st = new CephStat();
391     mount.lstat(path, st);
392     assertTrue(st.isDir());
393     mount.rmdir(path);
394   }
395
396   @Test
397   public void test_mkdirs() throws Exception {
398     String path = makePath();
399     mount.mkdirs(path + "/x/y", 0777);
400
401     CephStat st = new CephStat();
402     mount.lstat(path, st);
403     assertTrue(st.isDir());
404
405     mount.lstat(path + "/x", st);
406     assertTrue(st.isDir());
407
408     mount.lstat(path + "/x/y", st);
409     assertTrue(st.isDir());
410
411     mount.rmdir(path + "/x/y");
412     mount.rmdir(path + "/x");
413     mount.rmdir(path);
414   }
415
416   @Test(expected=FileNotFoundException.class)
417   public void test_rmdir() throws Exception {
418     /* make a new directory */
419     String path = makePath();
420     mount.mkdir(path, 0777);
421     CephStat st = new CephStat();
422     mount.lstat(path, st);
423     assertTrue(st.isDir());
424     /* remove it */
425     mount.rmdir(path);
426     /* should not exist now */
427     mount.lstat(path, st);
428   }
429
430   /*
431    * readlink
432    * symlink
433    */
434   @Test
435   public void test_symlink() throws Exception {
436     String oldpath = makePath();
437     String newpath = makePath();
438
439     mount.symlink(oldpath, newpath);
440     CephStat stat = new CephStat();
441     mount.lstat(newpath, stat);
442     assertTrue(stat.isSymlink());
443
444     String symlink = mount.readlink(newpath);
445     assertTrue(symlink.compareTo(oldpath) == 0);
446
447     mount.unlink(newpath);
448   }
449
450   /*
451    * lstat
452    */
453
454   @Test(expected=NullPointerException.class)
455   public void test_lstat_null_path() throws Exception {
456     mount.lstat(null, new CephStat());
457   }
458
459   @Test(expected=NullPointerException.class)
460   public void test_lstat_null_stat() throws Exception {
461     mount.lstat("/path", null);
462   }
463
464   @Test(expected=FileNotFoundException.class)
465   public void test_lstat_null_dne() throws Exception {
466     mount.lstat("/path/does/not/exist", new CephStat());
467   }
468
469   /*
470    * test_stat covers lstat and fstat and stat.
471    *
472    * TODO: create test that for lstat vs stat with symlink follow/nofollow.
473    */
474
475   @Test
476   public void test_stat() throws Exception {
477     /* create a new file */
478     String path = makePath();
479     int size = 12345;
480     int fd = createFile(path, size);
481     mount.close(fd);
482
483     /* test some basic info about the new file */
484     CephStat orig_st = new CephStat();
485     mount.lstat(path, orig_st);
486     assertTrue(orig_st.size == size);
487     assertTrue(orig_st.blksize > 0);
488     assertTrue(orig_st.blocks > 0);
489
490     /* now try stat */
491     CephStat stat_st = new CephStat();
492     mount.stat(path, stat_st);
493
494     /* now try fstat */
495     CephStat other_st = new CephStat();
496     fd = mount.open(path, CephMount.O_RDWR, 0);
497     mount.fstat(fd, other_st);
498     mount.close(fd);
499
500     mount.unlink(path);
501
502     /* compare to fstat results */
503     assertTrue(orig_st.mode == other_st.mode);
504     assertTrue(orig_st.uid == other_st.uid);
505     assertTrue(orig_st.gid == other_st.gid);
506     assertTrue(orig_st.size == other_st.size);
507     assertTrue(orig_st.blksize == other_st.blksize);
508     assertTrue(orig_st.blocks == other_st.blocks);
509
510     /* compare to stat results */
511     assertTrue(orig_st.mode == stat_st.mode);
512     assertTrue(orig_st.uid == stat_st.uid);
513     assertTrue(orig_st.gid == stat_st.gid);
514     assertTrue(orig_st.size == stat_st.size);
515     assertTrue(orig_st.blksize == stat_st.blksize);
516     assertTrue(orig_st.blocks == stat_st.blocks);
517   }
518
519   /*
520    * stat
521    */
522
523   @Test(expected=NullPointerException.class)
524   public void test_stat_null_path() throws Exception {
525     mount.stat(null, new CephStat());
526   }
527
528   @Test(expected=NullPointerException.class)
529   public void test_stat_null_stat() throws Exception {
530     mount.stat("/path", null);
531   }
532
533   @Test(expected=FileNotFoundException.class)
534   public void test_stat_null_dne() throws Exception {
535     mount.stat("/path/does/not/exist", new CephStat());
536   }
537
538   @Test(expected=CephNotDirectoryException.class)
539   public void test_enotdir() throws Exception {
540     String path = makePath();
541     int fd = createFile(path, 1);
542     mount.close(fd);
543
544     try {
545       CephStat stat = new CephStat();
546       mount.lstat(path + "/blah", stat);
547     } finally {
548       mount.unlink(path);
549     }
550   }
551
552   /*
553    * setattr
554    */
555
556   @Test(expected=NullPointerException.class)
557   public void test_setattr_null_path() throws Exception {
558     mount.setattr(null, new CephStat(), 0);
559   }
560
561   @Test(expected=NullPointerException.class)
562   public void test_setattr_null_stat() throws Exception {
563     mount.setattr("/path", null, 0);
564   }
565
566   @Test(expected=FileNotFoundException.class)
567   public void test_setattr_dne() throws Exception {
568     mount.setattr("/path/does/not/exist", new CephStat(), 0);
569   }
570
571   @Test
572   public void test_setattr() throws Exception {
573     /* create a file */
574     String path = makePath();
575     int fd = createFile(path, 1);
576     mount.close(fd);
577
578     CephStat st1 = new CephStat();
579     mount.lstat(path, st1);
580
581     st1.uid += 1;
582     st1.gid += 1;
583     mount.setattr(path, st1, mount.SETATTR_UID|mount.SETATTR_GID);
584
585     CephStat st2 = new CephStat();
586     mount.lstat(path, st2);
587
588     assertTrue(st2.uid == st1.uid);
589     assertTrue(st2.gid == st1.gid);
590
591     /* remove the file */
592     mount.unlink(path);
593   }
594
595   /*
596    * chmod
597    */
598
599   @Test(expected=NullPointerException.class)
600   public void test_chmod_null_path() throws Exception {
601     mount.chmod(null, 0);
602   }
603
604   @Test(expected=FileNotFoundException.class)
605   public void test_chmod_dne() throws Exception {
606     mount.chmod("/path/does/not/exist", 0);
607   }
608
609   @Test
610   public void test_chmod() throws Exception {
611     /* create a file */
612     String path = makePath();
613     int fd = createFile(path, 1);
614     mount.close(fd);
615
616     CephStat st = new CephStat();
617     mount.lstat(path, st);
618
619     /* flip a bit */
620     int mode = st.mode;
621     if ((mode & 1) != 0)
622       mode -= 1;
623     else
624       mode += 1;
625
626     mount.chmod(path, mode);
627     CephStat st2 = new CephStat();
628     mount.lstat(path, st2);
629     assertTrue(st2.mode == mode);
630
631     mount.unlink(path);
632   }
633
634   /*
635    * fchmod
636    */
637
638   @Test
639   public void test_fchmod() throws Exception {
640     /* create a file */
641     String path = makePath();
642     int fd = createFile(path, 1);
643
644     CephStat st = new CephStat();
645     mount.lstat(path, st);
646
647     /* flip a bit */
648     int mode = st.mode;
649     if ((mode & 1) != 0)
650       mode -= 1;
651     else
652       mode += 1;
653
654     mount.fchmod(fd, mode);
655     mount.close(fd);
656
657     CephStat st2 = new CephStat();
658     mount.lstat(path, st2);
659     assertTrue(st2.mode == mode);
660
661     mount.unlink(path);
662   }
663
664   /*
665    * truncate
666    */
667
668   @Test(expected=FileNotFoundException.class)
669   public void test_truncate_dne() throws Exception {
670     mount.truncate("/path/does/not/exist", 0);
671   }
672
673   @Test(expected=NullPointerException.class)
674   public void test_truncate_null_path() throws Exception {
675     mount.truncate(null, 0);
676   }
677
678   @Test
679   public void test_truncate() throws Exception {
680     // make file
681     String path = makePath();
682     int orig_size = 1398331;
683     int fd = createFile(path, orig_size);
684     mount.close(fd);
685
686     // check file size
687     CephStat st = new CephStat();
688     mount.lstat(path, st);
689     assertTrue(st.size == orig_size);
690
691     // truncate and check
692     int crop_size = 333333;
693     mount.truncate(path, crop_size);
694     mount.lstat(path, st);
695     assertTrue(st.size == crop_size);
696
697     // check after re-open
698     fd = mount.open(path, CephMount.O_RDWR, 0);
699     mount.fstat(fd, st);
700     assertTrue(st.size == crop_size);
701     mount.close(fd);
702
703     mount.unlink(path);
704   }
705
706   @Test
707   public void test_open_layout() throws Exception {
708     String path = makePath();
709     int fd = mount.open(path, CephMount.O_WRONLY|CephMount.O_CREAT, 0,
710         (1<<20), 1, (1<<20), null);
711     mount.close(fd);
712     mount.unlink(path);
713   }
714
715   /*
716    * open/close
717    */
718
719   @Test(expected=FileNotFoundException.class)
720   public void test_open_dne() throws Exception {
721     mount.open("/path/doesnt/exist", 0, 0);
722   }
723
724   /*
725    * lseek
726    */
727
728   @Test
729   public void test_lseek() throws Exception {
730     /* create a new file */
731     String path = makePath();
732     int size = 12345;
733     int fd = createFile(path, size);
734     mount.close(fd);
735
736     /* open and check size */
737     fd = mount.open(path, CephMount.O_RDWR, 0);
738     long end = mount.lseek(fd, 0, CephMount.SEEK_END);
739     mount.close(fd);
740
741     mount.unlink(path);
742
743     assertTrue(size == (int)end);
744   }
745
746   /*
747    * read/write
748    */
749
750   @Test
751   public void test_read() throws Exception {
752     String path = makePath();
753     int fd = createFile(path, 1500);
754     byte[] buf = new byte[1500];
755     long ret = mount.read(fd, buf, 1500, 0);
756     assertTrue(ret == 1500);
757     mount.unlink(path);
758   }
759
760   /*
761    * ftruncate
762    */
763
764   @Test
765   public void test_ftruncate() throws Exception {
766     // make file
767     String path = makePath();
768     int orig_size = 1398331;
769     int fd = createFile(path, orig_size);
770
771     // check file size
772     CephStat st = new CephStat();
773     mount.fstat(fd, st);
774     assertTrue(st.size == orig_size);
775
776     // truncate and check
777     int crop_size = 333333;
778     mount.ftruncate(fd, crop_size);
779     mount.fstat(fd, st);
780     if (st.size != crop_size) {
781       System.err.println("ftruncate error: st.size=" + st.size + " crop_size=" + crop_size);
782       assertTrue(false);
783     }
784     assertTrue(st.size == crop_size);
785     mount.close(fd);
786
787     // check after re-open
788     fd = mount.open(path, CephMount.O_RDWR, 0);
789     mount.fstat(fd, st);
790     assertTrue(st.size == crop_size);
791     mount.close(fd);
792
793     mount.unlink(path);
794   }
795
796   /*
797    * fsync
798    */
799
800   @Test
801   public void test_fsync() throws Exception {
802     String path = makePath();
803     int fd = createFile(path, 123);
804     mount.fsync(fd, false);
805     mount.fsync(fd, true);
806     mount.close(fd);
807     mount.unlink(path);
808   }
809
810   /*
811    * flock
812    */
813
814   @Test
815   public void test_flock() throws Exception {
816     String path = makePath();
817     int fd = createFile(path, 123);
818     mount.flock(fd, CephMount.LOCK_SH | CephMount.LOCK_NB, 42);
819     mount.flock(fd, CephMount.LOCK_SH | CephMount.LOCK_NB, 43);
820     mount.flock(fd, CephMount.LOCK_UN, 42);
821     mount.flock(fd, CephMount.LOCK_UN, 43);
822     mount.flock(fd, CephMount.LOCK_EX | CephMount.LOCK_NB, 42);
823     try {
824       mount.flock(fd, CephMount.LOCK_SH | CephMount.LOCK_NB, 43);
825       assertTrue(false);
826     } catch(IOException io) {}
827     try {
828       mount.flock(fd, CephMount.LOCK_EX | CephMount.LOCK_NB, 43);
829       assertTrue(false);
830     } catch(IOException io) {}
831     mount.flock(fd, CephMount.LOCK_SH, 42);  // downgrade
832     mount.flock(fd, CephMount.LOCK_SH, 43);
833     mount.flock(fd, CephMount.LOCK_UN, 42);
834     mount.flock(fd, CephMount.LOCK_UN, 43);
835     mount.close(fd);
836     mount.unlink(path);
837   }
838
839   /*
840    * fstat
841    *
842    * success case is handled in test_stat along with lstat.
843    */
844
845   /*
846    * sync_fs
847    */
848
849   @Test
850   public void test_sync_fs() throws Exception {
851     mount.sync_fs();
852   }
853
854   /*
855    * get/set/list/remove xattr
856    */
857
858   @Test
859   public void test_xattr() throws Exception {
860     /* make file */
861     String path = makePath();
862     int fd = createFile(path, 123);
863     mount.close(fd);
864
865     /* make xattrs */
866     String val1 = "This is a new xattr";
867     String val2 = "This is a different xattr";
868     byte[] buf1 = val1.getBytes();
869     byte[] buf2 = val2.getBytes();
870     mount.setxattr(path, "user.attr1", buf1, buf1.length, mount.XATTR_CREATE);
871     mount.setxattr(path, "user.attr2", buf2, buf2.length, mount.XATTR_CREATE);
872
873     /* list xattrs */
874     String[] xattrs = mount.listxattr(path);
875     assertTrue(xattrs.length == 2);
876     int found = 0;
877     for (String xattr : xattrs) {
878       if (xattr.compareTo("user.attr1") == 0) {
879         found++;
880         continue;
881       }
882       if (xattr.compareTo("user.attr2") == 0) {
883         found++;
884         continue;
885       }
886       System.out.println("found unwanted xattr: " + xattr);
887     }
888     assertTrue(found == 2);
889
890     /* get first xattr by looking up length */
891     long attr1_len = mount.getxattr(path, "user.attr1", null);
892     byte[] out = new byte[(int)attr1_len];
893     mount.getxattr(path, "user.attr1", out);
894     String outStr = new String(out);
895     assertTrue(outStr.compareTo(val1) == 0);
896
897     /* get second xattr assuming original length */
898     out = new byte[buf2.length];
899     mount.getxattr(path, "user.attr2", out);
900     outStr = new String(out);
901     assertTrue(outStr.compareTo(val2) == 0);
902
903     /* remove the attributes */
904     /* FIXME: the MDS returns ENODATA for removexattr */
905     /*
906     mount.removexattr(path, "attr1");
907     xattrs = mount.listxattr(path);
908     assertTrue(xattrs.length == 1);
909     mount.removexattr(path, "attr2");
910     xattrs = mount.listxattr(path);
911     assertTrue(xattrs.length == 0);
912     */
913
914     mount.unlink(path);
915   }
916
917   /*
918    * get/set/list/remove symlink xattr
919    *
920    * Currently not working. Code is the same as for regular xattrs, so there
921    * might be a deeper issue.
922    */
923
924   @Test
925   public void test_get_stripe_unit() throws Exception {
926     String path = makePath();
927     int fd = createFile(path, 1);
928     assertTrue(mount.get_file_stripe_unit(fd) > 0);
929     mount.close(fd);
930     mount.unlink(path);
931   }
932
933   @Test
934   public void test_get_repl() throws Exception {
935     String path = makePath();
936     int fd = createFile(path, 1);
937     assertTrue(mount.get_file_replication(fd) > 0);
938     mount.close(fd);
939     mount.unlink(path);
940   }
941
942   /*
943    * stripe unit granularity
944    */
945
946   @Test
947   public void test_get_stripe_unit_gran() throws Exception {
948     assertTrue(mount.get_stripe_unit_granularity() > 0);
949   }
950
951   @Test
952   public void test_get_pool_id() throws Exception {
953     String data_pool_name = getRootPoolName();
954     /* returns valid pool id */
955     assertTrue(mount.get_pool_id(data_pool_name) >= 0);
956
957     /* test non-existent pool name */
958     try {
959       mount.get_pool_id("asdlfkjlsejflkjef");
960       assertTrue(false);
961     } catch (CephPoolException e) {}
962   }
963
964   @Test
965   public void test_get_pool_replication() throws Exception {
966     /* test invalid pool id */
967     try {
968       mount.get_pool_replication(-1);
969       assertTrue(false);
970     } catch (CephPoolException e) {}
971
972     /* test valid pool id */
973     String data_pool_name = getRootPoolName();
974     int poolid = mount.get_pool_id(data_pool_name);
975     assertTrue(poolid >= 0);
976     assertTrue(mount.get_pool_replication(poolid) > 0);
977   }
978
979   @Test
980   public void test_get_file_pool_name() throws Exception {
981     String data_pool_name = getRootPoolName();
982     String path = makePath();
983     int fd = createFile(path, 1);
984     String pool = mount.get_file_pool_name(fd);
985     mount.close(fd);
986     assertTrue(pool != null);
987     /* assumes using default data pool */
988     assertTrue(pool.compareTo(data_pool_name) == 0);
989     mount.unlink(path);
990   }
991
992   @Test(expected=IOException.class)
993   public void test_get_file_pool_name_ebadf() throws Exception {
994     String pool = mount.get_file_pool_name(-40);
995   }
996
997   @Test
998   public void test_get_file_extent() throws Exception {
999     int stripe_unit = 1<<18;
1000     String path = makePath();
1001     int fd = mount.open(path, CephMount.O_WRONLY|CephMount.O_CREAT, 0,
1002         stripe_unit, 2, stripe_unit*2, null);
1003
1004     CephFileExtent e = mount.get_file_extent(fd, 0);
1005     assertTrue(e.getOSDs().length > 0);
1006
1007     assertTrue(e.getOffset() == 0);
1008     assertTrue(e.getLength() == stripe_unit);
1009
1010     e = mount.get_file_extent(fd, stripe_unit/2);
1011     assertTrue(e.getOffset() == stripe_unit/2);
1012     assertTrue(e.getLength() == stripe_unit/2);
1013
1014     e = mount.get_file_extent(fd, 3*stripe_unit/2-1);
1015     assertTrue(e.getOffset() == 3*stripe_unit/2-1);
1016     assertTrue(e.getLength() == stripe_unit/2+1);
1017
1018     e = mount.get_file_extent(fd, 3*stripe_unit/2+1);
1019     assertTrue(e.getLength() == stripe_unit/2-1);
1020
1021     mount.close(fd);
1022     mount.unlink(path);
1023   }
1024
1025   @Test
1026   public void test_get_osd_crush_location() throws Exception {
1027     Bucket[] path = mount.get_osd_crush_location(0);
1028     assertTrue(path.length > 0);
1029     for (Bucket b : path) {
1030       assertTrue(b.getType().length() > 0);
1031       assertTrue(b.getName().length() > 0);
1032     }
1033   }
1034
1035   @Test
1036   public void test_get_osd_address() throws Exception {
1037     InetAddress addr = mount.get_osd_address(0);
1038     assertTrue(addr.getHostAddress().length() > 0);
1039   }
1040 }