NVMeFake: add fake implementation for namespace

Faking two namespaces in the subsystem. Attaching both to the primary
controller and attaching first namespace to one of the secondary
controller as well.

It also introduces extra errors for the InitErrorInjection because there
is more identify cmd are executed during the subsystem initialization
for the namespaces. Increase the waiting time for recovery accordingly.

Tested: passed the unitest
Signed-off-by: Hao Jiang <jianghao@google.com>
Change-Id: I539e996d08a9510bba03086ef11f29dbc9115202
diff --git a/src/NVMeMiFake.hpp b/src/NVMeMiFake.hpp
index e7bbe00..bd13504 100644
--- a/src/NVMeMiFake.hpp
+++ b/src/NVMeMiFake.hpp
@@ -146,9 +146,9 @@
         std::function<void(nvme_ex_ptr, std::span<uint8_t>)>&& cb) override
     {
         std::cerr << "identify\n";
-        post([self{shared_from_this()}, cb = std::move(cb), cns]() {
+        post([self{shared_from_this()}, cb = std::move(cb), cns, nsid]() {
             std::cerr << "libnvme: identify\n";
-            self->io.post([cb{cb}, cns]() mutable {
+            self->io.post([cb{cb}, cns, nsid]() mutable {
                 std::vector<uint8_t> data;
                 switch (cns)
                 {
@@ -166,6 +166,20 @@
                         memcpy(data.data(), &list, data.size());
                         break;
                     }
+                    case NVME_IDENTIFY_CNS_NS_CTRL_LIST:
+                    {
+                        nvme_ctrl_list ctrlList{};
+                        ctrlList.num = 1;
+                        ctrlList.identifier[0] = 0;
+                        if (nsid == 1)
+                        {
+                            ctrlList.num++;
+                            ctrlList.identifier[1] = 1;
+                        }
+                        data.resize(sizeof(ctrlList));
+                        memcpy(data.data(), &ctrlList, data.size());
+                        break;
+                    }
                     default:
                         data.resize(NVME_IDENTIFY_DATA_SIZE);
                 }
@@ -485,8 +499,8 @@
         [[maybe_unused]] std::function<
             void(nvme_ex_ptr ex, std::vector<uint32_t> ns)>&& cb) override
     {
-        // return empty NS list
-        return cb({}, {});
+        // return fake NS
+        return cb({}, {1, 2});
     }
 
     void adminAttachDetachNamespace(
diff --git a/tests/test_nvme_mi.cpp b/tests/test_nvme_mi.cpp
index 08b8e8b..d069540 100644
--- a/tests/test_nvme_mi.cpp
+++ b/tests/test_nvme_mi.cpp
@@ -696,7 +696,7 @@
 
     // wait for subsystem initialization, each failure will introduce 1 second
     // delay for retry
-    timer.expires_after(subsysPollTime * (2 + 10));
+    timer.expires_after(subsysPollTime * (2 + 10 + 4));
     timer.async_wait([&](boost::system::error_code) {
         systemBus->async_method_call(
             [&, this](boost::system::error_code, const GetSubTreeType& result) {