1 /*
2  * Copyright (C) 2018-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #include "shared/source/built_ins/built_ins.h"
9 #include "shared/source/utilities/perf_counter.h"
10 #include "shared/test/common/test_macros/test.h"
11 
12 #include "opencl/source/built_ins/builtins_dispatch_builder.h"
13 #include "opencl/source/command_queue/command_queue_hw.h"
14 #include "opencl/source/command_queue/enqueue_copy_image.h"
15 #include "opencl/source/command_queue/enqueue_fill_image.h"
16 #include "opencl/source/command_queue/enqueue_read_image.h"
17 #include "opencl/source/command_queue/enqueue_write_image.h"
18 #include "opencl/source/command_queue/gpgpu_walker.h"
19 #include "opencl/source/event/event.h"
20 #include "opencl/source/helpers/hardware_commands_helper.h"
21 #include "opencl/source/kernel/kernel.h"
22 #include "opencl/test/unit_test/command_queue/command_enqueue_fixture.h"
23 #include "opencl/test/unit_test/command_queue/enqueue_fixture.h"
24 #include "opencl/test/unit_test/command_queue/enqueue_write_image_fixture.h"
25 #include "opencl/test/unit_test/fixtures/built_in_fixture.h"
26 #include "opencl/test/unit_test/fixtures/cl_device_fixture.h"
27 #include "opencl/test/unit_test/mocks/mock_kernel.h"
28 
29 using namespace NEO;
30 
31 struct GetSizeRequiredImageTest : public CommandEnqueueFixture,
32                                   public ::testing::Test {
33 
GetSizeRequiredImageTestGetSizeRequiredImageTest34     GetSizeRequiredImageTest() {
35     }
36 
SetUpGetSizeRequiredImageTest37     void SetUp() override {
38         REQUIRE_IMAGES_OR_SKIP(defaultHwInfo);
39         CommandEnqueueFixture::SetUp();
40 
41         srcImage = Image2dHelper<>::create(context);
42         dstImage = Image2dHelper<>::create(context);
43 
44         pDevice->setPreemptionMode(PreemptionMode::Disabled);
45     }
46 
TearDownGetSizeRequiredImageTest47     void TearDown() override {
48         if (IsSkipped()) {
49             return;
50         }
51         delete dstImage;
52         delete srcImage;
53 
54         CommandEnqueueFixture::TearDown();
55     }
56 
57     Image *srcImage = nullptr;
58     Image *dstImage = nullptr;
59 };
60 
HWTEST_F(GetSizeRequiredImageTest,WhenCopyingImageThenHeapsAndCommandBufferConsumedMinimumRequiredSize)61 HWTEST_F(GetSizeRequiredImageTest, WhenCopyingImageThenHeapsAndCommandBufferConsumedMinimumRequiredSize) {
62     auto &commandStream = pCmdQ->getCS(1024);
63     auto usedBeforeCS = commandStream.getUsed();
64     auto &dsh = pCmdQ->getIndirectHeap(IndirectHeap::DYNAMIC_STATE, 0u);
65     auto &ioh = pCmdQ->getIndirectHeap(IndirectHeap::INDIRECT_OBJECT, 0u);
66     auto &ssh = pCmdQ->getIndirectHeap(IndirectHeap::SURFACE_STATE, 0u);
67     auto usedBeforeDSH = dsh.getUsed();
68     auto usedBeforeIOH = ioh.getUsed();
69     auto usedBeforeSSH = ssh.getUsed();
70 
71     auto retVal = EnqueueCopyImageHelper<>::enqueueCopyImage(pCmdQ);
72     EXPECT_EQ(CL_SUCCESS, retVal);
73 
74     auto &builder = BuiltInDispatchBuilderOp::getBuiltinDispatchInfoBuilder(EBuiltInOps::CopyImageToImage3d,
75                                                                             pCmdQ->getClDevice());
76     ASSERT_NE(nullptr, &builder);
77 
78     BuiltinOpParams dc;
79     dc.srcMemObj = srcImage;
80     dc.dstMemObj = dstImage;
81     dc.srcOffset = EnqueueCopyImageTraits::srcOrigin;
82     dc.dstOffset = EnqueueCopyImageTraits::dstOrigin;
83     dc.size = {1, 1, 1};
84 
85     MultiDispatchInfo multiDispatchInfo(dc);
86     builder.buildDispatchInfos(multiDispatchInfo);
87     EXPECT_NE(0u, multiDispatchInfo.size());
88 
89     auto kernel = multiDispatchInfo.begin()->getKernel();
90     ASSERT_NE(nullptr, kernel);
91 
92     auto usedAfterCS = commandStream.getUsed();
93     auto usedAfterDSH = dsh.getUsed();
94     auto usedAfterIOH = ioh.getUsed();
95     auto usedAfterSSH = ssh.getUsed();
96 
97     auto expectedSizeCS = EnqueueOperation<FamilyType>::getSizeRequiredCS(CL_COMMAND_COPY_IMAGE, false, false, *pCmdQ, kernel, {});
98     auto expectedSizeDSH = HardwareCommandsHelper<FamilyType>::getSizeRequiredDSH(*kernel);
99     auto expectedSizeIOH = HardwareCommandsHelper<FamilyType>::getSizeRequiredIOH(*kernel);
100     auto expectedSizeSSH = HardwareCommandsHelper<FamilyType>::getSizeRequiredSSH(*kernel);
101 
102     // Since each enqueue* may flush, we may see a MI_BATCH_BUFFER_END appended.
103     expectedSizeCS += sizeof(typename FamilyType::MI_BATCH_BUFFER_END);
104     expectedSizeCS = alignUp(expectedSizeCS, MemoryConstants::cacheLineSize);
105 
106     EXPECT_GE(expectedSizeCS, usedAfterCS - usedBeforeCS);
107     EXPECT_GE(expectedSizeDSH, usedAfterDSH - usedBeforeDSH);
108     EXPECT_GE(expectedSizeIOH, usedAfterIOH - usedBeforeIOH);
109     EXPECT_GE(expectedSizeSSH, usedAfterSSH - usedBeforeSSH);
110 }
111 
HWTEST_F(GetSizeRequiredImageTest,WhenCopyingReadWriteImageThenHeapsAndCommandBufferConsumedMinimumRequiredSize)112 HWTEST_F(GetSizeRequiredImageTest, WhenCopyingReadWriteImageThenHeapsAndCommandBufferConsumedMinimumRequiredSize) {
113     auto &commandStream = pCmdQ->getCS(1024);
114     auto usedBeforeCS = commandStream.getUsed();
115     auto &dsh = pCmdQ->getIndirectHeap(IndirectHeap::DYNAMIC_STATE, 0u);
116     auto &ioh = pCmdQ->getIndirectHeap(IndirectHeap::INDIRECT_OBJECT, 0u);
117     auto &ssh = pCmdQ->getIndirectHeap(IndirectHeap::SURFACE_STATE, 0u);
118     auto usedBeforeDSH = dsh.getUsed();
119     auto usedBeforeIOH = ioh.getUsed();
120     auto usedBeforeSSH = ssh.getUsed();
121 
122     std::unique_ptr<MockProgram> program(Program::createBuiltInFromSource<MockProgram>("CopyImageToImage3d", context, context->getDevices(), nullptr));
123     program->build(program->getDevices(), nullptr, false);
124     std::unique_ptr<Kernel> kernel(Kernel::create<MockKernel>(program.get(), program->getKernelInfoForKernel("CopyImageToImage3d"), *context->getDevice(0), nullptr));
125 
126     EXPECT_NE(nullptr, kernel);
127     // This kernel does not operate on OpenCL 2.0 Read and Write images
128     EXPECT_FALSE(kernel->getKernelInfo().kernelDescriptor.kernelAttributes.flags.usesFencesForReadWriteImages);
129     // Simulate that the kernel actually operates on OpenCL 2.0 Read and Write images.
130     // Such kernel may require special WA DisableLSQCROPERFforOCL during construction of Command Buffer
131     const_cast<KernelDescriptor &>(kernel->getKernelInfo().kernelDescriptor).kernelAttributes.flags.usesFencesForReadWriteImages = true;
132 
133     // Enqueue kernel that may require special WA DisableLSQCROPERFforOCL
134     auto retVal = EnqueueKernelHelper<>::enqueueKernel(pCmdQ, kernel.get());
135     EXPECT_EQ(CL_SUCCESS, retVal);
136 
137     auto usedAfterCS = commandStream.getUsed();
138     auto usedAfterDSH = dsh.getUsed();
139     auto usedAfterIOH = ioh.getUsed();
140     auto usedAfterSSH = ssh.getUsed();
141 
142     auto expectedSizeCS = EnqueueOperation<FamilyType>::getSizeRequiredCS(CL_COMMAND_COPY_IMAGE, false, false, *pCmdQ, kernel.get(), {});
143     auto expectedSizeDSH = HardwareCommandsHelper<FamilyType>::getSizeRequiredDSH(*kernel.get());
144     auto expectedSizeIOH = HardwareCommandsHelper<FamilyType>::getSizeRequiredIOH(*kernel.get());
145     auto expectedSizeSSH = HardwareCommandsHelper<FamilyType>::getSizeRequiredSSH(*kernel.get());
146 
147     // Since each enqueue* may flush, we may see a MI_BATCH_BUFFER_END appended.
148     expectedSizeCS += sizeof(typename FamilyType::MI_BATCH_BUFFER_END);
149     expectedSizeCS = alignUp(expectedSizeCS, MemoryConstants::cacheLineSize);
150 
151     const_cast<KernelDescriptor &>(kernel->getKernelInfo().kernelDescriptor).kernelAttributes.flags.usesFencesForReadWriteImages = false;
152 
153     EXPECT_GE(expectedSizeCS, usedAfterCS - usedBeforeCS);
154     EXPECT_GE(expectedSizeDSH, usedAfterDSH - usedBeforeDSH);
155     EXPECT_GE(expectedSizeIOH, usedAfterIOH - usedBeforeIOH);
156     EXPECT_GE(expectedSizeSSH, usedAfterSSH - usedBeforeSSH);
157 }
158 
HWTEST_F(GetSizeRequiredImageTest,WhenReadingImageNonBlockingThenHeapsAndCommandBufferConsumedMinimumRequiredSize)159 HWTEST_F(GetSizeRequiredImageTest, WhenReadingImageNonBlockingThenHeapsAndCommandBufferConsumedMinimumRequiredSize) {
160     auto &commandStream = pCmdQ->getCS(1024);
161     auto usedBeforeCS = commandStream.getUsed();
162     auto &dsh = pCmdQ->getIndirectHeap(IndirectHeap::DYNAMIC_STATE, 0u);
163     auto &ioh = pCmdQ->getIndirectHeap(IndirectHeap::INDIRECT_OBJECT, 0u);
164     auto &ssh = pCmdQ->getIndirectHeap(IndirectHeap::SURFACE_STATE, 0u);
165     auto usedBeforeDSH = dsh.getUsed();
166     auto usedBeforeIOH = ioh.getUsed();
167     auto usedBeforeSSH = ssh.getUsed();
168 
169     auto retVal = EnqueueReadImageHelper<>::enqueueReadImage(
170         pCmdQ,
171         srcImage,
172         CL_FALSE);
173     EXPECT_EQ(CL_SUCCESS, retVal);
174 
175     auto &builder = BuiltInDispatchBuilderOp::getBuiltinDispatchInfoBuilder(EBuiltInOps::CopyImage3dToBuffer,
176                                                                             pCmdQ->getClDevice());
177     ASSERT_NE(nullptr, &builder);
178 
179     BuiltinOpParams dc;
180     dc.srcMemObj = srcImage;
181     dc.dstPtr = EnqueueReadImageTraits::hostPtr;
182     dc.srcOffset = EnqueueReadImageTraits::origin;
183     dc.size = EnqueueReadImageTraits::region;
184     dc.srcRowPitch = EnqueueReadImageTraits::rowPitch;
185     dc.srcSlicePitch = EnqueueReadImageTraits::slicePitch;
186 
187     MultiDispatchInfo multiDispatchInfo(dc);
188     builder.buildDispatchInfos(multiDispatchInfo);
189     EXPECT_NE(0u, multiDispatchInfo.size());
190 
191     auto kernel = multiDispatchInfo.begin()->getKernel();
192     ASSERT_NE(nullptr, kernel);
193 
194     auto usedAfterCS = commandStream.getUsed();
195     auto usedAfterDSH = dsh.getUsed();
196     auto usedAfterIOH = ioh.getUsed();
197     auto usedAfterSSH = ssh.getUsed();
198 
199     auto expectedSizeCS = EnqueueOperation<FamilyType>::getSizeRequiredCS(CL_COMMAND_READ_IMAGE, false, false, *pCmdQ, kernel, {});
200     auto expectedSizeDSH = HardwareCommandsHelper<FamilyType>::getSizeRequiredDSH(*kernel);
201     auto expectedSizeIOH = HardwareCommandsHelper<FamilyType>::getSizeRequiredIOH(*kernel);
202     auto expectedSizeSSH = HardwareCommandsHelper<FamilyType>::getSizeRequiredSSH(*kernel);
203 
204     // Since each enqueue* may flush, we may see a MI_BATCH_BUFFER_END appended.
205     expectedSizeCS += sizeof(typename FamilyType::MI_BATCH_BUFFER_END);
206     expectedSizeCS = alignUp(expectedSizeCS, MemoryConstants::cacheLineSize);
207 
208     EXPECT_GE(expectedSizeCS, usedAfterCS - usedBeforeCS);
209     EXPECT_GE(expectedSizeDSH, usedAfterDSH - usedBeforeDSH);
210     EXPECT_GE(expectedSizeIOH, usedAfterIOH - usedBeforeIOH);
211     EXPECT_GE(expectedSizeSSH, usedAfterSSH - usedBeforeSSH);
212 }
213 
HWTEST_F(GetSizeRequiredImageTest,WhenReadingImageBlockingThenHeapsAndCommandBufferConsumedMinimumRequiredSize)214 HWTEST_F(GetSizeRequiredImageTest, WhenReadingImageBlockingThenHeapsAndCommandBufferConsumedMinimumRequiredSize) {
215     auto &commandStream = pCmdQ->getCS(1024);
216     auto usedBeforeCS = commandStream.getUsed();
217     auto &dsh = pCmdQ->getIndirectHeap(IndirectHeap::DYNAMIC_STATE, 0u);
218     auto &ioh = pCmdQ->getIndirectHeap(IndirectHeap::INDIRECT_OBJECT, 0u);
219     auto &ssh = pCmdQ->getIndirectHeap(IndirectHeap::SURFACE_STATE, 0u);
220     auto usedBeforeDSH = dsh.getUsed();
221     auto usedBeforeIOH = ioh.getUsed();
222     auto usedBeforeSSH = ssh.getUsed();
223 
224     auto retVal = EnqueueReadImageHelper<>::enqueueReadImage(
225         pCmdQ,
226         srcImage,
227         CL_TRUE);
228     EXPECT_EQ(CL_SUCCESS, retVal);
229 
230     auto &builder = BuiltInDispatchBuilderOp::getBuiltinDispatchInfoBuilder(EBuiltInOps::CopyImage3dToBuffer,
231                                                                             pCmdQ->getClDevice());
232     ASSERT_NE(nullptr, &builder);
233 
234     BuiltinOpParams dc;
235     dc.srcMemObj = srcImage;
236     dc.dstPtr = EnqueueReadImageTraits::hostPtr;
237     dc.srcOffset = EnqueueReadImageTraits::origin;
238     dc.size = EnqueueReadImageTraits::region;
239     dc.srcRowPitch = EnqueueReadImageTraits::rowPitch;
240     dc.srcSlicePitch = EnqueueReadImageTraits::slicePitch;
241 
242     MultiDispatchInfo multiDispatchInfo(dc);
243     builder.buildDispatchInfos(multiDispatchInfo);
244     EXPECT_NE(0u, multiDispatchInfo.size());
245 
246     auto kernel = multiDispatchInfo.begin()->getKernel();
247     ASSERT_NE(nullptr, kernel);
248 
249     auto usedAfterCS = commandStream.getUsed();
250     auto usedAfterDSH = dsh.getUsed();
251     auto usedAfterIOH = ioh.getUsed();
252     auto usedAfterSSH = ssh.getUsed();
253 
254     auto expectedSizeCS = EnqueueOperation<FamilyType>::getSizeRequiredCS(CL_COMMAND_READ_IMAGE, false, false, *pCmdQ, kernel, {});
255     auto expectedSizeDSH = HardwareCommandsHelper<FamilyType>::getSizeRequiredDSH(*kernel);
256     auto expectedSizeIOH = HardwareCommandsHelper<FamilyType>::getSizeRequiredIOH(*kernel);
257     auto expectedSizeSSH = HardwareCommandsHelper<FamilyType>::getSizeRequiredSSH(*kernel);
258 
259     // Since each enqueue* may flush, we may see a MI_BATCH_BUFFER_END appended.
260     expectedSizeCS += sizeof(typename FamilyType::MI_BATCH_BUFFER_END);
261     expectedSizeCS = alignUp(expectedSizeCS, MemoryConstants::cacheLineSize);
262 
263     EXPECT_GE(expectedSizeCS, usedAfterCS - usedBeforeCS);
264     EXPECT_GE(expectedSizeDSH, usedAfterDSH - usedBeforeDSH);
265     EXPECT_GE(expectedSizeIOH, usedAfterIOH - usedBeforeIOH);
266     EXPECT_GE(expectedSizeSSH, usedAfterSSH - usedBeforeSSH);
267 }
268 
HWTEST_F(GetSizeRequiredImageTest,WhenWritingImageNonBlockingThenHeapsAndCommandBufferConsumedMinimumRequiredSize)269 HWTEST_F(GetSizeRequiredImageTest, WhenWritingImageNonBlockingThenHeapsAndCommandBufferConsumedMinimumRequiredSize) {
270     auto &commandStream = pCmdQ->getCS(1024);
271     auto usedBeforeCS = commandStream.getUsed();
272     auto &dsh = pCmdQ->getIndirectHeap(IndirectHeap::DYNAMIC_STATE, 0u);
273     auto &ioh = pCmdQ->getIndirectHeap(IndirectHeap::INDIRECT_OBJECT, 0u);
274     auto &ssh = pCmdQ->getIndirectHeap(IndirectHeap::SURFACE_STATE, 0u);
275     auto usedBeforeDSH = dsh.getUsed();
276     auto usedBeforeIOH = ioh.getUsed();
277     auto usedBeforeSSH = ssh.getUsed();
278 
279     auto retVal = EnqueueWriteImageHelper<>::enqueueWriteImage(
280         pCmdQ,
281         dstImage,
282         CL_FALSE);
283     EXPECT_EQ(CL_SUCCESS, retVal);
284 
285     auto &builder = BuiltInDispatchBuilderOp::getBuiltinDispatchInfoBuilder(EBuiltInOps::CopyBufferToImage3d,
286                                                                             pCmdQ->getClDevice());
287     ASSERT_NE(nullptr, &builder);
288 
289     BuiltinOpParams dc;
290     dc.srcPtr = EnqueueWriteImageTraits::hostPtr;
291     dc.dstMemObj = dstImage;
292     dc.dstOffset = EnqueueWriteImageTraits::origin;
293     dc.size = EnqueueWriteImageTraits::region;
294     dc.dstRowPitch = EnqueueWriteImageTraits::rowPitch;
295     dc.dstSlicePitch = EnqueueWriteImageTraits::slicePitch;
296 
297     MultiDispatchInfo multiDispatchInfo(dc);
298     builder.buildDispatchInfos(multiDispatchInfo);
299     EXPECT_NE(0u, multiDispatchInfo.size());
300 
301     auto kernel = multiDispatchInfo.begin()->getKernel();
302     ASSERT_NE(nullptr, kernel);
303 
304     auto usedAfterCS = commandStream.getUsed();
305     auto usedAfterDSH = dsh.getUsed();
306     auto usedAfterIOH = ioh.getUsed();
307     auto usedAfterSSH = ssh.getUsed();
308 
309     auto expectedSizeCS = EnqueueOperation<FamilyType>::getSizeRequiredCS(CL_COMMAND_WRITE_IMAGE, false, false, *pCmdQ, kernel, {});
310     auto expectedSizeDSH = HardwareCommandsHelper<FamilyType>::getSizeRequiredDSH(*kernel);
311     auto expectedSizeIOH = HardwareCommandsHelper<FamilyType>::getSizeRequiredIOH(*kernel);
312     auto expectedSizeSSH = HardwareCommandsHelper<FamilyType>::getSizeRequiredSSH(*kernel);
313 
314     // Since each enqueue* may flush, we may see a MI_BATCH_BUFFER_END appended.
315     expectedSizeCS += sizeof(typename FamilyType::MI_BATCH_BUFFER_END);
316     expectedSizeCS = alignUp(expectedSizeCS, MemoryConstants::cacheLineSize);
317 
318     EXPECT_GE(expectedSizeCS, usedAfterCS - usedBeforeCS);
319     EXPECT_GE(expectedSizeDSH, usedAfterDSH - usedBeforeDSH);
320     EXPECT_GE(expectedSizeIOH, usedAfterIOH - usedBeforeIOH);
321     EXPECT_GE(expectedSizeSSH, usedAfterSSH - usedBeforeSSH);
322 }
323 
HWTEST_F(GetSizeRequiredImageTest,WhenWritingImageBlockingThenHeapsAndCommandBufferConsumedMinimumRequiredSize)324 HWTEST_F(GetSizeRequiredImageTest, WhenWritingImageBlockingThenHeapsAndCommandBufferConsumedMinimumRequiredSize) {
325     auto &commandStream = pCmdQ->getCS(1024);
326     auto usedBeforeCS = commandStream.getUsed();
327     auto &dsh = pCmdQ->getIndirectHeap(IndirectHeap::DYNAMIC_STATE, 0u);
328     auto &ioh = pCmdQ->getIndirectHeap(IndirectHeap::INDIRECT_OBJECT, 0u);
329     auto &ssh = pCmdQ->getIndirectHeap(IndirectHeap::SURFACE_STATE, 0u);
330     auto usedBeforeDSH = dsh.getUsed();
331     auto usedBeforeIOH = ioh.getUsed();
332     auto usedBeforeSSH = ssh.getUsed();
333 
334     auto retVal = EnqueueWriteImageHelper<>::enqueueWriteImage(
335         pCmdQ,
336         dstImage,
337         CL_TRUE);
338     EXPECT_EQ(CL_SUCCESS, retVal);
339 
340     auto &builder = BuiltInDispatchBuilderOp::getBuiltinDispatchInfoBuilder(EBuiltInOps::CopyBufferToImage3d,
341                                                                             pCmdQ->getClDevice());
342     ASSERT_NE(nullptr, &builder);
343 
344     BuiltinOpParams dc;
345     dc.srcPtr = EnqueueWriteImageTraits::hostPtr;
346     dc.dstMemObj = dstImage;
347     dc.dstOffset = EnqueueWriteImageTraits::origin;
348     dc.size = EnqueueWriteImageTraits::region;
349     dc.dstRowPitch = EnqueueWriteImageTraits::rowPitch;
350     dc.dstSlicePitch = EnqueueWriteImageTraits::slicePitch;
351 
352     MultiDispatchInfo multiDispatchInfo(dc);
353     builder.buildDispatchInfos(multiDispatchInfo);
354     EXPECT_NE(0u, multiDispatchInfo.size());
355 
356     auto kernel = multiDispatchInfo.begin()->getKernel();
357     ASSERT_NE(nullptr, kernel);
358 
359     auto usedAfterCS = commandStream.getUsed();
360     auto usedAfterDSH = dsh.getUsed();
361     auto usedAfterIOH = ioh.getUsed();
362     auto usedAfterSSH = ssh.getUsed();
363 
364     auto expectedSizeCS = EnqueueOperation<FamilyType>::getSizeRequiredCS(CL_COMMAND_WRITE_IMAGE, false, false, *pCmdQ, kernel, {});
365     auto expectedSizeDSH = HardwareCommandsHelper<FamilyType>::getSizeRequiredDSH(*kernel);
366     auto expectedSizeIOH = HardwareCommandsHelper<FamilyType>::getSizeRequiredIOH(*kernel);
367     auto expectedSizeSSH = HardwareCommandsHelper<FamilyType>::getSizeRequiredSSH(*kernel);
368 
369     // Since each enqueue* may flush, we may see a MI_BATCH_BUFFER_END appended.
370     expectedSizeCS += sizeof(typename FamilyType::MI_BATCH_BUFFER_END);
371     expectedSizeCS = alignUp(expectedSizeCS, MemoryConstants::cacheLineSize);
372 
373     EXPECT_GE(expectedSizeCS, usedAfterCS - usedBeforeCS);
374     EXPECT_GE(expectedSizeDSH, usedAfterDSH - usedBeforeDSH);
375     EXPECT_GE(expectedSizeIOH, usedAfterIOH - usedBeforeIOH);
376     EXPECT_GE(expectedSizeSSH, usedAfterSSH - usedBeforeSSH);
377 }
378