10 #include "baseproc-sys.h"
14 std::vector<bool> usedfds = {true, true, true};
18 read_result(int errcode_p) : errcode(errcode_p) {}
20 read_result(std::vector<char> &data_p) : errcode(0), data(data_p) {}
21 read_result(std::vector<char> &&data_p) : errcode(0), data(std::move(data_p)) {}
23 int errcode; // errno return
24 std::vector<char> data; // data (if errcode == 0)
27 class read_cond : public std::vector<read_result>
30 using vector<read_result>::vector;
32 // if blocking, return EAGAIN rather than end-of-file:
33 bool is_blocking = false;
36 // map of fd to read results to supply for reads of that fd
37 std::map<int,read_cond> read_data;
39 // map of fd to the handler for writes to that fd
40 std::map<int, std::unique_ptr<bp_sys::write_handler>> write_hndlr_map;
46 int last_sig_sent = -1; // last signal number sent, accessible for tests.
47 pid_t last_forked_pid = 1; // last forked process id (incremented each 'fork')
49 // Test helper methods:
53 write_hndlr_map[0] = std::unique_ptr<bp_sys::write_handler> { new default_write_handler() };
54 write_hndlr_map[1] = std::unique_ptr<bp_sys::write_handler> { new default_write_handler() };
55 write_hndlr_map[2] = std::unique_ptr<bp_sys::write_handler> { new default_write_handler() };
58 // Allocate a file descriptor
61 return allocfd(new default_write_handler());
64 int allocfd(write_handler *whndlr)
66 auto f = std::find(usedfds.begin(), usedfds.end(), false);
67 if (f == usedfds.end()) {
68 int r = usedfds.size();
69 usedfds.push_back(true);
70 write_hndlr_map[r] = std::unique_ptr<bp_sys::write_handler>(whndlr);
75 auto r = f - usedfds.begin();
76 write_hndlr_map[r] = std::unique_ptr<bp_sys::write_handler>(whndlr);
80 // Supply data to be returned by read()
81 void supply_read_data(int fd, std::vector<char> &data)
83 read_data[fd].emplace_back(data);
86 void supply_read_data(int fd, std::vector<char> &&data)
88 read_data[fd].emplace_back(std::move(data));
91 void set_blocking(int fd)
93 read_data[fd].is_blocking = true;
96 // retrieve data written via write()
97 void extract_written_data(int fd, std::vector<char> &data)
99 auto &whandler = write_hndlr_map[fd];
100 if (whandler == nullptr) abort();
101 default_write_handler *dwhndlr = static_cast<default_write_handler *>(whandler.get());
102 data = std::move(dwhndlr->data);
106 // Mock implementations of system calls:
108 int pipe2(int fds[2], int flags)
117 if (size_t(fd) >= usedfds.size()) abort();
118 if (! usedfds[fd]) abort();
121 write_hndlr_map.erase(fd);
125 int kill(pid_t pid, int sig)
131 ssize_t read(int fd, void *buf, size_t count)
133 read_cond & rrs = read_data[fd];
135 if (rrs.is_blocking) {
142 read_result &rr = rrs.front();
143 if (rr.errcode != 0) {
145 // Remove the result record:
146 auto i = rrs.begin();
148 rrs.erase(rrs.begin(), i);
152 auto dsize = rr.data.size();
153 if (dsize <= count) {
154 // Consume entire result:
155 std::copy_n(rr.data.begin(), dsize, (char *)buf);
156 // Remove the result record:
157 rrs.erase(rrs.begin());
161 // Consume partial result:
162 std::copy_n(rr.data.begin(), count, (char *)buf);
163 rr.data.erase(rr.data.begin(), rr.data.begin() + count);
167 ssize_t write(int fd, const void *buf, size_t count)
169 return write_hndlr_map[fd]->write(fd, buf, count);
172 ssize_t writev(int fd, const struct iovec *iov, int iovcnt)
175 for (int i = 0; i < iovcnt; i++) {
176 ssize_t wr = write(fd, iov[i].iov_base, iov[i].iov_len);
184 if (size_t(wr) < iov[i].iov_len) {