Add test for console release for STARTING to STOPPED transition.
authorDavin McCall <davmac@davmac.org>
Thu, 18 Jan 2018 23:24:46 +0000 (23:24 +0000)
committerDavin McCall <davmac@davmac.org>
Thu, 18 Jan 2018 23:24:46 +0000 (23:24 +0000)
Test for console release when a service goes from STARTING to STOPPED.
Currently fails.

src/includes/service.h
src/tests/test_service.h
src/tests/tests.cc

index b0cf50a0406b17d5ee5ba7583f723b11aa8f3ef6..a11262f14710526104a7ba9a78f864c67e110af4 100644 (file)
@@ -769,6 +769,19 @@ class service_set
         }
     }
 
+    // Check if console queue is empty (possibly due to console already having
+    // been assigned to the only queueing service)
+    bool is_console_queue_empty() noexcept
+    {
+        return console_queue.is_empty();
+    }
+
+    // Check whether a service is queued for the console
+    bool is_queued_for_console(service_record * service) noexcept
+    {
+        return console_queue.is_queued(service);
+    }
+
     // Notification from service that it is active (state != STOPPED)
     // Only to be called on the transition from inactive to active.
     void service_active(service_record *) noexcept;
index 50daeae25a8332db0be07a0b0c422f190fb6f714..7ee377b69543d0806d1584992996e703fc380228 100644 (file)
@@ -1,5 +1,10 @@
 #include "service.h"
 
+// A test service.
+//
+// This service can be induced to successfully start or fail (once it is STARTING) by calling either the
+// started() or failed_to_start() functions.
+//
 class test_service : public service_record
 {
     public:
index c7b9f082f4fe619d6eda1aff8ed3bd31c0831763..893522f6bfcaffd1ce2642de0d26b0cd3e2576a8 100644 (file)
@@ -300,6 +300,65 @@ void test9()
     assert(s2->get_state() == service_state_t::STOPPED);
 }
 
+// Test 10: if start cancelled, remove from console queue
+void test10()
+{
+    service_set sset;
+
+    // Create s1 and s2. s2 depends on s1, and starts on the console.
+    test_service *s1 = new test_service(&sset, "test-service-1", service_type_t::INTERNAL, {});
+    test_service *s2 = new test_service(&sset, "test-service-2", service_type_t::INTERNAL, {{s1, REG}});
+    onstart_flags_t s2_flags;
+    s2_flags.starts_on_console = true;
+    s2->set_flags(s2_flags);
+    sset.add_service(s1);
+    sset.add_service(s2);
+
+    // Create s3, which starts and runs on console:
+    test_service *s3 = new test_service(&sset, "test-service-3", service_type_t::INTERNAL, {});
+    onstart_flags_t s3_flags;
+    s3_flags.starts_on_console = true;
+    s3_flags.runs_on_console = true;
+    sset.add_service(s3);
+
+    assert(sset.find_service("test-service-1") == s1);
+    assert(sset.find_service("test-service-2") == s2);
+    assert(sset.find_service("test-service-3") == s3);
+
+    // Start the s3 service, so it gets console:
+    sset.start_service(s3);
+    sset.process_queues();
+    s3->started();
+    sset.process_queues();
+
+    assert(! sset.is_queued_for_console(s3)); // should not be queued, because already has acquired
+    assert(sset.is_console_queue_empty());
+
+    // Start s2, which starts s1 as a dependency:
+
+    sset.start_service(s2);
+    sset.process_queues();
+
+    assert(s1->get_state() == service_state_t::STARTING);
+    assert(s2->get_state() == service_state_t::STARTING);
+
+    s1->started();
+    sset.process_queues();
+
+    // s2 should now be waiting for console:
+    assert(s1->get_state() == service_state_t::STARTED);
+    assert(s2->get_state() == service_state_t::STARTING);
+    assert(sset.is_queued_for_console(s2));
+
+    // stop s1, should stop s2, s2 should unqueue:
+    s1->stop();
+    sset.process_queues();
+
+    assert(s1->get_state() == service_state_t::STOPPED);
+    assert(s2->get_state() == service_state_t::STOPPED);
+    assert(! sset.is_queued_for_console(s2));
+}
+
 #define RUN_TEST(name) \
     std::cout << #name "... "; \
     name(); \
@@ -316,4 +375,5 @@ int main(int argc, char **argv)
     RUN_TEST(test7);
     RUN_TEST(test8);
     RUN_TEST(test9);
+    RUN_TEST(test10);
 }