1/*
2 * Copyright (C) 2018-2021 Intel Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 */
7
8#include "shared/source/device/device.h"
9#include "shared/test/unit_test/utilities/base_object_utils.h"
10
11#include "opencl/source/context/context.h"
12#include "opencl/source/helpers/base_object.h"
13#include "opencl/test/unit_test/mocks/mock_platform.h"
14#include "opencl/test/unit_test/test_macros/test_checks_ocl.h"
15
16#include "cl_api_tests.h"
17
18using namespace NEO;
19
20struct clCreatePipeTests : api_tests {
21    VariableBackup<bool> supportsPipesBackup{&defaultHwInfo->capabilityTable.supportsPipes, true};
22};
23
24namespace ClCreatePipeTests {
25
26class clCreatePipeWithParamTests : public ApiFixture<>, public testing::TestWithParam<uint64_t> {
27    void SetUp() override {
28        ApiFixture::SetUp();
29    }
30    void TearDown() override {
31        ApiFixture::TearDown();
32    }
33    VariableBackup<bool> supportsPipesBackup{&defaultHwInfo->capabilityTable.supportsPipes, true};
34};
35
36class clCreatePipeWithParamNegativeTests : public ApiFixture<>, public testing::TestWithParam<uint64_t> {
37    void SetUp() override {
38        ApiFixture::SetUp();
39    }
40    void TearDown() override {
41        ApiFixture::TearDown();
42    }
43    VariableBackup<bool> supportsPipesBackup{&defaultHwInfo->capabilityTable.supportsPipes, true};
44};
45
46TEST_P(clCreatePipeWithParamTests, GivenValidFlagsWhenCreatingPipeThenPipeIsCreatedAndSuccessIsReturned) {
47    cl_mem_flags flags = GetParam();
48
49    auto pipe = clCreatePipe(pContext, flags, 1, 20, nullptr, &retVal);
50    EXPECT_NE(nullptr, pipe);
51    EXPECT_EQ(CL_SUCCESS, retVal);
52
53    clReleaseMemObject(pipe);
54}
55
56TEST_P(clCreatePipeWithParamNegativeTests, GivenInalidFlagsWhenCreatingPipeThenInvalidValueErrorIsReturned) {
57    cl_mem_flags flags = GetParam();
58
59    auto pipe = clCreatePipe(pContext, flags, 1, 20, nullptr, &retVal);
60    EXPECT_EQ(nullptr, pipe);
61    EXPECT_EQ(CL_INVALID_VALUE, retVal);
62
63    clReleaseMemObject(pipe);
64}
65
66static cl_mem_flags validFlags[] = {
67    0,
68    CL_MEM_READ_WRITE,
69    CL_MEM_HOST_NO_ACCESS,
70    CL_MEM_READ_WRITE | CL_MEM_HOST_NO_ACCESS,
71};
72
73static cl_mem_flags invalidFlags[] = {
74    CL_MEM_READ_WRITE | CL_MEM_HOST_READ_ONLY,
75    CL_MEM_WRITE_ONLY,
76    CL_MEM_READ_ONLY | CL_MEM_HOST_WRITE_ONLY,
77    CL_MEM_HOST_READ_ONLY,
78    CL_MEM_HOST_WRITE_ONLY,
79    CL_MEM_USE_HOST_PTR,
80    CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE,
81    CL_MEM_COPY_HOST_PTR,
82    CL_MEM_ALLOC_HOST_PTR,
83    CL_MEM_COPY_HOST_PTR | CL_MEM_ALLOC_HOST_PTR,
84    CL_MEM_READ_ONLY | CL_MEM_WRITE_ONLY,
85    CL_MEM_READ_WRITE | CL_MEM_READ_ONLY,
86    CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY,
87    CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS,
88    CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_WRITE_ONLY,
89    CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_NO_ACCESS,
90    CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR,
91    CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR,
92};
93
94INSTANTIATE_TEST_CASE_P(
95    CreatePipeCheckFlags,
96    clCreatePipeWithParamTests,
97    testing::ValuesIn(validFlags));
98
99INSTANTIATE_TEST_CASE_P(
100    CreatePipeCheckFlagsNegative,
101    clCreatePipeWithParamNegativeTests,
102    testing::ValuesIn(invalidFlags));
103
104TEST_F(clCreatePipeTests, GivenValidFlagsAndNullReturnWhenCreatingPipeThenPipeIsCreated) {
105    cl_mem_flags flags = CL_MEM_READ_WRITE;
106    auto pipe = clCreatePipe(pContext, flags, 1, 20, nullptr, nullptr);
107
108    EXPECT_NE(nullptr, pipe);
109
110    clReleaseMemObject(pipe);
111}
112
113TEST_F(clCreatePipeTests, GivenPipePacketSizeZeroWhenCreatingPipeThenInvalidPipeSizeErrorIsReturned) {
114    cl_mem_flags flags = CL_MEM_READ_WRITE;
115    auto pipe = clCreatePipe(pContext, flags, 0, 20, nullptr, &retVal);
116
117    EXPECT_EQ(nullptr, pipe);
118    EXPECT_EQ(CL_INVALID_PIPE_SIZE, retVal);
119
120    clReleaseMemObject(pipe);
121}
122
123TEST_F(clCreatePipeTests, GivenPipeMaxSizeZeroWhenCreatingPipeThenInvalidPipeSizeErrorIsReturned) {
124    cl_mem_flags flags = CL_MEM_READ_WRITE;
125    auto pipe = clCreatePipe(pContext, flags, 1, 0, nullptr, &retVal);
126
127    EXPECT_EQ(nullptr, pipe);
128    EXPECT_EQ(CL_INVALID_PIPE_SIZE, retVal);
129
130    clReleaseMemObject(pipe);
131}
132
133TEST_F(clCreatePipeTests, GivenPipePropertiesNotNullWhenCreatingPipeThenInvalidValueErrorIsReturned) {
134    cl_mem_flags flags = CL_MEM_READ_WRITE;
135    cl_pipe_properties properties = {0};
136    auto pipe = clCreatePipe(pContext, flags, 1, 20, &properties, &retVal);
137
138    EXPECT_EQ(nullptr, pipe);
139    EXPECT_EQ(CL_INVALID_VALUE, retVal);
140
141    clReleaseMemObject(pipe);
142}
143
144TEST_F(clCreatePipeTests, GivenDeviceNotSupportingPipesWhenCreatingPipeThenInvalidOperationErrorIsReturned) {
145    auto hardwareInfo = *defaultHwInfo;
146    hardwareInfo.capabilityTable.supportsPipes = false;
147
148    auto pClDevice = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(&hardwareInfo, 0));
149    MockContext mockContext{pClDevice.get(), false};
150
151    auto pipe = clCreatePipe(&mockContext, 0, 1, 20, nullptr, &retVal);
152    EXPECT_EQ(nullptr, pipe);
153    EXPECT_EQ(CL_INVALID_OPERATION, retVal);
154}
155
156TEST_F(clCreatePipeTests, GivenPipePacketSizeGreaterThanAllowedWhenCreatingPipeThenInvalidPipeSizeErrorIsReturned) {
157    cl_uint packetSize = pContext->getDevice(0)->getDeviceInfo().pipeMaxPacketSize;
158    cl_mem_flags flags = CL_MEM_READ_WRITE;
159
160    auto pipe = clCreatePipe(pContext, flags, packetSize, 20, nullptr, &retVal);
161    EXPECT_NE(nullptr, pipe);
162    EXPECT_EQ(CL_SUCCESS, retVal);
163
164    clReleaseMemObject(pipe);
165
166    packetSize += 1;
167    pipe = clCreatePipe(pContext, flags, packetSize, 20, nullptr, &retVal);
168
169    EXPECT_EQ(nullptr, pipe);
170    EXPECT_EQ(CL_INVALID_PIPE_SIZE, retVal);
171
172    clReleaseMemObject(pipe);
173}
174
175TEST_F(clCreatePipeTests, GivenNullContextWhenCreatingPipeThenInvalidContextErrorIsReturned) {
176
177    auto pipe = clCreatePipe(nullptr, 0, 1, 20, nullptr, &retVal);
178
179    EXPECT_EQ(nullptr, pipe);
180    EXPECT_EQ(CL_INVALID_CONTEXT, retVal);
181
182    clReleaseMemObject(pipe);
183}
184
185TEST(clCreatePipeTest, givenPlatformWithoutDevicesWhenClCreatePipeIsCalledThenDeviceIsTakenFromContext) {
186    auto executionEnvironment = platform()->peekExecutionEnvironment();
187    executionEnvironment->initializeMemoryManager();
188    executionEnvironment->prepareRootDeviceEnvironments(1);
189    auto device = std::make_unique<ClDevice>(*Device::create<RootDevice>(executionEnvironment, 0u), platform());
190    const ClDeviceInfo &devInfo = device->getDeviceInfo();
191    if (devInfo.svmCapabilities == 0 || device->getHardwareInfo().capabilityTable.supportsPipes == false) {
192        GTEST_SKIP();
193    }
194    cl_device_id clDevice = device.get();
195    cl_int retVal;
196    auto context = ReleaseableObjectPtr<Context>(Context::create<Context>(nullptr, ClDeviceVector(&clDevice, 1), nullptr, nullptr, retVal));
197    EXPECT_EQ(CL_SUCCESS, retVal);
198
199    EXPECT_EQ(0u, platform()->getNumDevices());
200    cl_uint packetSize = context->getDevice(0)->getDeviceInfo().pipeMaxPacketSize;
201    cl_mem_flags flags = CL_MEM_READ_WRITE;
202
203    auto pipe = clCreatePipe(context.get(), flags, packetSize, 20, nullptr, &retVal);
204    EXPECT_NE(nullptr, pipe);
205    EXPECT_EQ(CL_SUCCESS, retVal);
206
207    clReleaseMemObject(pipe);
208}
209} // namespace ClCreatePipeTests
210