From 4002600dd685491050e2e524556b82ea69e19c24 Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Tue, 10 Jul 2018 12:14:16 +0100 Subject: [PATCH] tests: add another control protocol test (load service). --- src/tests/cptests/cptests.cc | 95 ++++++++++++++++++++++++++ src/tests/test-bpsys.cc | 22 +++++- src/tests/test-includes/baseproc-sys.h | 1 + 3 files changed, 116 insertions(+), 2 deletions(-) diff --git a/src/tests/cptests/cptests.cc b/src/tests/cptests/cptests.cc index 1041c1d..322f4aa 100644 --- a/src/tests/cptests/cptests.cc +++ b/src/tests/cptests/cptests.cc @@ -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 cmd = { DINIT_CP_LOADSERVICE }; + uint16_t name_len = strlen(service_name_1); + char *name_len_cptr = reinterpret_cast(&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 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(wdata[1]); + assert(s == service_state_t::STOPPED); + service_state_t ts = static_cast(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(wdata[1]); + assert(s == service_state_t::STOPPED); + ts = static_cast(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; } diff --git a/src/tests/test-bpsys.cc b/src/tests/test-bpsys.cc index 794f687..9f9ada2 100644 --- a/src/tests/test-bpsys.cc +++ b/src/tests/test-bpsys.cc @@ -23,8 +23,17 @@ struct read_result std::vector data; // data (if errcode == 0) }; +class read_cond : public std::vector +{ + public: + using vector::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> read_data; +std::map read_data; // map of data written to each fd std::map> written_data; @@ -63,6 +72,11 @@ void supply_read_data(int fd, std::vector &&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 &data) { @@ -95,8 +109,12 @@ int kill(pid_t pid, int sig) ssize_t read(int fd, void *buf, size_t count) { - std::vector & rrs = read_data[fd]; + read_cond & rrs = read_data[fd]; if (rrs.empty()) { + if (rrs.is_blocking) { + errno = EAGAIN; + return -1; + } return 0; } diff --git a/src/tests/test-includes/baseproc-sys.h b/src/tests/test-includes/baseproc-sys.h index 4376ae1..78e3408 100644 --- a/src/tests/test-includes/baseproc-sys.h +++ b/src/tests/test-includes/baseproc-sys.h @@ -18,6 +18,7 @@ int allocfd(); void supply_read_data(int fd, std::vector &data); void supply_read_data(int fd, std::vector &&data); +void set_blocking(int fd); void extract_written_data(int fd, std::vector &data); // Mock system calls: -- 2.25.1