1/*
2 * Copyright (C) 2018-2021 Intel Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 */
7
8#include "shared/source/compiler_interface/compiler_interface.h"
9#include "shared/source/compiler_interface/intermediate_representations.h"
10#include "shared/source/device/device.h"
11#include "shared/source/device_binary_format/elf/elf.h"
12#include "shared/source/device_binary_format/elf/elf_encoder.h"
13#include "shared/source/device_binary_format/elf/ocl_elf.h"
14#include "shared/source/helpers/file_io.h"
15#include "shared/test/common/helpers/kernel_binary_helper.h"
16#include "shared/test/common/helpers/test_files.h"
17
18#include "opencl/source/context/context.h"
19
20#include "cl_api_tests.h"
21
22using namespace NEO;
23typedef api_tests clGetProgramBuildInfoTests;
24
25namespace ULT {
26void verifyDevices(cl_program pProgram, size_t expectedNumDevices, cl_device_id *expectedDevices);
27
28TEST_F(clGetProgramBuildInfoTests, givenSourceWhenclGetProgramBuildInfoIsCalledThenReturnClBuildNone) {
29    cl_program pProgram = nullptr;
30    std::unique_ptr<char[]> pSource = nullptr;
31    size_t sourceSize = 0;
32    std::string testFile;
33
34    KernelBinaryHelper kbHelper("CopyBuffer_simd16");
35
36    testFile.append(clFiles);
37    testFile.append("CopyBuffer_simd16.cl");
38
39    pSource = loadDataFromFile(
40        testFile.c_str(),
41        sourceSize);
42
43    ASSERT_NE(0u, sourceSize);
44    ASSERT_NE(nullptr, pSource);
45
46    const char *sources[1] = {pSource.get()};
47    pProgram = clCreateProgramWithSource(
48        pContext,
49        1,
50        sources,
51        &sourceSize,
52        &retVal);
53
54    EXPECT_NE(nullptr, pProgram);
55    ASSERT_EQ(CL_SUCCESS, retVal);
56
57    cl_build_status buildStatus;
58    retVal = clGetProgramBuildInfo(pProgram, testedClDevice, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
59    EXPECT_EQ(CL_SUCCESS, retVal);
60    EXPECT_EQ(CL_BUILD_NONE, buildStatus);
61
62    retVal = clCompileProgram(
63        pProgram,
64        1,
65        &testedClDevice,
66        nullptr,
67        0,
68        nullptr,
69        nullptr,
70        nullptr,
71        nullptr);
72
73    ASSERT_EQ(CL_SUCCESS, retVal);
74
75    retVal = clGetProgramBuildInfo(pProgram, testedClDevice, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
76    EXPECT_EQ(CL_SUCCESS, retVal);
77    EXPECT_EQ(CL_BUILD_SUCCESS, buildStatus);
78
79    retVal = clBuildProgram(
80        pProgram,
81        1,
82        &testedClDevice,
83        nullptr,
84        nullptr,
85        nullptr);
86
87    ASSERT_EQ(CL_SUCCESS, retVal);
88
89    retVal = clGetProgramBuildInfo(pProgram, testedClDevice, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
90    EXPECT_EQ(CL_SUCCESS, retVal);
91    EXPECT_EQ(CL_BUILD_SUCCESS, buildStatus);
92
93    // try to get program build info for invalid program object - should fail
94    retVal = clGetProgramBuildInfo(nullptr, testedClDevice, CL_PROGRAM_BUILD_STATUS, 0, nullptr, nullptr);
95    EXPECT_EQ(CL_INVALID_PROGRAM, retVal);
96
97    retVal = clReleaseProgram(pProgram);
98    EXPECT_EQ(CL_SUCCESS, retVal);
99}
100
101TEST(clGetProgramBuildInfoTest, givenMultiDeviceProgramWhenCompilingForSpecificDevicesThenOnlySpecificDevicesAndTheirSubDevicesReportBuildStatus) {
102    cl_program pProgram = nullptr;
103    std::unique_ptr<char[]> pSource = nullptr;
104    size_t sourceSize = 0;
105    std::string testFile;
106
107    KernelBinaryHelper kbHelper("CopyBuffer_simd16");
108
109    testFile.append(clFiles);
110    testFile.append("CopyBuffer_simd16.cl");
111
112    pSource = loadDataFromFile(
113        testFile.c_str(),
114        sourceSize);
115
116    ASSERT_NE(0u, sourceSize);
117    ASSERT_NE(nullptr, pSource);
118
119    const char *sources[1] = {pSource.get()};
120
121    MockUnrestrictiveContextMultiGPU context;
122    cl_int retVal = CL_INVALID_PROGRAM;
123
124    pProgram = clCreateProgramWithSource(
125        &context,
126        1,
127        sources,
128        &sourceSize,
129        &retVal);
130
131    EXPECT_NE(nullptr, pProgram);
132    ASSERT_EQ(CL_SUCCESS, retVal);
133
134    cl_build_status buildStatus;
135    for (const auto &device : context.getDevices()) {
136        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
137        EXPECT_EQ(CL_SUCCESS, retVal);
138        EXPECT_EQ(CL_BUILD_NONE, buildStatus);
139    }
140
141    cl_device_id devicesForCompilation[] = {context.getDevice(1), context.getDevice(3)};
142    cl_device_id associatedSubDevices[] = {context.getDevice(4), context.getDevice(5)};
143    cl_device_id devicesNotForCompilation[] = {context.getDevice(0), context.getDevice(2)};
144
145    retVal = clCompileProgram(
146        pProgram,
147        2,
148        devicesForCompilation,
149        nullptr,
150        0,
151        nullptr,
152        nullptr,
153        nullptr,
154        nullptr);
155
156    ASSERT_EQ(CL_SUCCESS, retVal);
157
158    for (const auto &device : devicesNotForCompilation) {
159        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
160        EXPECT_EQ(CL_SUCCESS, retVal);
161        EXPECT_EQ(CL_BUILD_NONE, buildStatus);
162    }
163    for (const auto &device : devicesForCompilation) {
164        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
165        EXPECT_EQ(CL_SUCCESS, retVal);
166        EXPECT_EQ(CL_BUILD_SUCCESS, buildStatus);
167    }
168    for (const auto &device : associatedSubDevices) {
169        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
170        EXPECT_EQ(CL_SUCCESS, retVal);
171        EXPECT_EQ(CL_BUILD_SUCCESS, buildStatus);
172    }
173
174    retVal = clReleaseProgram(pProgram);
175    EXPECT_EQ(CL_SUCCESS, retVal);
176}
177
178TEST(clGetProgramBuildInfoTest, givenMultiDeviceProgramWhenCompilingWithoutInputDevicesThenAllDevicesReportBuildStatus) {
179    cl_program pProgram = nullptr;
180    std::unique_ptr<char[]> pSource = nullptr;
181    size_t sourceSize = 0;
182    std::string testFile;
183
184    KernelBinaryHelper kbHelper("CopyBuffer_simd16");
185
186    testFile.append(clFiles);
187    testFile.append("CopyBuffer_simd16.cl");
188
189    pSource = loadDataFromFile(
190        testFile.c_str(),
191        sourceSize);
192
193    ASSERT_NE(0u, sourceSize);
194    ASSERT_NE(nullptr, pSource);
195
196    const char *sources[1] = {pSource.get()};
197
198    MockUnrestrictiveContextMultiGPU context;
199    cl_int retVal = CL_INVALID_PROGRAM;
200
201    pProgram = clCreateProgramWithSource(
202        &context,
203        1,
204        sources,
205        &sourceSize,
206        &retVal);
207
208    EXPECT_NE(nullptr, pProgram);
209    ASSERT_EQ(CL_SUCCESS, retVal);
210
211    cl_build_status buildStatus;
212    for (const auto &device : context.getDevices()) {
213        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
214        EXPECT_EQ(CL_SUCCESS, retVal);
215        EXPECT_EQ(CL_BUILD_NONE, buildStatus);
216    }
217
218    retVal = clCompileProgram(
219        pProgram,
220        0,
221        nullptr,
222        nullptr,
223        0,
224        nullptr,
225        nullptr,
226        nullptr,
227        nullptr);
228
229    ASSERT_EQ(CL_SUCCESS, retVal);
230
231    for (const auto &device : context.getDevices()) {
232        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
233        EXPECT_EQ(CL_SUCCESS, retVal);
234        EXPECT_EQ(CL_BUILD_SUCCESS, buildStatus);
235    }
236
237    retVal = clReleaseProgram(pProgram);
238    EXPECT_EQ(CL_SUCCESS, retVal);
239}
240
241TEST_F(clGetProgramBuildInfoTests, givenElfBinaryWhenclGetProgramBuildInfoIsCalledThenReturnClBuildNone) {
242    cl_program pProgram = nullptr;
243    cl_int binaryStatus = CL_INVALID_VALUE;
244
245    NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEncoder;
246    elfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_LIBRARY;
247    const uint8_t data[4] = {};
248    elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_OPTIONS, NEO::Elf::SectionNamesOpenCl::buildOptions, data);
249    elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, NEO::Elf::SectionNamesOpenCl::spirvObject, ArrayRef<const uint8_t>::fromAny(NEO::spirvMagic.begin(), NEO::spirvMagic.size()));
250    auto elfBinary = elfEncoder.encode();
251
252    const size_t binarySize = elfBinary.size();
253    const unsigned char *elfBinaryTemp = reinterpret_cast<unsigned char *>(elfBinary.data());
254    pProgram = clCreateProgramWithBinary(
255        pContext,
256        1,
257        &testedClDevice,
258        &binarySize,
259        &elfBinaryTemp,
260        &binaryStatus,
261        &retVal);
262
263    EXPECT_EQ(CL_SUCCESS, retVal);
264    EXPECT_NE(nullptr, pProgram);
265    EXPECT_EQ(CL_SUCCESS, binaryStatus);
266
267    cl_build_status buildStatus;
268    retVal = clGetProgramBuildInfo(pProgram, testedClDevice, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, nullptr);
269    EXPECT_EQ(CL_SUCCESS, retVal);
270    EXPECT_EQ(CL_BUILD_NONE, buildStatus);
271
272    retVal = clReleaseProgram(pProgram);
273    EXPECT_EQ(CL_SUCCESS, retVal);
274}
275
276TEST_F(clGetProgramBuildInfoTests, givenInvalidDeviceInputWhenGetProgramBuildInfoIsCalledThenInvalidDeviceErrorIsReturned) {
277    cl_build_status buildStatus;
278    retVal = clGetProgramBuildInfo(pProgram, nullptr, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, nullptr);
279    EXPECT_EQ(CL_INVALID_DEVICE, retVal);
280    retVal = clGetProgramBuildInfo(pProgram, reinterpret_cast<cl_device_id>(pProgram), CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, nullptr);
281    EXPECT_EQ(CL_INVALID_DEVICE, retVal);
282
283    MockContext context;
284    retVal = clGetProgramBuildInfo(pProgram, context.getDevice(0), CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, nullptr);
285    EXPECT_EQ(CL_INVALID_DEVICE, retVal);
286}
287
288TEST(clGetProgramBuildInfoTest, givenMultiDeviceProgramWhenLinkingForSpecificDevicesThenOnlySpecificDevicesReportBuildStatus) {
289    MockProgram *pProgram = nullptr;
290    std::unique_ptr<char[]> pSource = nullptr;
291    size_t sourceSize = 0;
292    std::string testFile;
293
294    KernelBinaryHelper kbHelper("CopyBuffer_simd16");
295
296    testFile.append(clFiles);
297    testFile.append("CopyBuffer_simd16.cl");
298
299    pSource = loadDataFromFile(
300        testFile.c_str(),
301        sourceSize);
302
303    ASSERT_NE(0u, sourceSize);
304    ASSERT_NE(nullptr, pSource);
305
306    const char *sources[1] = {pSource.get()};
307
308    MockUnrestrictiveContextMultiGPU context;
309    cl_int retVal = CL_INVALID_PROGRAM;
310
311    pProgram = Program::create<MockProgram>(
312        &context,
313        1,
314        sources,
315        &sourceSize,
316        retVal);
317
318    EXPECT_NE(nullptr, pProgram);
319    ASSERT_EQ(CL_SUCCESS, retVal);
320
321    cl_build_status buildStatus;
322    for (const auto &device : context.getDevices()) {
323        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
324        EXPECT_EQ(CL_SUCCESS, retVal);
325        EXPECT_EQ(CL_BUILD_NONE, buildStatus);
326    }
327
328    retVal = clCompileProgram(
329        pProgram,
330        0,
331        nullptr,
332        nullptr,
333        0,
334        nullptr,
335        nullptr,
336        nullptr,
337        nullptr);
338
339    ASSERT_EQ(CL_SUCCESS, retVal);
340
341    pProgram->setBuildStatus(CL_BUILD_NONE);
342
343    cl_device_id devicesForLinking[] = {context.getDevice(1), context.getDevice(3)};
344    cl_program programForLinking = pProgram;
345
346    auto outProgram = clLinkProgram(
347        &context,
348        2,
349        devicesForLinking,
350        nullptr,
351        1,
352        &programForLinking,
353        nullptr,
354        nullptr,
355        &retVal);
356
357    ASSERT_EQ(CL_SUCCESS, retVal);
358    EXPECT_NE(nullptr, outProgram);
359
360    verifyDevices(outProgram, 2, devicesForLinking);
361
362    for (const auto &device : devicesForLinking) {
363        retVal = clGetProgramBuildInfo(outProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
364        EXPECT_EQ(CL_SUCCESS, retVal);
365        EXPECT_EQ(CL_BUILD_SUCCESS, buildStatus);
366    }
367
368    retVal = clReleaseProgram(pProgram);
369    EXPECT_EQ(CL_SUCCESS, retVal);
370    retVal = clReleaseProgram(outProgram);
371    EXPECT_EQ(CL_SUCCESS, retVal);
372}
373
374TEST(clGetProgramBuildInfoTest, givenMultiDeviceProgramWhenLinkingWithoutInputDevicesThenAllDevicesReportBuildStatus) {
375    MockProgram *pProgram = nullptr;
376    std::unique_ptr<char[]> pSource = nullptr;
377    size_t sourceSize = 0;
378    std::string testFile;
379
380    KernelBinaryHelper kbHelper("CopyBuffer_simd16");
381
382    testFile.append(clFiles);
383    testFile.append("CopyBuffer_simd16.cl");
384
385    pSource = loadDataFromFile(
386        testFile.c_str(),
387        sourceSize);
388
389    ASSERT_NE(0u, sourceSize);
390    ASSERT_NE(nullptr, pSource);
391
392    const char *sources[1] = {pSource.get()};
393
394    MockUnrestrictiveContextMultiGPU context;
395    cl_int retVal = CL_INVALID_PROGRAM;
396
397    pProgram = Program::create<MockProgram>(
398        &context,
399        1,
400        sources,
401        &sourceSize,
402        retVal);
403
404    EXPECT_NE(nullptr, pProgram);
405    ASSERT_EQ(CL_SUCCESS, retVal);
406
407    cl_build_status buildStatus;
408    for (const auto &device : context.getDevices()) {
409        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
410        EXPECT_EQ(CL_SUCCESS, retVal);
411        EXPECT_EQ(CL_BUILD_NONE, buildStatus);
412    }
413
414    retVal = clCompileProgram(
415        pProgram,
416        0,
417        nullptr,
418        nullptr,
419        0,
420        nullptr,
421        nullptr,
422        nullptr,
423        nullptr);
424
425    ASSERT_EQ(CL_SUCCESS, retVal);
426
427    pProgram->setBuildStatus(CL_BUILD_NONE);
428
429    cl_program programForLinking = pProgram;
430
431    auto outProgram = clLinkProgram(
432        &context,
433        0,
434        nullptr,
435        nullptr,
436        1,
437        &programForLinking,
438        nullptr,
439        nullptr,
440        &retVal);
441
442    ASSERT_EQ(CL_SUCCESS, retVal);
443    EXPECT_NE(nullptr, outProgram);
444
445    std::vector<cl_device_id> contextDevices;
446    context.getDevices().toDeviceIDs(contextDevices);
447    verifyDevices(outProgram, contextDevices.size(), contextDevices.data());
448
449    for (const auto &device : context.getDevices()) {
450        retVal = clGetProgramBuildInfo(outProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
451        EXPECT_EQ(CL_SUCCESS, retVal);
452        EXPECT_EQ(CL_BUILD_SUCCESS, buildStatus);
453    }
454
455    retVal = clReleaseProgram(pProgram);
456    EXPECT_EQ(CL_SUCCESS, retVal);
457    retVal = clReleaseProgram(outProgram);
458    EXPECT_EQ(CL_SUCCESS, retVal);
459}
460
461TEST(clGetProgramBuildInfoTest, givenMultiDeviceProgramWhenBuildingForSpecificDevicesThenOnlySpecificDevicesAndTheirSubDevicesReportBuildStatus) {
462    MockProgram *pProgram = nullptr;
463    std::unique_ptr<char[]> pSource = nullptr;
464    size_t sourceSize = 0;
465    std::string testFile;
466
467    KernelBinaryHelper kbHelper("CopyBuffer_simd16");
468
469    testFile.append(clFiles);
470    testFile.append("CopyBuffer_simd16.cl");
471
472    pSource = loadDataFromFile(
473        testFile.c_str(),
474        sourceSize);
475
476    ASSERT_NE(0u, sourceSize);
477    ASSERT_NE(nullptr, pSource);
478
479    const char *sources[1] = {pSource.get()};
480
481    MockUnrestrictiveContextMultiGPU context;
482    cl_int retVal = CL_INVALID_PROGRAM;
483
484    pProgram = Program::create<MockProgram>(
485        &context,
486        1,
487        sources,
488        &sourceSize,
489        retVal);
490
491    EXPECT_NE(nullptr, pProgram);
492    ASSERT_EQ(CL_SUCCESS, retVal);
493
494    cl_build_status buildStatus;
495    cl_program_binary_type binaryType;
496    cl_program_binary_type expectedBinaryType = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
497    for (const auto &device : context.getDevices()) {
498        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
499        EXPECT_EQ(CL_SUCCESS, retVal);
500        EXPECT_EQ(CL_BUILD_NONE, buildStatus);
501    }
502
503    cl_device_id devicesForBuild[] = {context.getDevice(1), context.getDevice(3)};
504    cl_device_id associatedSubDevices[] = {context.getDevice(4), context.getDevice(5)};
505    cl_device_id devicesNotForBuild[] = {context.getDevice(0), context.getDevice(2)};
506
507    retVal = clBuildProgram(
508        pProgram,
509        2,
510        devicesForBuild,
511        nullptr,
512        nullptr,
513        nullptr);
514
515    ASSERT_EQ(CL_SUCCESS, retVal);
516
517    for (const auto &device : devicesForBuild) {
518        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
519        EXPECT_EQ(CL_SUCCESS, retVal);
520        EXPECT_EQ(CL_BUILD_SUCCESS, buildStatus);
521        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BINARY_TYPE, sizeof(binaryType), &binaryType, NULL);
522        EXPECT_EQ(CL_SUCCESS, retVal);
523        EXPECT_EQ(expectedBinaryType, binaryType);
524    }
525    for (const auto &device : associatedSubDevices) {
526        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
527        EXPECT_EQ(CL_SUCCESS, retVal);
528        EXPECT_EQ(CL_BUILD_SUCCESS, buildStatus);
529        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BINARY_TYPE, sizeof(binaryType), &binaryType, NULL);
530        EXPECT_EQ(CL_SUCCESS, retVal);
531        EXPECT_EQ(expectedBinaryType, binaryType);
532    }
533    for (const auto &device : devicesNotForBuild) {
534        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
535        EXPECT_EQ(CL_SUCCESS, retVal);
536        EXPECT_EQ(CL_BUILD_NONE, buildStatus);
537    }
538
539    retVal = clReleaseProgram(pProgram);
540    EXPECT_EQ(CL_SUCCESS, retVal);
541}
542
543TEST(clGetProgramBuildInfoTest, givenMultiDeviceProgramWhenBuildingWithoutInputDevicesThenAllDevicesReportBuildStatus) {
544    MockProgram *pProgram = nullptr;
545    std::unique_ptr<char[]> pSource = nullptr;
546    size_t sourceSize = 0;
547    std::string testFile;
548
549    KernelBinaryHelper kbHelper("CopyBuffer_simd16");
550
551    testFile.append(clFiles);
552    testFile.append("CopyBuffer_simd16.cl");
553
554    pSource = loadDataFromFile(
555        testFile.c_str(),
556        sourceSize);
557
558    ASSERT_NE(0u, sourceSize);
559    ASSERT_NE(nullptr, pSource);
560
561    const char *sources[1] = {pSource.get()};
562
563    MockUnrestrictiveContextMultiGPU context;
564    cl_int retVal = CL_INVALID_PROGRAM;
565
566    pProgram = Program::create<MockProgram>(
567        &context,
568        1,
569        sources,
570        &sourceSize,
571        retVal);
572
573    EXPECT_NE(nullptr, pProgram);
574    ASSERT_EQ(CL_SUCCESS, retVal);
575
576    cl_build_status buildStatus;
577    cl_program_binary_type binaryType;
578    cl_program_binary_type expectedBinaryType = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
579    for (const auto &device : context.getDevices()) {
580        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
581        EXPECT_EQ(CL_SUCCESS, retVal);
582        EXPECT_EQ(CL_BUILD_NONE, buildStatus);
583    }
584
585    retVal = clBuildProgram(
586        pProgram,
587        0,
588        nullptr,
589        nullptr,
590        nullptr,
591        nullptr);
592
593    ASSERT_EQ(CL_SUCCESS, retVal);
594
595    for (const auto &device : context.getDevices()) {
596        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BUILD_STATUS, sizeof(buildStatus), &buildStatus, NULL);
597        EXPECT_EQ(CL_SUCCESS, retVal);
598        EXPECT_EQ(CL_BUILD_SUCCESS, buildStatus);
599        retVal = clGetProgramBuildInfo(pProgram, device, CL_PROGRAM_BINARY_TYPE, sizeof(binaryType), &binaryType, NULL);
600        EXPECT_EQ(CL_SUCCESS, retVal);
601        EXPECT_EQ(expectedBinaryType, binaryType);
602    }
603
604    retVal = clReleaseProgram(pProgram);
605    EXPECT_EQ(CL_SUCCESS, retVal);
606}
607
608} // namespace ULT
609