1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2019-2019 Bareos GmbH & Co. KG
5 
6    This program is Free Software; you can redistribute it and/or
7    modify it under the terms of version three of the GNU Affero General Public
8    License as published by the Free Software Foundation and included
9    in the file LICENSE.
10 
11    This program is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14    Affero General Public License for more details.
15 
16    You should have received a copy of the GNU Affero General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19    02110-1301, USA.
20 */
21 
22 #if defined(HAVE_MINGW)
23 #include "include/bareos.h"
24 #include "gtest/gtest.h"
25 #else
26 #include "gtest/gtest.h"
27 #include "include/bareos.h"
28 #endif
29 
30 #include "lib/alist.h"
31 #include "lib/parse_conf.h"
32 #include "stored/stored_conf.h"
33 #include "stored/stored_globals.h"
34 
35 using namespace storagedaemon;
36 
37 typedef std::unique_ptr<ConfigurationParser> PConfigParser;
38 
InitGlobals()39 static void InitGlobals()
40 {
41   my_config = nullptr;
42   OSDependentInit();
43 }
44 
GetMultipliedDeviceResource(ConfigurationParser & my_config)45 static DeviceResource* GetMultipliedDeviceResource(
46     ConfigurationParser& my_config)
47 {
48   const char* name = "MultipliedDeviceResource0001";
49 
50   BareosResource* p = my_config.GetResWithName(R_DEVICE, name, false);
51   DeviceResource* device = dynamic_cast<DeviceResource*>(p);
52   if (device && device->count) { return device; }
53 
54   return nullptr;
55 }
56 
TEST(sd,MultipliedDeviceTest_ConfigParameter)57 TEST(sd, MultipliedDeviceTest_ConfigParameter)
58 {
59   InitGlobals();
60   std::string path_to_config =
61       RELATIVE_PROJECT_SOURCE_DIR "/configs/stored_multiplied_device/";
62 
63   PConfigParser my_config(InitSdConfig(path_to_config.c_str(), M_INFO));
64   storagedaemon::my_config = my_config.get();
65 
66   ASSERT_TRUE(my_config->ParseConfig());
67   auto device = GetMultipliedDeviceResource(*my_config);
68   ASSERT_TRUE(device);
69 
70   EXPECT_EQ(device->count, 3);
71 }
72 
CountAllDeviceResources(ConfigurationParser & my_config)73 static uint32_t CountAllDeviceResources(ConfigurationParser& my_config)
74 {
75   uint32_t count = 0;
76   BareosResource* p = nullptr;
77   while ((p = my_config.GetNextRes(R_DEVICE, p))) {
78     DeviceResource* device = dynamic_cast<DeviceResource*>(p);
79     if (device && device->multiplied_device_resource) { count++; }
80   }
81   return count;
82 }
83 
TEST(sd,MultipliedDeviceTest_CountAllAutomaticallyCreatedResources)84 TEST(sd, MultipliedDeviceTest_CountAllAutomaticallyCreatedResources)
85 {
86   InitGlobals();
87   std::string path_to_config =
88       RELATIVE_PROJECT_SOURCE_DIR "/configs/stored_multiplied_device/";
89 
90   PConfigParser my_config(InitSdConfig(path_to_config.c_str(), M_INFO));
91   storagedaemon::my_config = my_config.get();
92 
93   ASSERT_TRUE(my_config->ParseConfig());
94   auto count = CountAllDeviceResources(*my_config);
95 
96   /* configurable using Device config for "AnotherMultipliedDeviceResource" */
97   int amount_to_check = 103;
98   EXPECT_EQ(count, amount_to_check);
99 }
100 
GetDeviceResourceByName(ConfigurationParser & my_config,const char * name)101 DeviceResource* GetDeviceResourceByName(ConfigurationParser& my_config,
102                                         const char* name)
103 {
104   BareosResource* p = my_config.GetResWithName(R_DEVICE, name, false);
105   return dynamic_cast<DeviceResource*>(p);
106 }
107 
CheckNamesOfConfiguredDeviceResources_1(ConfigurationParser & my_config)108 static uint32_t CheckNamesOfConfiguredDeviceResources_1(
109     ConfigurationParser& my_config)
110 {
111   uint32_t count_str_ok = 0;
112   uint32_t count_devices = 0;
113 
114   DeviceResource* source_device =
115       GetDeviceResourceByName(my_config, "MultipliedDeviceResource0001");
116   if (!source_device) { return 0; }
117 
118   /* find all matching multiplied-devices, this includes the source device */
119   BareosResource* p = nullptr;
120   while ((p = my_config.GetNextRes(R_DEVICE, p))) {
121     DeviceResource* device = dynamic_cast<DeviceResource*>(p);
122     if (device->multiplied_device_resource == source_device) {
123       const char* name = nullptr;
124       ++count_devices;
125       switch (count_devices) {
126         case 1:
127           name = "MultipliedDeviceResource0001";
128           break;
129         case 2:
130           name = "MultipliedDeviceResource0002";
131           break;
132         case 3:
133           name = "MultipliedDeviceResource0003";
134           break;
135         default:
136           return 0;
137       } /* switch (count_devices) */
138       std::string name_of_device(device->resource_name_);
139       std::string name_to_compare(name ? name : "???");
140       if (name_of_device == name_to_compare) { ++count_str_ok; }
141     } /* if (device->multiplied_device_resource) */
142   }   /* while GetNextRes */
143   return count_str_ok;
144 }
145 
TEST(sd,MultipliedDeviceTest_CheckNames_1)146 TEST(sd, MultipliedDeviceTest_CheckNames_1)
147 {
148   InitGlobals();
149   std::string path_to_config =
150       RELATIVE_PROJECT_SOURCE_DIR "/configs/stored_multiplied_device/";
151 
152   PConfigParser my_config(InitSdConfig(path_to_config.c_str(), M_INFO));
153   storagedaemon::my_config = my_config.get();
154 
155   ASSERT_TRUE(my_config->ParseConfig());
156 
157   auto count = CheckNamesOfConfiguredDeviceResources_1(*my_config);
158 
159   EXPECT_EQ(count, 3);
160 }
161 
CheckNamesOfConfiguredDeviceResources_2(ConfigurationParser & my_config)162 static uint32_t CheckNamesOfConfiguredDeviceResources_2(
163     ConfigurationParser& my_config)
164 {
165   uint32_t count_str_ok = 0;
166   uint32_t count_devices = 0;
167 
168   DeviceResource* source_device =
169       GetDeviceResourceByName(my_config, "AnotherMultipliedDeviceResource0001");
170   if (!source_device) { return 0; }
171 
172   BareosResource* p = nullptr;
173   while ((p = my_config.GetNextRes(R_DEVICE, p))) {
174     DeviceResource* device = dynamic_cast<DeviceResource*>(p);
175     if (device->multiplied_device_resource == source_device) {
176       const char* name = nullptr;
177       ++count_devices;
178       switch (count_devices) {
179         case 1:
180           name = "AnotherMultipliedDeviceResource0001";
181           break;
182         case 2:
183           name = "AnotherMultipliedDeviceResource0002";
184           break;
185         case 3:
186           name = "AnotherMultipliedDeviceResource0003";
187           break;
188         /* configurable using Device config for
189          * "AnotherMultipliedDeviceResource" */
190         case 9999:
191           name = "AnotherMultipliedDeviceResource9999";
192           break;
193         default:
194           if (count_devices < 10000) {
195             ++count_str_ok;
196             continue;
197           } else {
198             return 0;
199           }
200       } /* switch (count_devices) */
201       std::string name_of_device(device->resource_name_);
202       std::string name_to_compare(name ? name : "???");
203       if (name_of_device == name_to_compare) { ++count_str_ok; }
204     } /* if (device->multiplied_device_resource) */
205   }   /* while GetNextRes */
206   return count_str_ok;
207 }
208 
TEST(sd,MultipliedDeviceTest_CheckNames_2)209 TEST(sd, MultipliedDeviceTest_CheckNames_2)
210 {
211   InitGlobals();
212   std::string path_to_config =
213       RELATIVE_PROJECT_SOURCE_DIR "/configs/stored_multiplied_device/";
214 
215   PConfigParser my_config(InitSdConfig(path_to_config.c_str(), M_INFO));
216   storagedaemon::my_config = my_config.get();
217 
218   ASSERT_TRUE(my_config->ParseConfig());
219 
220   auto count = CheckNamesOfConfiguredDeviceResources_2(*my_config);
221 
222   EXPECT_EQ(count, 100);
223 }
224 
CheckAutochangerInAllDevices(ConfigurationParser & my_config)225 static uint32_t CheckAutochangerInAllDevices(ConfigurationParser& my_config)
226 {
227   std::map<std::string, std::string> names = {
228       {"MultipliedDeviceResource0001", "virtual-multiplied-device-autochanger"},
229       {"MultipliedDeviceResource0002", "virtual-multiplied-device-autochanger"},
230       {"MultipliedDeviceResource0003", "virtual-multiplied-device-autochanger"},
231       {"AnotherMultipliedDeviceResource0001",
232        "another-virtual-multiplied-device-autochanger"},
233       {"AnotherMultipliedDeviceResource0002",
234        "another-virtual-multiplied-device-autochanger"},
235       {"AnotherMultipliedDeviceResource0100",
236        "another-virtual-multiplied-device-autochanger"}};
237 
238   uint32_t count_str_ok = 0;
239   BareosResource* p = nullptr;
240 
241   while ((p = my_config.GetNextRes(R_DEVICE, p))) {
242     DeviceResource* device = dynamic_cast<DeviceResource*>(p);
243     if (device && device->multiplied_device_resource) {
244       if (device->changer_res && device->changer_res->resource_name_) {
245         std::string changer_name(device->changer_res->resource_name_);
246         if (names.find(device->resource_name_) != names.end()) {
247           if (names.at(device->resource_name_) == changer_name) {
248             ++count_str_ok;
249           }
250         }
251       }
252     }
253   }
254   return count_str_ok;
255 }
256 
TEST(sd,MultipliedDeviceTest_CheckNameOfAutomaticallyAttachedAutochanger)257 TEST(sd, MultipliedDeviceTest_CheckNameOfAutomaticallyAttachedAutochanger)
258 {
259   InitGlobals();
260   std::string path_to_config =
261       RELATIVE_PROJECT_SOURCE_DIR "/configs/stored_multiplied_device/";
262 
263   PConfigParser my_config(InitSdConfig(path_to_config.c_str(), M_INFO));
264   storagedaemon::my_config = my_config.get();
265 
266   ASSERT_TRUE(my_config->ParseConfig());
267 
268   auto count = CheckAutochangerInAllDevices(*my_config);
269 
270   EXPECT_EQ(count, 6);
271 }
272 
CheckSomeDevicesInAutochanger(ConfigurationParser & my_config)273 static uint32_t CheckSomeDevicesInAutochanger(ConfigurationParser& my_config)
274 {
275   uint32_t count_str_ok = 0;
276   BareosResource* p = nullptr;
277 
278   std::set<std::string> names = {{"MultipliedDeviceResource0001"},
279                                  {"MultipliedDeviceResource0002"},
280                                  {"MultipliedDeviceResource0003"}};
281 
282   while ((p = my_config.GetNextRes(R_AUTOCHANGER, p))) {
283     AutochangerResource* autochanger = dynamic_cast<AutochangerResource*>(p);
284     if (autochanger) {
285       std::string autochanger_name(autochanger->resource_name_);
286       std::string autochanger_name_test(
287           "virtual-multiplied-device-autochanger");
288       if (autochanger_name == autochanger_name_test) {
289         DeviceResource* device = nullptr;
290         foreach_alist (device, autochanger->device) {
291           std::string device_name(device->resource_name_);
292           if (names.find(device_name) != names.end()) { ++count_str_ok; }
293         }
294       }
295     }
296   }
297   return count_str_ok;
298 }
299 
TEST(sd,MultipliedDeviceTest_CheckNameOfDevicesAutomaticallyAttachedToAutochanger)300 TEST(sd,
301      MultipliedDeviceTest_CheckNameOfDevicesAutomaticallyAttachedToAutochanger)
302 {
303   InitGlobals();
304   std::string path_to_config =
305       RELATIVE_PROJECT_SOURCE_DIR "/configs/stored_multiplied_device/";
306 
307   PConfigParser my_config(InitSdConfig(path_to_config.c_str(), M_INFO));
308   storagedaemon::my_config = my_config.get();
309 
310   ASSERT_TRUE(my_config->ParseConfig());
311 
312   auto count = CheckSomeDevicesInAutochanger(*my_config);
313 
314   EXPECT_EQ(count, 3);
315 }
316 
TEST(sd,MultipliedDeviceTest_CheckPointerReferenceOfOriginalDevice)317 TEST(sd, MultipliedDeviceTest_CheckPointerReferenceOfOriginalDevice)
318 {
319   InitGlobals();
320   std::string path_to_config =
321       RELATIVE_PROJECT_SOURCE_DIR "/configs/stored_multiplied_device/";
322 
323   PConfigParser my_config(InitSdConfig(path_to_config.c_str(), M_INFO));
324   storagedaemon::my_config = my_config.get();
325 
326   ASSERT_TRUE(my_config->ParseConfig());
327 
328   BareosResource* p;
329   p = my_config->GetResWithName(R_DEVICE, "MultipliedDeviceResource0001");
330   ASSERT_TRUE(p);
331   DeviceResource* original_device = dynamic_cast<DeviceResource*>(p);
332   EXPECT_EQ(original_device, original_device->multiplied_device_resource);
333 }
334 
TEST(sd,MultipliedDeviceTest_CheckPointerReferenceOfCopiedDevice)335 TEST(sd, MultipliedDeviceTest_CheckPointerReferenceOfCopiedDevice)
336 {
337   InitGlobals();
338   std::string path_to_config =
339       RELATIVE_PROJECT_SOURCE_DIR "/configs/stored_multiplied_device/";
340 
341   PConfigParser my_config(InitSdConfig(path_to_config.c_str(), M_INFO));
342   storagedaemon::my_config = my_config.get();
343 
344   ASSERT_TRUE(my_config->ParseConfig());
345 
346   BareosResource* p;
347   p = my_config->GetResWithName(R_DEVICE, "MultipliedDeviceResource0001");
348   ASSERT_TRUE(p);
349   DeviceResource* original_device = dynamic_cast<DeviceResource*>(p);
350   p = my_config->GetResWithName(R_DEVICE, "MultipliedDeviceResource0002");
351   ASSERT_TRUE(p);
352   DeviceResource* multiplied_device = dynamic_cast<DeviceResource*>(p);
353   EXPECT_EQ(original_device, multiplied_device->multiplied_device_resource);
354 }
355