1 /*
2  * Copyright (C) 2020-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #pragma once
9 #include "shared/test/common/mocks/mock_cif.h"
10 #include "shared/test/common/mocks/mock_compiler_interface.h"
11 #include "shared/test/common/test_macros/mock_method_macros.h"
12 
13 #include "level_zero/core/source/module/module_imp.h"
14 #include "level_zero/core/test/unit_tests/mock.h"
15 #include "level_zero/core/test/unit_tests/white_box.h"
16 
17 #include "gtest/gtest.h"
18 namespace L0 {
19 namespace ult {
20 
21 template <>
22 struct WhiteBox<::L0::Module> : public ::L0::ModuleImp {
23     using BaseClass = ::L0::ModuleImp;
24     using BaseClass::BaseClass;
25     using BaseClass::copyPatchedSegments;
26     using BaseClass::device;
27     using BaseClass::exportedFunctionsSurface;
28     using BaseClass::isFullyLinked;
29     using BaseClass::kernelImmDatas;
30     using BaseClass::symbols;
31     using BaseClass::translationUnit;
32     using BaseClass::type;
33     using BaseClass::unresolvedExternalsInfo;
34 };
35 
36 using Module = WhiteBox<::L0::Module>;
37 
38 template <>
39 struct Mock<Module> : public Module {
40 
41     Mock(::L0::Device *device, ModuleBuildLog *moduleBuildLog, ModuleType type) : WhiteBox(device, moduleBuildLog, type) {}
42     Mock(::L0::Device *device, ModuleBuildLog *moduleBuildLog) : Mock(device, moduleBuildLog, ModuleType::User){};
43 
44     ADDMETHOD_NOBASE(createKernel, ze_result_t, ZE_RESULT_SUCCESS, (const ze_kernel_desc_t *desc, ze_kernel_handle_t *phFunction));
45     ADDMETHOD_NOBASE(destroy, ze_result_t, ZE_RESULT_SUCCESS, ());
46     ADDMETHOD_NOBASE(getFunctionPointer, ze_result_t, ZE_RESULT_SUCCESS, (const char *pKernelName, void **pfnFunction));
47     ADDMETHOD_NOBASE(getNativeBinary, ze_result_t, ZE_RESULT_SUCCESS, (size_t * pSize, uint8_t *pModuleNativeBinary));
48     ADDMETHOD_CONST_NOBASE(getKernelImmutableData, const L0::KernelImmutableData *, nullptr, (const char *functionName));
49     ADDMETHOD_CONST_NOBASE(getMaxGroupSize, uint32_t, 256, ());
50     ADDMETHOD_NOBASE(getKernelNames, ze_result_t, ZE_RESULT_SUCCESS, (uint32_t * pCount, const char **pNames));
51     ADDMETHOD_NOBASE(performDynamicLink, ze_result_t, ZE_RESULT_SUCCESS,
52                      (uint32_t numModules, ze_module_handle_t *phModules, ze_module_build_log_handle_t *phLinkLog));
53     ADDMETHOD_NOBASE(getProperties, ze_result_t, ZE_RESULT_SUCCESS, (ze_module_properties_t * pModuleProperties));
54     ADDMETHOD_NOBASE(getGlobalPointer, ze_result_t, ZE_RESULT_SUCCESS, (const char *pGlobalName, size_t *pSize, void **pPtr));
55     ADDMETHOD_CONST_NOBASE(isDebugEnabled, bool, false, ());
56 };
57 
58 struct MockModuleTranslationUnit : public L0::ModuleTranslationUnit {
59     MockModuleTranslationUnit(L0::Device *device) : L0::ModuleTranslationUnit(device) {
60     }
61 
62     bool processUnpackedBinary() override {
63         return true;
64     }
65 };
66 
67 struct MockModule : public L0::ModuleImp {
68     using ModuleImp::debugEnabled;
69     using ModuleImp::kernelImmDatas;
70     using ModuleImp::translationUnit;
71 
72     MockModule(L0::Device *device,
73                L0::ModuleBuildLog *moduleBuildLog,
74                L0::ModuleType type) : ModuleImp(device, moduleBuildLog, type) {
75         maxGroupSize = 32;
76     };
77 
78     ~MockModule() = default;
79 
80     const KernelImmutableData *getKernelImmutableData(const char *functionName) const override {
81         return kernelImmData;
82     }
83 
84     KernelImmutableData *kernelImmData = nullptr;
85 };
86 
87 struct MockCompilerInterface : public NEO::CompilerInterface {
88     NEO::TranslationOutput::ErrorCode build(const NEO::Device &device,
89                                             const NEO::TranslationInput &input,
90                                             NEO::TranslationOutput &output) override {
91 
92         receivedApiOptions = input.apiOptions.begin();
93         inputInternalOptions = input.internalOptions.begin();
94 
95         if (failBuild) {
96             return NEO::TranslationOutput::ErrorCode::BuildFailure;
97         }
98         return NEO::TranslationOutput::ErrorCode::Success;
99     }
100     NEO::TranslationOutput::ErrorCode link(const NEO::Device &device,
101                                            const NEO::TranslationInput &input,
102                                            NEO::TranslationOutput &output) override {
103 
104         receivedApiOptions = input.apiOptions.begin();
105         inputInternalOptions = input.internalOptions.begin();
106 
107         return NEO::TranslationOutput::ErrorCode::Success;
108     }
109 
110     std::string receivedApiOptions;
111     std::string inputInternalOptions;
112     bool failBuild = false;
113 };
114 template <typename T1, typename T2>
115 struct MockCompilerInterfaceWithSpecConstants : public NEO::CompilerInterface {
116     MockCompilerInterfaceWithSpecConstants(uint32_t moduleNumSpecConstants) : moduleNumSpecConstants(moduleNumSpecConstants) {
117     }
118     NEO::TranslationOutput::ErrorCode build(const NEO::Device &device,
119                                             const NEO::TranslationInput &input,
120                                             NEO::TranslationOutput &output) override {
121 
122         EXPECT_EQ(moduleNumSpecConstants, input.specializedValues.size());
123 
124         return NEO::TranslationOutput::ErrorCode::Success;
125     }
126     NEO::TranslationOutput::ErrorCode link(const NEO::Device &device,
127                                            const NEO::TranslationInput &input,
128                                            NEO::TranslationOutput &output) override {
129 
130         EXPECT_EQ(moduleNumSpecConstants, input.specializedValues.size());
131 
132         return NEO::TranslationOutput::ErrorCode::Success;
133     }
134 
135     NEO::TranslationOutput::ErrorCode getSpecConstantsInfo(const NEO::Device &device,
136                                                            ArrayRef<const char> srcSpirV, NEO::SpecConstantInfo &output) override {
137         output.idsBuffer.reset(new NEO::MockCIFBuffer());
138         output.sizesBuffer.reset(new NEO::MockCIFBuffer());
139         for (uint32_t i = 0; i < moduleNumSpecConstants; i++) {
140             output.idsBuffer->PushBackRawCopy(moduleSpecConstantsIds[i]);
141             output.sizesBuffer->PushBackRawCopy(moduleSpecConstantsSizes[i]);
142         }
143         return NEO::TranslationOutput::ErrorCode::Success;
144     }
145     uint32_t moduleNumSpecConstants = 0u;
146     const std::vector<uint32_t> moduleSpecConstantsIds{2, 0, 1, 3, 5, 4};
147     const std::vector<T1> moduleSpecConstantsValuesT1{10, 20, 30};
148     const std::vector<T2> moduleSpecConstantsValuesT2{static_cast<T2>(std::numeric_limits<T1>::max()) + 60u, static_cast<T2>(std::numeric_limits<T1>::max()) + 50u, static_cast<T2>(std::numeric_limits<T1>::max()) + 40u};
149     const std::vector<uint32_t> moduleSpecConstantsSizes{sizeof(T2), sizeof(T1), sizeof(T2), sizeof(T1), sizeof(T2), sizeof(T1)};
150     static_assert(sizeof(T1) < sizeof(T2));
151 };
152 
153 struct MockCompilerInterfaceLinkFailure : public NEO::CompilerInterface {
154     NEO::TranslationOutput::ErrorCode link(const NEO::Device &device,
155                                            const NEO::TranslationInput &input,
156                                            NEO::TranslationOutput &output) override {
157 
158         return NEO::TranslationOutput::ErrorCode::BuildFailure;
159     }
160 };
161 
162 } // namespace ult
163 } // namespace L0
164