Improve unit test infrastructure - allow control of write()
[oweals/dinit.git] / src / tests / test-includes / baseproc-sys.h
index fbe4a61c835325d2a2259338f630354b0cbd7c9c..2d2980783a36b2bdb75255c753a73d73c8803363 100644 (file)
@@ -1,12 +1,55 @@
+#ifndef BPSYS_INCLUDED
+#define BPSYS_INCLUDED
+
+#include <string>
+#include <vector>
+
 #include <sys/types.h>
-#include <iostream>
+#include <unistd.h>
+#include <sys/uio.h>
 
 // Mock system functions for testing.
 
 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);
+void set_blocking(int fd);
+void extract_written_data(int fd, std::vector<char> &data);
+
+// Mock system calls:
+
+// implementations elsewhere:
 int pipe2(int pipefd[2], int flags);
 int close(int fd);
+int kill(pid_t pid, int sig);
 
 inline int fcntl(int fd, int cmd, ...)
 {
@@ -14,12 +57,82 @@ inline int fcntl(int fd, int cmd, ...)
     return 0;
 }
 
-inline int kill(pid_t pid, int sig)
+inline pid_t getpgid(pid_t pid)
+{
+    return pid;
+}
+
+inline int tcsetpgrp(int fd, pid_t pgid)
 {
-    // No proper mock implemented yet:
-    std::cout << "(kill; aborting)" << std::endl;
-    abort();
     return 0;
 }
 
+inline pid_t getpgrp()
+{
+    return getpid();
 }
+
+class exit_status
+{
+    friend pid_t waitpid(pid_t, exit_status *, int);
+
+    bool did_exit_v;
+    bool was_signalled_v;
+    int status;
+
+    public:
+    exit_status() : did_exit_v(true), was_signalled_v(false), status(0) { }
+
+    // status_p is either the exit status or termination signal:
+    exit_status(bool did_exit_p, bool was_signalled_p, int status_p)
+        : did_exit_v(did_exit_p), was_signalled_v(was_signalled_p), status(status_p)
+    { }
+
+    explicit exit_status(int status_p)
+    {
+        throw std::string("initalised exit_status with integer argument");
+    }
+
+    bool did_exit()
+    {
+        return did_exit_v;
+    }
+
+    bool did_exit_clean()
+    {
+        return did_exit_v && status == 0;
+    }
+
+    bool was_signalled()
+    {
+        return was_signalled_v;
+    }
+
+    int get_exit_status()
+    {
+        return status;
+    }
+
+    int get_term_sig()
+    {
+        return status;
+    }
+
+    int as_int()
+    {
+        return -1;
+    }
+};
+
+inline pid_t waitpid(pid_t p, exit_status *statusp, int flags)
+{
+    throw std::string("not implemented");
+}
+
+ssize_t read(int fd, void *buf, size_t count);
+ssize_t write(int fd, const void *buf, size_t count);
+ssize_t writev (int fd, const struct iovec *iovec, int count);
+
+}
+
+#endif