tests: allow batch resource updates in sysrepo alarm expectations

Change-Id: I6723bbcca7b8b9a1e114283426f4851c6e74506a
diff --git a/tests/health_systemd-units.cpp b/tests/health_systemd-units.cpp
index 2a82e6e..5bf878b 100644
--- a/tests/health_systemd-units.cpp
+++ b/tests/health_systemd-units.cpp
@@ -22,7 +22,7 @@
 using namespace std::chrono_literals;
 
 #define REQUIRE_NEW_ALARM_INVENTORY_UNIT(UNIT) \
-    REQUIRE_NEW_ALARM_INVENTORY_RESOURCE(alarmsWatcher, "velia-alarms:systemd-unit-failure", std::set<std::string>{UNIT})
+    REQUIRE_NEW_ALARM_INVENTORY_RESOURCES(alarmsWatcher, (std::set<std::string>{"velia-alarms:systemd-unit-failure"}), std::set<std::string>{UNIT})
 
 #define REQUIRE_ALARM_RPC(UNIT, SEVERITY, TEXT) \
     REQUIRE_NEW_ALARM(alarmsWatcher, "velia-alarms:systemd-unit-failure", UNIT, SEVERITY, TEXT)
diff --git a/tests/sysrepo-helpers/alarms.cpp b/tests/sysrepo-helpers/alarms.cpp
index 3b95bb0..c7ad7e3 100644
--- a/tests/sysrepo-helpers/alarms.cpp
+++ b/tests/sysrepo-helpers/alarms.cpp
@@ -13,11 +13,13 @@
 {
 }
 
-void AlarmWatcher::AlarmInventory::add(const std::string& alarmTypeId, const std::set<std::string>& resources, const std::set<std::string>& severities)
+void AlarmWatcher::AlarmInventory::add(const std::set<std::string>& alarmTypeIds, const std::set<std::string>& resources, const std::set<std::string>& severities)
 {
-    auto& alarm = inventory[alarmTypeId];
-    alarm.resources.insert(resources.begin(), resources.end());
-    alarm.severities.insert(severities.begin(), severities.end());
+    for (const auto& type : alarmTypeIds) {
+        auto& alarm = inventory[type];
+        alarm.resources.insert(resources.begin(), resources.end());
+        alarm.severities.insert(severities.begin(), severities.end());
+    }
 }
 
 bool AlarmWatcher::AlarmInventory::contains(const std::string& alarmTypeId, const std::optional<std::string>& resource, const std::optional<std::string>& severity) const
diff --git a/tests/sysrepo-helpers/alarms.h b/tests/sysrepo-helpers/alarms.h
index 914c0e5..6863a8e 100644
--- a/tests/sysrepo-helpers/alarms.h
+++ b/tests/sysrepo-helpers/alarms.h
@@ -15,13 +15,7 @@
 #include "sysrepo-helpers/rpc.h"
 #include "test_log_setup.h"
 
