tests: add another control protocol test (load service).
authorDavin McCall <davmac@davmac.org>
Tue, 10 Jul 2018 11:14:16 +0000 (12:14 +0100)
committerDavin McCall <davmac@davmac.org>
Tue, 10 Jul 2018 11:14:16 +0000 (12:14 +0100)
src/tests/cptests/cptests.cc
src/tests/test-bpsys.cc
src/tests/test-includes/baseproc-sys.h

index 1041c1de67479895c7b712b2ae1e62117e386d02..322f4aae5120440cafc7c802f23b5cffe79629a1 100644 (file)
@@ -228,6 +228,100 @@ void cptest_findservice3()
     delete cc;
 }
 
+class test_service_set : public service_set
+{
+    public:
+    service_record * service1 = nullptr;
+    service_record * service2 = nullptr;
+
+    virtual service_record *load_service(const char *name) override
+    {
+        auto r = find_service(name);
+        if (r == nullptr) {
+            if (strcmp(name, "test-service-1") == 0) {
+                service1 = new service_record(this, "test-service-1");
+                add_service(service1);
+                return service1;
+            }
+            else if (strcmp(name, "test-service-2") == 0) {
+                service2 = new service_record(this, "test-service-2");
+                add_service(service2);
+                return service2;
+            }
+            throw service_not_found(name);
+        }
+        return r;
+    }
+};
+
+void cptest_loadservice()
+{
+    test_service_set sset;
+
+    const char * const service_name_1 = "test-service-1";
+    const char * const service_name_2 = "test-service-2";
+
+    int fd = bp_sys::allocfd();
+    auto *cc = new control_conn_t(event_loop, &sset, fd);
+
+    std::vector<char> cmd = { DINIT_CP_LOADSERVICE };
+    uint16_t name_len = strlen(service_name_1);
+    char *name_len_cptr = reinterpret_cast<char *>(&name_len);
+    cmd.insert(cmd.end(), name_len_cptr, name_len_cptr + sizeof(name_len));
+    cmd.insert(cmd.end(), service_name_1, service_name_1 + name_len);
+
+    bp_sys::supply_read_data(fd, std::move(cmd));
+    bp_sys::set_blocking(fd);
+
+    event_loop.regd_bidi_watchers[fd]->read_ready(event_loop, fd);
+
+    // We expect:
+    // (1 byte)   DINIT_RP_SERVICERECORD
+    // (1 byte)   state
+    // (handle_t) handle
+    // (1 byte)   target state
+
+    std::vector<char> wdata;
+    bp_sys::extract_written_data(fd, wdata);
+
+    assert(wdata.size() == 3 + sizeof(control_conn_t::handle_t));
+    assert(wdata[0] == DINIT_RP_SERVICERECORD);
+    service_state_t s = static_cast<service_state_t>(wdata[1]);
+    assert(s == service_state_t::STOPPED);
+    service_state_t ts = static_cast<service_state_t>(wdata[6]);
+    assert(ts == service_state_t::STOPPED);
+
+    assert(sset.service1 != nullptr);
+    assert(sset.service2 == nullptr);
+
+    cmd = { DINIT_CP_LOADSERVICE };
+    cmd.insert(cmd.end(), name_len_cptr, name_len_cptr + sizeof(name_len));
+    cmd.insert(cmd.end(), service_name_2, service_name_2 + name_len);
+
+    bp_sys::supply_read_data(fd, std::move(cmd));
+
+    event_loop.regd_bidi_watchers[fd]->read_ready(event_loop, fd);
+
+    // We expect:
+    // (1 byte)   DINIT_RP_SERVICERECORD
+    // (1 byte)   state
+    // (handle_t) handle
+    // (1 byte)   target state
+
+    bp_sys::extract_written_data(fd, wdata);
+
+    assert(wdata.size() == 3 + sizeof(control_conn_t::handle_t));
+    assert(wdata[0] == DINIT_RP_SERVICERECORD);
+    s = static_cast<service_state_t>(wdata[1]);
+    assert(s == service_state_t::STOPPED);
+    ts = static_cast<service_state_t>(wdata[6]);
+    assert(ts == service_state_t::STOPPED);
+
+    assert(sset.service1 != nullptr);
+    assert(sset.service2 != nullptr);
+
+    delete cc;
+}
 
 #define RUN_TEST(name, spacing) \
     std::cout << #name "..." spacing; \
@@ -241,5 +335,6 @@ int main(int argc, char **argv)
     RUN_TEST(cptest_findservice1, "");
     RUN_TEST(cptest_findservice2, "");
     RUN_TEST(cptest_findservice3, "");
+    RUN_TEST(cptest_loadservice, " ");
     return 0;
 }
index 794f687503990c815eb31cb9024989b89de8299c..9f9ada27b90d963d46d39bab23c152c8ea1dbee5 100644 (file)
@@ -23,8 +23,17 @@ struct read_result
        std::vector<char> data;  // data (if errcode == 0)
 };
 
+class read_cond : public std::vector<read_result>
+{
+    public:
+    using vector<read_result>::vector;
+
+    // if blocking, return EAGAIN rather than end-of-file:
+    bool is_blocking = false;
+};
+
 // map of fd to read results to supply for reads of that fd
-std::map<int,std::vector<read_result>> read_data;
+std::map<int,read_cond> read_data;
 
 // map of data written to each fd
 std::map<int,std::vector<char>> written_data;
@@ -63,6 +72,11 @@ void supply_read_data(int fd, std::vector<char> &&data)
        read_data[fd].emplace_back(std::move(data));
 }
 
+void set_blocking(int fd)
+{
+    read_data[fd].is_blocking = true;
+}
+
 // retrieve data written via write()
 void extract_written_data(int fd, std::vector<char> &data)
 {
@@ -95,8 +109,12 @@ int kill(pid_t pid, int sig)
 
 ssize_t read(int fd, void *buf, size_t count)
 {
-       std::vector<read_result> & rrs = read_data[fd];
+       read_cond & rrs = read_data[fd];
        if (rrs.empty()) {
+           if (rrs.is_blocking) {
+               errno = EAGAIN;
+               return -1;
+           }
                return 0;
        }
 
index 4376ae19914b033dd9876e605396eaa7e0f14a07..78e3408d19c820a7362afc47381e9fa61bdcba66 100644 (file)
@@ -18,6 +18,7 @@ int allocfd();
 
 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: