xref: /openbmc/phosphor-ipmi-flash/tools/test/tools_pci_unittest.cpp (revision c1a30c047edae2201cd5038d5548741bef79821b)
1 /*
2  * Copyright 2020 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "internal_sys_mock.hpp"
18 #include "pci.hpp"
19 #include "pciaccess_mock.hpp"
20 #include "tool_errors.hpp"
21 
22 #include <stdplus/raw.hpp>
23 
24 #include <algorithm>
25 #include <cstdlib>
26 #include <string>
27 #include <vector>
28 
29 #include <gtest/gtest.h>
30 
31 namespace host_tool
32 {
33 namespace
34 {
35 
36 using namespace std::string_literals;
37 
38 using ::testing::Assign;
39 using ::testing::ContainerEq;
40 using ::testing::DoAll;
41 using ::testing::Each;
42 using ::testing::Eq;
43 using ::testing::InSequence;
44 using ::testing::NotNull;
45 using ::testing::Return;
46 using ::testing::SetArgPointee;
47 
48 // TODO: switch to ConainerEq for C++20
49 MATCHER_P(SpanEq, s, "")
50 {
51     return arg.size() == s.size() && !memcmp(arg.data(), s.data(), s.size());
52 }
53 
54 MATCHER_P(PciIdMatch, m, "")
55 {
56     return (arg->vendor_id == m->vendor_id && arg->device_id == m->device_id &&
57             arg->subvendor_id == m->subvendor_id &&
58             arg->subdevice_id == m->subdevice_id);
59 }
60 
61 pci_device_iterator* mockIter = reinterpret_cast<pci_device_iterator*>(0x42);
62 
63 constexpr pciaddr_t mockBaseAddr = 0xdeadbeef;
64 constexpr pciaddr_t mockRegionSize = 0x20000;
65 
66 class Device
67 {
68   public:
69     virtual const struct pci_id_match* getMatch() const = 0;
70     virtual struct pci_device getDevice() const = 0;
71     virtual void expectSetup(PciAccessMock& pciMock,
72                              const struct pci_device& dev) const {};
73     virtual std::unique_ptr<PciBridgeIntf> getBridge(PciAccess* pci) const = 0;
74     virtual std::string getName() const = 0;
75 };
76 
77 class NuvotonDevice : public Device
78 {
79   public:
80     const struct pci_id_match* getMatch() const override
81     {
82         return &match;
83     }
84 
85     struct pci_device getDevice() const override
86     {
87         struct pci_device dev;
88 
89         dev.vendor_id = match.vendor_id;
90         dev.device_id = match.device_id;
91 
92         dev.regions[0].is_IO = false;
93         dev.regions[0].base_addr = mockBaseAddr;
94         dev.regions[0].size = mockRegionSize;
95 
96         return dev;
97     }
98 
99     void expectSetup(PciAccessMock& pciMock,
100                      const struct pci_device& dev) const override
101     {
102         static constexpr std::uint8_t defaultVal = 0x40;
103 
104         InSequence in;
105 
106         EXPECT_CALL(pciMock,
107                     pci_device_cfg_read_u8(Eq(&dev), NotNull(), config))
108             .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
109         EXPECT_CALL(pciMock, pci_device_cfg_write_u8(
110                                  Eq(&dev), defaultVal | bridgeEnabled, config))
111             .WillOnce(Return(0));
112 
113         EXPECT_CALL(pciMock,
114                     pci_device_cfg_read_u8(Eq(&dev), NotNull(), config))
115             .WillOnce(
116                 DoAll(SetArgPointee<1>(defaultVal | bridgeEnabled), Return(0)));
117         EXPECT_CALL(pciMock,
118                     pci_device_cfg_write_u8(Eq(&dev), defaultVal, config))
119             .WillOnce(Return(0));
120     }
121 
122     std::unique_ptr<PciBridgeIntf> getBridge(PciAccess* pci) const override
123     {
124         return std::make_unique<NuvotonPciBridge>(pci);
125     }
126 
127     std::string getName() const override
128     {
129         return "Nuvoton"s;
130     }
131 
132     /* Offset to the config register */
133     static constexpr int config = 0x04;
134     /* Second bit determines whether bridge is enabled */
135     static constexpr std::uint8_t bridgeEnabled = 0x02;
136 
137   private:
138     static constexpr struct pci_id_match match
139     {
140         0x1050, 0x0750, PCI_MATCH_ANY, PCI_MATCH_ANY
141     };
142 };
143 
144 class AspeedDevice : public Device
145 {
146   public:
147     const struct pci_id_match* getMatch() const override
148     {
149         return &match;
150     }
151 
152     struct pci_device getDevice() const override
153     {
154         struct pci_device dev;
155 
156         dev.vendor_id = match.vendor_id;
157         dev.device_id = match.device_id;
158 
159         dev.regions[1].is_IO = false;
160         dev.regions[1].base_addr = mockBaseAddr;
161         dev.regions[1].size = mockRegionSize;
162 
163         return dev;
164     }
165 
166     std::unique_ptr<PciBridgeIntf> getBridge(PciAccess* pci) const override
167     {
168         return std::make_unique<AspeedPciBridge>(pci);
169     }
170 
171     std::string getName() const override
172     {
173         return "Aspeed"s;
174     }
175 
176     /* Offset to the config region */
177     static constexpr int config = 0x0f000;
178     /* Lower bit determines whether bridge is enabled */
179     static constexpr std::uint8_t bridgeEnabled = 0x01;
180     /* Offset to the MMIO address configuration */
181     static constexpr int bridge = 0x0f004;
182 
183   private:
184     static constexpr struct pci_id_match match
185     {
186         0x1a03, 0x2000, PCI_MATCH_ANY, PCI_MATCH_ANY
187     };
188 };
189 
190 NuvotonDevice nuvotonDevice;
191 AspeedDevice aspeedDevice;
192 
193 class PciSetupTest : public testing::TestWithParam<Device*>
194 {};
195 
196 /* Handle device not found */
197 TEST_P(PciSetupTest, NotFound)
198 {
199     PciAccessMock pciMock;
200 
201     InSequence in;
202 
203     EXPECT_CALL(pciMock, pci_id_match_iterator_create(
204                              PciIdMatch(GetParam()->getMatch())))
205         .WillOnce(Return(mockIter));
206     EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
207         .WillOnce(Return(nullptr));
208     EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
209 
210     EXPECT_THROW(GetParam()->getBridge(&pciMock), NotFoundException);
211 }
212 
213 /* Test finding device but probe fails */
214 TEST_P(PciSetupTest, ProbeFail)
215 {
216     PciAccessMock pciMock;
217     struct pci_device dev;
218 
219     EXPECT_CALL(pciMock, pci_id_match_iterator_create(
220                              PciIdMatch(GetParam()->getMatch())))
221         .WillOnce(Return(mockIter));
222     EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
223         .WillOnce(Return(&dev))
224         .WillRepeatedly(Return(nullptr));
225 
226     EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev))).WillOnce(Return(EFAULT));
227 
228     EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
229 
230     EXPECT_THROW(GetParam()->getBridge(&pciMock), std::system_error);
231 }
232 
233 /* Test finding device but mapping fails */
234 TEST_P(PciSetupTest, MapFail)
235 {
236     PciAccessMock pciMock;
237     struct pci_device dev;
238 
239     EXPECT_CALL(pciMock, pci_id_match_iterator_create(
240                              PciIdMatch(GetParam()->getMatch())))
241         .WillOnce(Return(mockIter));
242     EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
243         .WillOnce(Return(&dev))
244         .WillRepeatedly(Return(nullptr));
245 
246     EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
247         .WillOnce(DoAll(Assign(&dev, GetParam()->getDevice()), Return(0)));
248 
249     EXPECT_CALL(pciMock,
250                 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
251                                      PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
252         .WillOnce(Return(EFAULT));
253 
254     EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
255 
256     EXPECT_THROW(GetParam()->getBridge(&pciMock), std::system_error);
257 }
258 
259 /* Test finding device but unmapping fails */
260 TEST_P(PciSetupTest, UnmapFail)
261 {
262     PciAccessMock pciMock;
263     struct pci_device dev;
264     std::vector<std::uint8_t> region(mockRegionSize);
265 
266     EXPECT_CALL(pciMock, pci_id_match_iterator_create(
267                              PciIdMatch(GetParam()->getMatch())))
268         .WillOnce(Return(mockIter));
269     EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
270         .WillOnce(Return(&dev))
271         .WillRepeatedly(Return(nullptr));
272 
273     EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
274         .WillOnce(DoAll(Assign(&dev, GetParam()->getDevice()), Return(0)));
275 
276     EXPECT_CALL(pciMock,
277                 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
278                                      PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
279         .WillOnce(DoAll(SetArgPointee<4>(region.data()), Return(0)));
280 
281     EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
282     EXPECT_CALL(pciMock, pci_device_unmap_range(Eq(&dev), Eq(region.data()),
283                                                 mockRegionSize))
284         .WillOnce(Return(EFAULT));
285 
286     GetParam()->expectSetup(pciMock, dev);
287     // This will print an error but not throw
288     GetParam()->getBridge(&pciMock);
289 }
290 
291 /* Create expectations on pciMock for finding device and mapping memory region
292  */
293 void expectSetup(PciAccessMock& pciMock, struct pci_device& dev, Device* param,
294                  std::uint8_t* region, bool deviceExpectations = true)
295 {
296     EXPECT_CALL(pciMock,
297                 pci_id_match_iterator_create(PciIdMatch(param->getMatch())))
298         .WillOnce(Return(mockIter));
299     EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
300         .WillOnce(Return(&dev))
301         .WillRepeatedly(Return(nullptr));
302 
303     EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
304         .WillOnce(DoAll(Assign(&dev, param->getDevice()), Return(0)));
305 
306     EXPECT_CALL(pciMock,
307                 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
308                                      PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
309         .WillOnce(DoAll(SetArgPointee<4>(region), Return(0)));
310 
311     EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
312     EXPECT_CALL(pciMock,
313                 pci_device_unmap_range(Eq(&dev), Eq(region), mockRegionSize))
314         .WillOnce(Return(0));
315 
316     if (deviceExpectations)
317         param->expectSetup(pciMock, dev);
318 }
319 
320 /* Test finding device and mapping memory region */
321 TEST_P(PciSetupTest, Success)
322 {
323     PciAccessMock pciMock;
324     struct pci_device dev;
325     std::vector<std::uint8_t> region(mockRegionSize);
326 
327     expectSetup(pciMock, dev, GetParam(), region.data());
328 
329     GetParam()->getBridge(&pciMock);
330 }
331 
332 INSTANTIATE_TEST_SUITE_P(Default, PciSetupTest,
333                          ::testing::Values(&nuvotonDevice, &aspeedDevice),
334                          [](const testing::TestParamInfo<Device*>& info) {
335                              return info.param->getName();
336                          });
337 
338 TEST(NuvotonWriteTest, TooLarge)
339 {
340     PciAccessMock pciMock;
341     struct pci_device dev;
342     std::vector<std::uint8_t> region(mockRegionSize);
343     std::vector<std::uint8_t> data(0x4001);
344 
345     expectSetup(pciMock, dev, &nuvotonDevice, region.data());
346 
347     std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
348     EXPECT_THROW(bridge->write(stdplus::span<std::uint8_t>(data)),
349                  ToolException);
350 }
351 
352 TEST(NuvotonWriteTest, Success)
353 {
354     PciAccessMock pciMock;
355     struct pci_device dev;
356     std::vector<std::uint8_t> region(mockRegionSize);
357     std::vector<std::uint8_t> data(0x4000);
358 
359     std::generate(data.begin(), data.end(), std::rand);
360 
361     expectSetup(pciMock, dev, &nuvotonDevice, region.data());
362 
363     std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
364     bridge->write(stdplus::span<std::uint8_t>(data));
365 
366     EXPECT_THAT(stdplus::span<uint8_t>(&region[0], data.size()),
367                 SpanEq(stdplus::span<uint8_t>(data)));
368 }
369 
370 TEST(NuvotonConfigureTest, Success)
371 {
372     PciAccessMock pciMock;
373     struct pci_device dev;
374     std::vector<std::uint8_t> region(mockRegionSize);
375     ipmi_flash::PciConfigResponse config{0x123bea51};
376 
377     expectSetup(pciMock, dev, &nuvotonDevice, region.data());
378 
379     std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
380     bridge->configure(config);
381 
382     /* No effect from calling configure(), so the whole region should be 0 */
383     EXPECT_THAT(region, Each(0));
384 }
385 
386 TEST(NuvotonDataLengthTest, Success)
387 {
388     PciAccessMock pciMock;
389     struct pci_device dev;
390     std::vector<std::uint8_t> region(mockRegionSize);
391 
392     expectSetup(pciMock, dev, &nuvotonDevice, region.data());
393 
394     std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
395     EXPECT_EQ(bridge->getDataLength(), 0x4000);
396 }
397 
398 /* Make sure config register is left alone if the bridge is already enabled */
399 TEST(NuvotonBridgeTest, AlreadyEnabledSuccess)
400 {
401     PciAccessMock pciMock;
402     struct pci_device dev;
403     std::vector<std::uint8_t> region(mockRegionSize);
404 
405     constexpr std::uint8_t defaultVal = 0x40;
406 
407     /* Only set standard expectations; not those from nuvotonDevice */
408     expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
409 
410     {
411         InSequence in;
412 
413         EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
414                                                     NuvotonDevice::config))
415             .WillOnce(DoAll(
416                 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
417                 Return(0)));
418 
419         EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
420                                                     NuvotonDevice::config))
421             .WillOnce(DoAll(
422                 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
423                 Return(0)));
424         EXPECT_CALL(pciMock, pci_device_cfg_write_u8(Eq(&dev), defaultVal,
425                                                      NuvotonDevice::config))
426             .WillOnce(Return(0));
427     }
428 
429     nuvotonDevice.getBridge(&pciMock);
430 }
431 
432 /* Read fails when attempting to setup the bridge */
433 TEST(NuvotonBridgeTest, ReadSetupFail)
434 {
435     PciAccessMock pciMock;
436     struct pci_device dev;
437     std::vector<std::uint8_t> region(mockRegionSize);
438 
439     /* Only set standard expectations; not those from nuvotonDevice */
440     expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
441 
442     EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
443                                                 NuvotonDevice::config))
444         .WillOnce(Return(EFAULT));
445 
446     EXPECT_THROW(nuvotonDevice.getBridge(&pciMock), std::system_error);
447 }
448 
449 /* Write fails when attempting to setup the bridge */
450 TEST(NuvotonBridgeTest, WriteSetupFail)
451 {
452     PciAccessMock pciMock;
453     struct pci_device dev;
454     std::vector<std::uint8_t> region(mockRegionSize);
455 
456     constexpr std::uint8_t defaultVal = 0x40;
457 
458     /* Only set standard expectations; not those from nuvotonDevice */
459     expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
460 
461     EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
462                                                 NuvotonDevice::config))
463         .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
464     EXPECT_CALL(pciMock,
465                 pci_device_cfg_write_u8(
466                     Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
467                     NuvotonDevice::config))
468         .WillOnce(Return(EFAULT));
469 
470     EXPECT_THROW(nuvotonDevice.getBridge(&pciMock), std::system_error);
471 }
472 
473 /* Read fails when attempting to disable the bridge */
474 TEST(NuvotonBridgeTest, ReadDisableFail)
475 {
476     PciAccessMock pciMock;
477     struct pci_device dev;
478     std::vector<std::uint8_t> region(mockRegionSize);
479 
480     constexpr std::uint8_t defaultVal = 0x40;
481 
482     /* Only set standard expectations; not those from nuvotonDevice */
483     expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
484 
485     {
486         InSequence in;
487 
488         EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
489                                                     NuvotonDevice::config))
490             .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
491         EXPECT_CALL(pciMock,
492                     pci_device_cfg_write_u8(
493                         Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
494                         NuvotonDevice::config))
495             .WillOnce(Return(0));
496 
497         EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
498                                                     NuvotonDevice::config))
499             .WillOnce(Return(EFAULT));
500     }
501 
502     nuvotonDevice.getBridge(&pciMock);
503 }
504 
505 /* Write fails when attempting to disable the bridge */
506 TEST(NuvotonBridgeTest, WriteDisableFail)
507 {
508     PciAccessMock pciMock;
509     struct pci_device dev;
510     std::vector<std::uint8_t> region(mockRegionSize);
511 
512     constexpr std::uint8_t defaultVal = 0x40;
513 
514     /* Only set standard expectations; not those from nuvotonDevice */
515     expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
516 
517     {
518         InSequence in;
519 
520         EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
521                                                     NuvotonDevice::config))
522             .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
523         EXPECT_CALL(pciMock,
524                     pci_device_cfg_write_u8(
525                         Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
526                         NuvotonDevice::config))
527             .WillOnce(Return(0));
528 
529         EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
530                                                     NuvotonDevice::config))
531             .WillOnce(DoAll(
532                 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
533                 Return(0)));
534         EXPECT_CALL(pciMock, pci_device_cfg_write_u8(Eq(&dev), defaultVal,
535                                                      NuvotonDevice::config))
536             .WillOnce(Return(EFAULT));
537     }
538 
539     nuvotonDevice.getBridge(&pciMock);
540 }
541 
542 /* Make sure the bridge gets enabled when needed */
543 TEST(NuvotonBridgeTest, NotEnabledSuccess)
544 {
545     PciAccessMock pciMock;
546     struct pci_device dev;
547     std::vector<std::uint8_t> region(mockRegionSize);
548 
549     expectSetup(pciMock, dev, &nuvotonDevice, region.data());
550     nuvotonDevice.getBridge(&pciMock);
551 }
552 
553 TEST(AspeedWriteTest, TooLarge)
554 {
555     PciAccessMock pciMock;
556     struct pci_device dev;
557     std::vector<std::uint8_t> region(mockRegionSize);
558     std::vector<std::uint8_t> data(0x10001);
559 
560     expectSetup(pciMock, dev, &aspeedDevice, region.data());
561 
562     std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
563     EXPECT_THROW(bridge->write(stdplus::span<std::uint8_t>(data)),
564                  ToolException);
565 }
566 
567 TEST(AspeedWriteTest, Success)
568 {
569     PciAccessMock pciMock;
570     struct pci_device dev;
571     std::vector<std::uint8_t> region(mockRegionSize);
572     std::vector<std::uint8_t> data(0x10000);
573 
574     std::generate(data.begin(), data.end(), std::rand);
575 
576     expectSetup(pciMock, dev, &aspeedDevice, region.data());
577 
578     std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
579     bridge->write(stdplus::span<std::uint8_t>(data));
580 
581     EXPECT_THAT(stdplus::span<uint8_t>(&region[0x10000], data.size()),
582                 SpanEq(stdplus::span<uint8_t>(data)));
583 }
584 
585 TEST(AspeedConfigureTest, Success)
586 {
587     PciAccessMock pciMock;
588     struct pci_device dev;
589     std::vector<std::uint8_t> region(mockRegionSize);
590     ipmi_flash::PciConfigResponse config{0x123bea51};
591 
592     expectSetup(pciMock, dev, &aspeedDevice, region.data());
593 
594     std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
595     bridge->configure(config);
596 
597     auto configSpan = stdplus::raw::asSpan<uint8_t>(config);
598     EXPECT_THAT(
599         stdplus::span<uint8_t>(&region[AspeedDevice::bridge], sizeof(config)),
600         SpanEq(configSpan));
601 }
602 
603 TEST(AspeedDataLengthTest, Success)
604 {
605     PciAccessMock pciMock;
606     struct pci_device dev;
607     std::vector<std::uint8_t> region(mockRegionSize);
608 
609     expectSetup(pciMock, dev, &aspeedDevice, region.data());
610 
611     std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
612     EXPECT_EQ(bridge->getDataLength(), 0x10000);
613 }
614 
615 /* Make sure config region is left alone if the bridge is already enabled */
616 TEST(AspeedBridgeTest, AlreadyEnabledSuccess)
617 {
618     PciAccessMock pciMock;
619     struct pci_device dev;
620     std::vector<std::uint8_t> region(mockRegionSize);
621 
622     constexpr std::uint8_t defaultVal = 0x42;
623 
624     region[AspeedDevice::config] = defaultVal | AspeedDevice::bridgeEnabled;
625 
626     expectSetup(pciMock, dev, &aspeedDevice, region.data());
627 
628     std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
629 
630     {
631         std::vector<std::uint8_t> enabledRegion(mockRegionSize);
632         enabledRegion[AspeedDevice::config] =
633             defaultVal | AspeedDevice::bridgeEnabled;
634         EXPECT_THAT(region, ContainerEq(enabledRegion));
635     }
636 
637     bridge.reset();
638 
639     {
640         std::vector<std::uint8_t> disabledRegion(mockRegionSize);
641         disabledRegion[AspeedDevice::config] = defaultVal;
642         EXPECT_THAT(region, ContainerEq(disabledRegion));
643     }
644 }
645 
646 /* Make sure the bridge gets enabled when needed */
647 TEST(AspeedBridgeTest, NotEnabledSuccess)
648 {
649     PciAccessMock pciMock;
650     struct pci_device dev;
651     std::vector<std::uint8_t> region(mockRegionSize);
652 
653     constexpr std::uint8_t defaultVal = 0x42;
654 
655     region[AspeedDevice::config] = defaultVal;
656 
657     expectSetup(pciMock, dev, &aspeedDevice, region.data());
658 
659     std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
660 
661     {
662         std::vector<std::uint8_t> enabledRegion(mockRegionSize);
663         enabledRegion[AspeedDevice::config] =
664             defaultVal | AspeedDevice::bridgeEnabled;
665         EXPECT_THAT(region, ContainerEq(enabledRegion));
666     }
667 
668     bridge.reset();
669 
670     {
671         std::vector<std::uint8_t> disabledRegion(mockRegionSize);
672         disabledRegion[AspeedDevice::config] = defaultVal;
673         EXPECT_THAT(region, ContainerEq(disabledRegion));
674     }
675 }
676 
677 } // namespace
678 } // namespace host_tool
679