Improve unit test infrastructure - allow control of write()
authorDavin McCall <davmac@davmac.org>
Wed, 1 Jan 2020 00:53:13 +0000 (10:53 +1000)
committerDavin McCall <davmac@davmac.org>
Wed, 1 Jan 2020 00:53:13 +0000 (10:53 +1000)
In the unit test infrastructure, allow behaviour of the write() call
(i.e. bp_sys::write()) to be overridden with a custom handler.

src/tests/test-bpsys.cc
src/tests/test-includes/baseproc-sys.h
src/tests/test-includes/dinit.h

index 21e9b469a012e181fd42c31c80946550f7166ec0..fc0a08d788066a19584e7a04ed7dd412fd49b79f 100644 (file)
@@ -1,6 +1,7 @@
 #include <vector>
 #include <utility>
 #include <algorithm>
+#include <memory>
 #include <map>
 
 #include <cstdlib>
@@ -35,8 +36,8 @@ class read_cond : public std::vector<read_result>
 // map of fd to read results to supply for reads of that fd
 std::map<int,read_cond> read_data;
 
-// map of data written to each fd
-std::map<int,std::vector<char>> written_data;
+// map of fd to the handler for writes to that fd
+std::map<int, std::unique_ptr<bp_sys::write_handler>> write_hndlr_map;
 
 } // anon namespace
 
@@ -47,18 +48,33 @@ pid_t last_forked_pid = 1;  // last forked process id (incremented each 'fork')
 
 // Test helper methods:
 
+void init_bpsys()
+{
+    write_hndlr_map[0] = std::unique_ptr<bp_sys::write_handler> { new default_write_handler() };
+    write_hndlr_map[1] = std::unique_ptr<bp_sys::write_handler> { new default_write_handler() };
+    write_hndlr_map[2] = std::unique_ptr<bp_sys::write_handler> { new default_write_handler() };
+}
+
 // Allocate a file descriptor
 int allocfd()
+{
+    return allocfd(new default_write_handler());
+}
+
+int allocfd(write_handler *whndlr)
 {
     auto f = std::find(usedfds.begin(), usedfds.end(), false);
     if (f == usedfds.end()) {
         int r = usedfds.size();
         usedfds.push_back(true);
+        write_hndlr_map[r] = std::unique_ptr<bp_sys::write_handler>(whndlr);
         return r;
     }
 
     *f = true;
-    return f - usedfds.begin();
+    auto r = f - usedfds.begin();
+    write_hndlr_map[r] = std::unique_ptr<bp_sys::write_handler>(whndlr);
+    return r;
 }
 
 // Supply data to be returned by read()
@@ -80,7 +96,10 @@ void set_blocking(int fd)
 // retrieve data written via write()
 void extract_written_data(int fd, std::vector<char> &data)
 {
-       data = std::move(written_data[fd]);
+    auto &whandler = write_hndlr_map[fd];
+    if (whandler == nullptr) abort();
+    default_write_handler *dwhndlr = static_cast<default_write_handler *>(whandler.get());
+       data = std::move(dwhndlr->data);
 }
 
 
@@ -96,8 +115,10 @@ int pipe2(int fds[2], int flags)
 int close(int fd)
 {
     if (size_t(fd) >= usedfds.size()) abort();
+    if (! usedfds[fd]) abort();
 
     usedfds[fd] = false;
+    write_hndlr_map.erase(fd);
     return 0;
 }
 
@@ -145,9 +166,7 @@ ssize_t read(int fd, void *buf, size_t count)
 
 ssize_t write(int fd, const void *buf, size_t count)
 {
-       std::vector<char> &wd = written_data[fd];
-       wd.insert(wd.end(), (char *)buf, (char *)buf + count);
-       return count;
+    return write_hndlr_map[fd]->write(fd, buf, count);
 }
 
 ssize_t writev(int fd, const struct iovec *iov, int iovcnt)
index c8e2441877479a50d05247792a22b27381d6b79a..2d2980783a36b2bdb75255c753a73d73c8803363 100644 (file)
 
 namespace bp_sys {
 
+class write_handler
+{
+public:
+    virtual ssize_t write(int fd, const void *buf, size_t count) = 0;
+    virtual ~write_handler() { }
+};
+
+class default_write_handler : public write_handler
+{
+public:
+    std::vector<char> data;
+
+    virtual ssize_t write(int fd, const void *buf, size_t count)
+    {
+        data.insert(data.end(), (char *)buf, (char *)buf + count);
+        return count;
+    }
+};
+
 // Test helper functions:
 
+void init_bpsys();
+
 // allocate a file descriptor
 int allocfd();
+int allocfd(write_handler *hndlr);
 
 void supply_read_data(int fd, std::vector<char> &data);
 void supply_read_data(int fd, std::vector<char> &&data);
index bf6eb68e77ec05ddc48758673fc4cea1c3abf0e0..22804fc71227975a41325624058750446e146fc8 100644 (file)
@@ -47,7 +47,11 @@ class eventloop_t
     {
         auto i = regd_fd_watchers.find(fd);
         if (i != regd_fd_watchers.end()) {
-            i->second->fd_event(*this, fd, events);
+            fd_watcher *watcher = i->second;
+            dasynq::rearm r = watcher->fd_event(*this, fd, events);
+            if (r == dasynq::rearm::REMOVE) {
+                watcher->deregister(*this);
+            }
         }
     }
 
@@ -115,6 +119,7 @@ class eventloop_t
         {
             loop.regd_fd_watchers.erase(watched_fd);
             watched_fd = -1;
+            watch_removed();
         }
 
         virtual rearm fd_event(eventloop_t & loop, int fd, int flags) = 0;