]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/fs/fuse/mockfs.hh
fuse(4) use a global environment check.
[FreeBSD/FreeBSD.git] / tests / sys / fs / fuse / mockfs.hh
1 /*-
2  * Copyright (c) 2019 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by BFF Storage Systems, LLC under sponsorship
6  * from the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 extern "C" {
31 #include <sys/types.h>
32
33 #include <pthread.h>
34
35 #include "fuse_kernel.h"
36 }
37
38 #include <gmock/gmock.h>
39
40 #define SET_OUT_HEADER_LEN(out, variant) { \
41         (out)->header.len = (sizeof((out)->header) + \
42                              sizeof((out)->body.variant)); \
43 }
44
45 extern int verbosity;
46
47 union fuse_payloads_in {
48         /* value is from fuse_kern_chan.c in fusefs-libs */
49         uint8_t         bytes[0x21000 - sizeof(struct fuse_in_header)];
50         fuse_forget_in  forget;
51         fuse_init_in    init;
52         char            lookup[0];
53         fuse_setattr_in setattr;
54 };
55
56 struct mockfs_buf_in {
57         fuse_in_header          header;
58         union fuse_payloads_in  body;
59 };
60
61 union fuse_payloads_out {
62         fuse_init_out           init;
63         fuse_entry_out          entry;
64         fuse_attr_out           attr;
65 };
66
67 struct mockfs_buf_out {
68         fuse_out_header         header;
69         union fuse_payloads_out body;
70 };
71
72 /*
73  * Fake FUSE filesystem
74  *
75  * "Mounts" a filesystem to a temporary directory and services requests
76  * according to the programmed expectations.
77  *
78  * Operates directly on the fuse(4) kernel API, not the libfuse(3) user api.
79  */
80 class MockFS {
81         public:
82         /* thread id of the fuse daemon thread */
83         pthread_t m_daemon_id;
84
85         private:
86         /* file descriptor of /dev/fuse control device */
87         int m_fuse_fd;
88         
89         /* pid of the test process */
90         pid_t m_pid;
91
92         /* 
93          * Thread that's running the mockfs daemon.
94          *
95          * It must run in a separate thread so it doesn't deadlock with the
96          * client test code.
97          */
98         pthread_t m_thr;
99
100         /* Initialize a session after mounting */
101         void init();
102
103         /* Default request handler */
104         void process_default(const mockfs_buf_in*, mockfs_buf_out*);
105
106         /* Entry point for the daemon thread */
107         static void* service(void*);
108
109         /* Read, but do not process, a single request from the kernel */
110         void read_request(mockfs_buf_in*);
111
112         public:
113         /* Create a new mockfs and mount it to a tempdir */
114         MockFS();
115         virtual ~MockFS();
116
117         /* Process FUSE requests endlessly */
118         void loop();
119
120         /* 
121          * Request handler
122          *
123          * This method is expected to provide the response to each FUSE
124          * operation.  Responses must be immediate (so this method can't be used
125          * for testing a daemon with queue depth > 1).  Test cases must define
126          * each response using Googlemock expectations
127          */
128         MOCK_METHOD2(process, void(const mockfs_buf_in*, mockfs_buf_out*));
129
130         /* Gracefully unmount */
131         void unmount();
132 };