-enum class EntryAction {
-    Create,
-    Update,
-};
-
-inline ValueChanges constructAlarmInventoryChange(EntryAction action,
-                                                  const std::string& alarmType,
+inline ValueChanges constructAlarmInventoryChange(const std::string& alarmType,
                                                   const std::set<std::string>& resources,
                                                   const std::set<std::string>& severities,
                                                   const std::optional<bool>& willClear,
@@ -30,11 +24,8 @@
     const std::string prefix = "/ietf-alarms:alarms/alarm-inventory/alarm-type[alarm-type-id='" + alarmType + "'][alarm-type-qualifier='']";
 
     ValueChanges ret;
-
-    if (action == EntryAction::Create) {
-        ret.emplace(prefix + "/alarm-type-id", alarmType);
-        ret.emplace(prefix + "/alarm-type-qualifier", "");
-    }
+    ret.emplace(prefix + "/alarm-type-id", alarmType);
+    ret.emplace(prefix + "/alarm-type-qualifier", "");
 
     if (willClear) {
         ret.emplace(prefix + "/will-clear", *willClear ? "true" : "false");
@@ -57,6 +48,21 @@
     return ret;
 }
 
+inline ValueChanges constructAlarmInventoryResourceChange(const std::set<std::string>& alarmTypeIds, const std::set<std::string>& resources) {
+    ValueChanges ret;
+
+    for (const auto& alarmType : alarmTypeIds) {
+        const std::string prefix = "/ietf-alarms:alarms/alarm-inventory/alarm-type[alarm-type-id='" + alarmType + "'][alarm-type-qualifier='']";
+
+        size_t i = 1;
+        for (const auto& resource : resources) {
+            ret.emplace(prefix + "/resource[" + std::to_string(i++) + "]", resource);
+        }
+    }
+
+    return ret;
+}
+
 /** @brief A simple mock implementation of the alarm server */
 struct AlarmWatcher {
     /** @brief Poor man's /ietf-alarms:alarms/alarm-inventory implementation in C++. */
@@ -70,7 +76,7 @@
 
         std::map<AlarmType, AllowedResourcesAndSeverities> inventory;
 
-        void add(const std::string& alarmTypeId, const std::set<std::string>& resources, const std::set<std::string>& severities);
+        void add(const std::set<std::string>& alarmTypeIds, const std::set<std::string>& resources, const std::set<std::string>& severities);
         bool contains(const std::string& alarmTypeId, const std::optional<std::string>& resource, const std::optional<std::string>& severity) const;
     };
 
@@ -86,16 +92,16 @@
     LR_WITH(INV.contains(ALARM_TYPE, RESOURCE, SEVERITY))
 
 // inserts the alarm in AlarmInventory as a side effect
-#define INSERT_INTO_INVENTORY(INV, ALARM_TYPE, RESOURCE, SEVERITIES) \
-    LR_SIDE_EFFECT(INV.add(ALARM_TYPE, RESOURCE, SEVERITIES))
+#define INSERT_INTO_INVENTORY(INV, ALARM_TYPES, RESOURCES, SEVERITIES) \
+    LR_SIDE_EFFECT(INV.add(ALARM_TYPES, RESOURCES, SEVERITIES))
 
 #define REQUIRE_NEW_ALARM_INVENTORY_ENTRY(WATCHER, ALARM_TYPE, RESOURCES, SEVERITIES, WILL_CLEAR, DESCRIPTION) \
-    REQUIRE_DATASTORE_CHANGE(WATCHER.datastoreWatcher, constructAlarmInventoryChange(EntryAction::Create, ALARM_TYPE, RESOURCES, SEVERITIES, WILL_CLEAR, DESCRIPTION)) \
-        .INSERT_INTO_INVENTORY(WATCHER.alarmInventory, ALARM_TYPE, RESOURCES, SEVERITIES)
+    REQUIRE_DATASTORE_CHANGE(WATCHER.datastoreWatcher, constructAlarmInventoryChange(ALARM_TYPE, RESOURCES, SEVERITIES, WILL_CLEAR, DESCRIPTION)) \
+        .INSERT_INTO_INVENTORY(WATCHER.alarmInventory, (std::set<std::string>{ALARM_TYPE}), RESOURCES, SEVERITIES)
 
-#define REQUIRE_NEW_ALARM_INVENTORY_RESOURCE(WATCHER, ALARM_TYPE, RESOURCES) \
-    REQUIRE_DATASTORE_CHANGE(WATCHER.datastoreWatcher, constructAlarmInventoryChange(EntryAction::Update, ALARM_TYPE, RESOURCES, {}, std::nullopt, std::nullopt)) \
-        .INSERT_INTO_INVENTORY(WATCHER.alarmInventory, ALARM_TYPE, RESOURCES, (std::set<std::string>{}))
+#define REQUIRE_NEW_ALARM_INVENTORY_RESOURCES(WATCHER, ALARM_TYPES, RESOURCES) \
+    REQUIRE_DATASTORE_CHANGE(WATCHER.datastoreWatcher, constructAlarmInventoryResourceChange(ALARM_TYPES, RESOURCES)) \
+        .INSERT_INTO_INVENTORY(WATCHER.alarmInventory, ALARM_TYPES, RESOURCES, (std::set<std::string>{}))
 
 #define REQUIRE_NEW_ALARM(WATCHER, ALARM_TYPE, RESOURCE, SEVERITY, TEXT) \
     REQUIRE_RPC_CALL(WATCHER.rpcWatcher, (Values{ \
diff --git a/tests/sysrepo_ietf-hardware.cpp b/tests/sysrepo_ietf-hardware.cpp
index a9424a9..ed86055 100644
--- a/tests/sysrepo_ietf-hardware.cpp
+++ b/tests/sysrepo_ietf-hardware.cpp
@@ -20,7 +20,7 @@
             (std::set<std::string>{}), true, DESCRIPTION)
 
 #define REQUIRE_ALARM_INVENTORY_ADD_RESOURCES(ALARM_TYPE, ...) \
-    REQUIRE_NEW_ALARM_INVENTORY_RESOURCE(alarmWatcher, ALARM_TYPE, (std::set<std::string>{__VA_ARGS__}))
+    REQUIRE_NEW_ALARM_INVENTORY_RESOURCES(alarmWatcher, (std::set<std::string>{ALARM_TYPE}), (std::set<std::string>{__VA_ARGS__}))
 
 #define REQUIRE_ALARM_RPC(ALARM_TYPE, RESOURCE, SEVERITY, TEXT) \
     REQUIRE_NEW_ALARM(alarmWatcher, ALARM_TYPE, COMPONENT(RESOURCE), SEVERITY, TEXT)