1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <fcntl.h>
6 #include <limits.h>
7 #include <unistd.h>
8 
9 #include <fbl/unique_fd.h>
10 #include <fs-management/fvm.h>
11 #include <lib/async-loop/cpp/loop.h>
12 #include <lib/memfs/memfs.h>
13 #include <unittest/unittest.h>
14 #include <zircon/device/device.h>
15 
16 #include "filesystems.h"
17 
18 const char* filesystem_name_filter = "";
19 
print_test_help(FILE * f)20 static void print_test_help(FILE* f) {
21     fprintf(f,
22             "  -d <blkdev>\n"
23             "      Use block device <blkdev> instead of a ramdisk\n"
24             "\n"
25             "  -f <fs>\n"
26             "      Test only fileystem <fs>, where <fs> is one of:\n");
27     for (int j = 0; j < NUM_FILESYSTEMS; j++) {
28         fprintf(f, "%8s%s\n", "", FILESYSTEMS[j].name);
29     }
30 }
31 
main(int argc,char ** argv)32 int main(int argc, char** argv) {
33     use_real_disk = false;
34 
35     unittest_register_test_help_printer(print_test_help);
36 
37     int i = 1;
38     while (i < argc) {
39         if (strcmp(argv[i], "-d") == 0 && (i + 1 < argc)) {
40             fbl::unique_fd fd(open(argv[i + 1], O_RDWR));
41             if (!fd) {
42                 fprintf(stderr, "[fs] Could not open block device\n");
43                 return -1;
44             } else if (ioctl_device_get_topo_path(fd.get(), test_disk_path, PATH_MAX) < 0) {
45                 fprintf(stderr, "[fs] Could not acquire topological path of block device\n");
46                 return -1;
47             } else if (ioctl_block_get_info(fd.get(), &test_disk_info) < 0) {
48                 fprintf(stderr, "[fs] Could not read disk info\n");
49                 return -1;
50             }
51             // If we previously tried running tests on this disk, it may
52             // have created an FVM and failed. (Try to) clean up from previous state
53             // before re-running.
54             fvm_destroy(test_disk_path);
55             use_real_disk = true;
56             i += 2;
57         } else if (!strcmp(argv[i], "-f") && (i + 1 < argc)) {
58             bool found = false;
59             for (int j = 0; j < NUM_FILESYSTEMS; j++) {
60                 if (!strcmp(argv[i + 1], FILESYSTEMS[j].name)) {
61                     found = true;
62                     filesystem_name_filter = argv[i + 1];
63                     break;
64                 }
65             }
66             if (!found) {
67                 fprintf(stderr, "Error: Filesystem not found\n");
68                 return -1;
69             }
70             i += 2;
71         } else {
72             // Ignore options we don't recognize. See ulib/unittest/README.md.
73             break;
74         }
75     }
76 
77     // Initialize tmpfs.
78     async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
79     if (loop.StartThread() != ZX_OK) {
80         fprintf(stderr, "Error: Cannot initialize local tmpfs loop\n");
81         return -1;
82     }
83     if (memfs_install_at(loop.dispatcher(), kTmpfsPath) != ZX_OK) {
84         fprintf(stderr, "Error: Cannot install local tmpfs\n");
85         return -1;
86     }
87 
88     return unittest_run_all_tests(argc, argv) ? 0 : -1;
89 }
90