1 /*
2  * Copyright (C) 2020-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #pragma once
9 #include "shared/source/helpers/string.h"
10 
11 #include "level_zero/core/test/unit_tests/mock.h"
12 #include "level_zero/tools/source/sysman/power/linux/os_power_imp.h"
13 #include "level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h"
14 
15 #include "sysman/linux/pmt/pmt.h"
16 #include "sysman/power/power_imp.h"
17 #include "sysman/sysman_imp.h"
18 
19 extern bool sysmanUltsEnable;
20 
21 using ::testing::DoDefault;
22 using ::testing::Matcher;
23 using ::testing::Return;
24 
25 namespace L0 {
26 namespace ult {
27 constexpr uint64_t setEnergyCounter = (83456u * 1048576u);
28 constexpr uint64_t offset = 0x400;
29 const std::string deviceName("device");
30 const std::string baseTelemSysFS("/sys/class/intel_pmt");
31 const std::string hwmonDir("device/hwmon");
32 const std::string i915HwmonDir("device/hwmon/hwmon2");
33 const std::string nonI915HwmonDir("device/hwmon/hwmon1");
34 const std::vector<std::string> listOfMockedHwmonDirs = {"hwmon0", "hwmon1", "hwmon2", "hwmon3", "hwmon4"};
35 const std::string sustainedPowerLimitEnabled("power1_max_enable");
36 const std::string sustainedPowerLimit("power1_max");
37 const std::string sustainedPowerLimitInterval("power1_max_interval");
38 const std::string burstPowerLimitEnabled("power1_cap_enable");
39 const std::string burstPowerLimit("power1_cap");
40 const std::string energyCounterNode("energy1_input");
41 const std::string defaultPowerLimit("power_default_limit");
42 const std::string minPowerLimit("power_min_limit");
43 const std::string maxPowerLimit("power_max_limit");
44 constexpr uint64_t expectedEnergyCounter = 123456785u;
45 constexpr uint32_t mockDefaultPowerLimitVal = 300000000;
46 constexpr uint32_t mockMaxPowerLimitVal = 490000000;
47 constexpr uint32_t mockMinPowerLimitVal = 10;
48 const std::map<std::string, uint64_t> deviceKeyOffsetMapPower = {
49     {"PACKAGE_ENERGY", 0x400},
50     {"COMPUTE_TEMPERATURES", 0x68},
51     {"SOC_TEMPERATURES", 0x60},
52     {"CORE_TEMPERATURES", 0x6c}};
53 
54 class PowerSysfsAccess : public SysfsAccess {};
55 
56 template <>
57 struct Mock<PowerSysfsAccess> : public PowerSysfsAccess {
58 
59     ze_result_t getValStringHelper(const std::string file, std::string &val);
60     ze_result_t getValString(const std::string file, std::string &val) {
61         ze_result_t result = ZE_RESULT_ERROR_UNKNOWN;
62         if (file.compare(i915HwmonDir + "/" + "name") == 0) {
63             val = "i915";
64             result = ZE_RESULT_SUCCESS;
65         } else if (file.compare(nonI915HwmonDir + "/" + "name") == 0) {
66             result = ZE_RESULT_ERROR_NOT_AVAILABLE;
67         } else {
68             val = "garbageI915";
69             result = ZE_RESULT_SUCCESS;
70         }
71         return result;
72     }
73 
74     uint64_t sustainedPowerLimitEnabledVal = 1u;
75     uint64_t sustainedPowerLimitVal = 0;
76     uint64_t sustainedPowerLimitIntervalVal = 0;
77     uint64_t burstPowerLimitEnabledVal = 0;
78     uint64_t burstPowerLimitVal = 0;
79     uint64_t energyCounterNodeVal = expectedEnergyCounter;
80 
81     ze_result_t getValUnsignedLongReturnErrorForBurstPowerLimit(const std::string file, uint64_t &val) {
82         if (file.compare(i915HwmonDir + "/" + burstPowerLimitEnabled) == 0) {
83             val = burstPowerLimitEnabledVal;
84         }
85         if (file.compare(i915HwmonDir + "/" + burstPowerLimit) == 0) {
86 
87             return ZE_RESULT_ERROR_NOT_AVAILABLE;
88         }
89         return ZE_RESULT_SUCCESS;
90     }
91 
92     ze_result_t getValUnsignedLongReturnErrorForBurstPowerLimitEnabled(const std::string file, uint64_t &val) {
93         if (file.compare(i915HwmonDir + "/" + burstPowerLimitEnabled) == 0) {
94             return ZE_RESULT_ERROR_NOT_AVAILABLE; // mocking the condition when user passes nullptr for sustained and peak power in zesPowerGetLimit and burst power file is absent
95         }
96         return ZE_RESULT_SUCCESS;
97     }
98 
99     ze_result_t getValUnsignedLongReturnErrorForSustainedPowerLimitEnabled(const std::string file, uint64_t &val) {
100         if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitEnabled) == 0) {
101             return ZE_RESULT_ERROR_NOT_AVAILABLE; // mocking the condition when user passes nullptr for burst and peak power in zesPowerGetLimit and sustained power file is absent
102         }
103         return ZE_RESULT_SUCCESS;
104     }
105 
106     ze_result_t getValUnsignedLongReturnsPowerLimitEnabledAsDisabled(const std::string file, uint64_t &val) {
107         if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitEnabled) == 0) {
108             val = 0;
109             return ZE_RESULT_SUCCESS;
110         } else if (file.compare(i915HwmonDir + "/" + burstPowerLimitEnabled) == 0) {
111             val = 0;
112             return ZE_RESULT_SUCCESS;
113         }
114         return ZE_RESULT_SUCCESS;
115     }
116 
117     ze_result_t getValUnsignedLongReturnErrorForSustainedPower(const std::string file, uint64_t &val) {
118         if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitEnabled) == 0) {
119             val = 1;
120         } else if (file.compare(i915HwmonDir + "/" + sustainedPowerLimit) == 0) {
121             return ZE_RESULT_ERROR_NOT_AVAILABLE;
122         }
123         return ZE_RESULT_SUCCESS;
124     }
125 
126     ze_result_t getValUnsignedLongReturnErrorForSustainedPowerInterval(const std::string file, uint64_t &val) {
127         if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitEnabled) == 0) {
128             val = 1;
129         } else if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitInterval) == 0) {
130             return ZE_RESULT_ERROR_NOT_AVAILABLE;
131         }
132         return ZE_RESULT_SUCCESS;
133     }
134 
135     ze_result_t setValUnsignedLongReturnErrorForBurstPowerLimit(const std::string file, const int val) {
136         if (file.compare(i915HwmonDir + "/" + burstPowerLimit) == 0) {
137             return ZE_RESULT_ERROR_NOT_AVAILABLE;
138         }
139         return ZE_RESULT_SUCCESS;
140     }
141 
142     ze_result_t setValUnsignedLongReturnErrorForBurstPowerLimitEnabled(const std::string file, const int val) {
143         if (file.compare(i915HwmonDir + "/" + burstPowerLimitEnabled) == 0) {
144             return ZE_RESULT_ERROR_NOT_AVAILABLE;
145         }
146         return ZE_RESULT_SUCCESS;
147     }
148 
149     ze_result_t setValUnsignedLongReturnErrorForSustainedPowerLimitEnabled(const std::string file, const int val) {
150         if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitEnabled) == 0) {
151             return ZE_RESULT_ERROR_NOT_AVAILABLE;
152         }
153         return ZE_RESULT_SUCCESS;
154     }
155 
156     ze_result_t setValUnsignedLongReturnInsufficientForSustainedPowerLimitEnabled(const std::string file, const int val) {
157         if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitEnabled) == 0) {
158             return ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS;
159         }
160         return ZE_RESULT_SUCCESS;
161     }
162 
163     ze_result_t setValReturnErrorForSustainedPower(const std::string file, const int val) {
164         if (file.compare(i915HwmonDir + "/" + sustainedPowerLimit) == 0) {
165             return ZE_RESULT_ERROR_NOT_AVAILABLE;
166         }
167         return ZE_RESULT_SUCCESS;
168     }
169 
170     ze_result_t setValReturnErrorForSustainedPowerInterval(const std::string file, const int val) {
171         if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitInterval) == 0) {
172             return ZE_RESULT_ERROR_NOT_AVAILABLE;
173         }
174         return ZE_RESULT_SUCCESS;
175     }
176 
177     ze_result_t getValUnsignedLongHelper(const std::string file, uint64_t &val);
178     ze_result_t getValUnsignedLong(const std::string file, uint64_t &val) {
179         ze_result_t result = ZE_RESULT_SUCCESS;
180         if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitEnabled) == 0) {
181             val = sustainedPowerLimitEnabledVal;
182         } else if (file.compare(i915HwmonDir + "/" + sustainedPowerLimit) == 0) {
183             val = sustainedPowerLimitVal;
184         } else if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitInterval) == 0) {
185             val = sustainedPowerLimitIntervalVal;
186         } else if (file.compare(i915HwmonDir + "/" + burstPowerLimitEnabled) == 0) {
187             val = burstPowerLimitEnabledVal;
188         } else if (file.compare(i915HwmonDir + "/" + burstPowerLimit) == 0) {
189             val = burstPowerLimitVal;
190         } else if (file.compare(i915HwmonDir + "/" + energyCounterNode) == 0) {
191             val = energyCounterNodeVal;
192         } else {
193             result = ZE_RESULT_ERROR_NOT_AVAILABLE;
194         }
195 
196         return result;
197     }
198 
199     ze_result_t getValUnsignedInt(const std::string file, uint32_t &val) {
200         ze_result_t result = ZE_RESULT_SUCCESS;
201         if (file.compare(i915HwmonDir + "/" + defaultPowerLimit) == 0) {
202             val = mockDefaultPowerLimitVal;
203         } else if (file.compare(i915HwmonDir + "/" + maxPowerLimit) == 0) {
204             val = mockMaxPowerLimitVal;
205         } else if (file.compare(i915HwmonDir + "/" + minPowerLimit) == 0) {
206             val = mockMinPowerLimitVal;
207         } else {
208             result = ZE_RESULT_ERROR_NOT_AVAILABLE;
209         }
210         return result;
211     }
212 
213     ze_result_t getValUnsignedIntMax(const std::string file, uint32_t &val) {
214         ze_result_t result = ZE_RESULT_SUCCESS;
215         if (file.compare(i915HwmonDir + "/" + maxPowerLimit) == 0) {
216             val = std::numeric_limits<uint32_t>::max();
217         } else {
218             result = ZE_RESULT_ERROR_NOT_AVAILABLE;
219         }
220         return result;
221     }
222 
223     ze_result_t setVal(const std::string file, const int val) {
224         ze_result_t result = ZE_RESULT_SUCCESS;
225         if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitEnabled) == 0) {
226             sustainedPowerLimitEnabledVal = static_cast<uint64_t>(val);
227         } else if (file.compare(i915HwmonDir + "/" + sustainedPowerLimit) == 0) {
228             sustainedPowerLimitVal = static_cast<uint64_t>(val);
229         } else if (file.compare(i915HwmonDir + "/" + sustainedPowerLimitInterval) == 0) {
230             sustainedPowerLimitIntervalVal = static_cast<uint64_t>(val);
231         } else if (file.compare(i915HwmonDir + "/" + burstPowerLimitEnabled) == 0) {
232             burstPowerLimitEnabledVal = static_cast<uint64_t>(val);
233         } else if (file.compare(i915HwmonDir + "/" + burstPowerLimit) == 0) {
234             burstPowerLimitVal = static_cast<uint64_t>(val);
235         } else {
236             result = ZE_RESULT_ERROR_NOT_AVAILABLE;
237         }
238 
239         return result;
240     }
241     ze_result_t getscanDirEntries(const std::string file, std::vector<std::string> &listOfEntries) {
242         if (file.compare(hwmonDir) == 0) {
243             listOfEntries = listOfMockedHwmonDirs;
244             return ZE_RESULT_SUCCESS;
245         }
246         return ZE_RESULT_ERROR_NOT_AVAILABLE;
247     }
248 
249     Mock<PowerSysfsAccess>() = default;
250 
251     MOCK_METHOD(ze_result_t, read, (const std::string file, uint64_t &val), (override));
252     MOCK_METHOD(ze_result_t, read, (const std::string file, std::string &val), (override));
253     MOCK_METHOD(ze_result_t, read, (const std::string file, uint32_t &val), (override));
254     MOCK_METHOD(ze_result_t, write, (const std::string file, const int val), (override));
255     MOCK_METHOD(ze_result_t, scanDirEntries, (const std::string file, std::vector<std::string> &listOfEntries), (override));
256 };
257 
258 class PowerPmt : public PlatformMonitoringTech {
259   public:
260     PowerPmt(FsAccess *pFsAccess, ze_bool_t onSubdevice, uint32_t subdeviceId) : PlatformMonitoringTech(pFsAccess, onSubdevice, subdeviceId) {}
261     using PlatformMonitoringTech::closeFunction;
262     using PlatformMonitoringTech::keyOffsetMap;
263     using PlatformMonitoringTech::openFunction;
264     using PlatformMonitoringTech::preadFunction;
265     using PlatformMonitoringTech::telemetryDeviceEntry;
266 };
267 
268 template <>
269 struct Mock<PowerPmt> : public PowerPmt {
270     ~Mock() override {
271         rootDeviceTelemNodeIndex = 0;
272     }
273 
274     Mock<PowerPmt>(FsAccess *pFsAccess, ze_bool_t onSubdevice, uint32_t subdeviceId) : PowerPmt(pFsAccess, onSubdevice, subdeviceId) {}
275 
276     void mockedInit(FsAccess *pFsAccess) {
277         std::string rootPciPathOfGpuDevice = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0";
278         if (ZE_RESULT_SUCCESS != PlatformMonitoringTech::enumerateRootTelemIndex(pFsAccess, rootPciPathOfGpuDevice)) {
279             return;
280         }
281 
282         telemetryDeviceEntry = "/sys/class/intel_pmt/telem2/telem";
283     }
284 };
285 
286 class PowerFsAccess : public FsAccess {};
287 
288 template <>
289 struct Mock<PowerFsAccess> : public PowerFsAccess {
290     ze_result_t listDirectorySuccess(const std::string directory, std::vector<std::string> &listOfTelemNodes) {
291         if (directory.compare(baseTelemSysFS) == 0) {
292             listOfTelemNodes.push_back("telem1");
293             listOfTelemNodes.push_back("telem2");
294             listOfTelemNodes.push_back("telem3");
295             listOfTelemNodes.push_back("telem4");
296             listOfTelemNodes.push_back("telem5");
297             return ZE_RESULT_SUCCESS;
298         }
299         return ZE_RESULT_ERROR_NOT_AVAILABLE;
300     }
301 
302     ze_result_t listDirectoryFailure(const std::string directory, std::vector<std::string> &events) {
303         return ZE_RESULT_ERROR_NOT_AVAILABLE;
304     }
305 
306     ze_result_t getRealPathSuccess(const std::string path, std::string &buf) {
307         if (path.compare("/sys/class/intel_pmt/telem1") == 0) {
308             buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:86:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry.1.auto/intel_pmt/telem1";
309         } else if (path.compare("/sys/class/intel_pmt/telem2") == 0) {
310             buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:86:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry.1.auto/intel_pmt/telem2";
311         } else if (path.compare("/sys/class/intel_pmt/telem3") == 0) {
312             buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry.1.auto/intel_pmt/telem3";
313         } else if (path.compare("/sys/class/intel_pmt/telem4") == 0) {
314             buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry.1.auto/intel_pmt/telem4";
315         } else if (path.compare("/sys/class/intel_pmt/telem5") == 0) {
316             buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry.1.auto/intel_pmt/telem5";
317         } else {
318             return ZE_RESULT_ERROR_NOT_AVAILABLE;
319         }
320 
321         return ZE_RESULT_SUCCESS;
322     }
323 
324     ze_result_t getRealPathFailure(const std::string path, std::string &buf) {
325         return ZE_RESULT_ERROR_NOT_AVAILABLE;
326     }
327 
328     MOCK_METHOD(ze_result_t, listDirectory, (const std::string path, std::vector<std::string> &list), (override));
329     MOCK_METHOD(ze_result_t, getRealPath, (const std::string path, std::string &buf), (override));
330     Mock<PowerFsAccess>() = default;
331 };
332 
333 class PublicLinuxPowerImp : public L0::LinuxPowerImp {
334   public:
335     PublicLinuxPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) : LinuxPowerImp(pOsSysman, onSubdevice, subdeviceId) {}
336     using LinuxPowerImp::pPmt;
337 };
338 
339 class SysmanDevicePowerFixture : public SysmanDeviceFixture {
340   protected:
341     std::unique_ptr<PublicLinuxPowerImp> pPublicLinuxPowerImp;
342     std::unique_ptr<Mock<PowerPmt>> pPmt;
343     std::unique_ptr<Mock<PowerFsAccess>> pFsAccess;
344     std::unique_ptr<Mock<PowerSysfsAccess>> pSysfsAccess;
345     SysfsAccess *pSysfsAccessOld = nullptr;
346     FsAccess *pFsAccessOriginal = nullptr;
347     OsPower *pOsPowerOriginal = nullptr;
348     std::vector<ze_device_handle_t> deviceHandles;
349     void SetUp() override {
350         if (!sysmanUltsEnable) {
351             GTEST_SKIP();
352         }
353         SysmanDeviceFixture::SetUp();
354         pFsAccess = std::make_unique<NiceMock<Mock<PowerFsAccess>>>();
355         pFsAccessOriginal = pLinuxSysmanImp->pFsAccess;
356         pLinuxSysmanImp->pFsAccess = pFsAccess.get();
357         pSysfsAccessOld = pLinuxSysmanImp->pSysfsAccess;
358         pSysfsAccess = std::make_unique<NiceMock<Mock<PowerSysfsAccess>>>();
359         pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get();
360         ON_CALL(*pFsAccess.get(), listDirectory(_, _))
361             .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<PowerFsAccess>::listDirectorySuccess));
362         ON_CALL(*pFsAccess.get(), getRealPath(_, _))
363             .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<PowerFsAccess>::getRealPathSuccess));
364         ON_CALL(*pSysfsAccess.get(), read(_, Matcher<std::string &>(_)))
365             .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<PowerSysfsAccess>::getValString));
366         ON_CALL(*pSysfsAccess.get(), read(_, Matcher<uint64_t &>(_)))
367             .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<PowerSysfsAccess>::getValUnsignedLong));
368         ON_CALL(*pSysfsAccess.get(), read(_, Matcher<uint32_t &>(_)))
369             .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<PowerSysfsAccess>::getValUnsignedInt));
370         ON_CALL(*pSysfsAccess.get(), write(_, _))
371             .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<PowerSysfsAccess>::setVal));
372         ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _))
373             .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<PowerSysfsAccess>::getscanDirEntries));
374         uint32_t subDeviceCount = 0;
375         Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, nullptr);
376         if (subDeviceCount == 0) {
377             deviceHandles.resize(1, device->toHandle());
378         } else {
379             deviceHandles.resize(subDeviceCount, nullptr);
380             Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, deviceHandles.data());
381         }
382 
383         for (auto &deviceHandle : deviceHandles) {
384             ze_device_properties_t deviceProperties = {ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES};
385             Device::fromHandle(deviceHandle)->getProperties(&deviceProperties);
386             auto pPmt = new NiceMock<Mock<PowerPmt>>(pFsAccess.get(), deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE,
387                                                      deviceProperties.subdeviceId);
388             pPmt->mockedInit(pFsAccess.get());
389             pPmt->keyOffsetMap = deviceKeyOffsetMapPower;
390             pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject.emplace(deviceProperties.subdeviceId, pPmt);
391         }
392 
393         pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles, device->toHandle());
394     }
395     void TearDown() override {
396         if (!sysmanUltsEnable) {
397             GTEST_SKIP();
398         }
399         SysmanDeviceFixture::TearDown();
400         pLinuxSysmanImp->pFsAccess = pFsAccessOriginal;
401         pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOld;
402     }
403 
404     std::vector<zes_pwr_handle_t> getPowerHandles(uint32_t count) {
405         std::vector<zes_pwr_handle_t> handles(count, nullptr);
406         EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS);
407         return handles;
408     }
409 };
410 
411 class SysmanDevicePowerMultiDeviceFixture : public SysmanMultiDeviceFixture {
412   protected:
413     std::unique_ptr<PublicLinuxPowerImp> pPublicLinuxPowerImp;
414     std::unique_ptr<Mock<PowerPmt>> pPmt;
415     std::unique_ptr<Mock<PowerFsAccess>> pFsAccess;
416     std::unique_ptr<Mock<PowerSysfsAccess>> pSysfsAccess;
417     SysfsAccess *pSysfsAccessOld = nullptr;
418     FsAccess *pFsAccessOriginal = nullptr;
419     OsPower *pOsPowerOriginal = nullptr;
420     std::vector<ze_device_handle_t> deviceHandles;
421     void SetUp() override {
422         if (!sysmanUltsEnable) {
423             GTEST_SKIP();
424         }
425         SysmanMultiDeviceFixture::SetUp();
426         pFsAccess = std::make_unique<NiceMock<Mock<PowerFsAccess>>>();
427         pFsAccessOriginal = pLinuxSysmanImp->pFsAccess;
428         pLinuxSysmanImp->pFsAccess = pFsAccess.get();
429         pSysfsAccessOld = pLinuxSysmanImp->pSysfsAccess;
430         pSysfsAccess = std::make_unique<NiceMock<Mock<PowerSysfsAccess>>>();
431         pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get();
432         ON_CALL(*pFsAccess.get(), listDirectory(_, _))
433             .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<PowerFsAccess>::listDirectorySuccess));
434         ON_CALL(*pFsAccess.get(), getRealPath(_, _))
435             .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<PowerFsAccess>::getRealPathSuccess));
436         ON_CALL(*pSysfsAccess.get(), read(_, Matcher<std::string &>(_)))
437             .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<PowerSysfsAccess>::getValString));
438         ON_CALL(*pSysfsAccess.get(), read(_, Matcher<uint64_t &>(_)))
439             .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<PowerSysfsAccess>::getValUnsignedLong));
440         ON_CALL(*pSysfsAccess.get(), read(_, Matcher<uint32_t &>(_)))
441             .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<PowerSysfsAccess>::getValUnsignedInt));
442         ON_CALL(*pSysfsAccess.get(), write(_, _))
443             .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<PowerSysfsAccess>::setVal));
444         ON_CALL(*pSysfsAccess.get(), scanDirEntries(_, _))
445             .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<PowerSysfsAccess>::getscanDirEntries));
446         uint32_t subDeviceCount = 0;
447         Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, nullptr);
448         if (subDeviceCount == 0) {
449             deviceHandles.resize(1, device->toHandle());
450         } else {
451             deviceHandles.resize(subDeviceCount, nullptr);
452             Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, deviceHandles.data());
453         }
454 
455         for (auto &deviceHandle : deviceHandles) {
456             ze_device_properties_t deviceProperties = {ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES};
457             Device::fromHandle(deviceHandle)->getProperties(&deviceProperties);
458             auto pPmt = new NiceMock<Mock<PowerPmt>>(pFsAccess.get(), deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE,
459                                                      deviceProperties.subdeviceId);
460             pPmt->mockedInit(pFsAccess.get());
461             pPmt->keyOffsetMap = deviceKeyOffsetMapPower;
462             pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject.emplace(deviceProperties.subdeviceId, pPmt);
463         }
464 
465         pSysmanDeviceImp->pPowerHandleContext->init(deviceHandles, device->toHandle());
466     }
467     void TearDown() override {
468         if (!sysmanUltsEnable) {
469             GTEST_SKIP();
470         }
471         SysmanMultiDeviceFixture::TearDown();
472         pLinuxSysmanImp->pFsAccess = pFsAccessOriginal;
473         pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOld;
474     }
475 
476     std::vector<zes_pwr_handle_t> getPowerHandles(uint32_t count) {
477         std::vector<zes_pwr_handle_t> handles(count, nullptr);
478         EXPECT_EQ(zesDeviceEnumPowerDomains(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS);
479         return handles;
480     }
481 };
482 
483 } // namespace ult
484 } // namespace L0
485