blob: 45b571301d519e5029f0303be623cf97effde4ab [file] [log] [blame]
Austin Engcc2516a2023-10-17 20:57:54 +00001//* Copyright 2017 The Dawn & Tint Authors
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04002//*
Austin Engcc2516a2023-10-17 20:57:54 +00003//* Redistribution and use in source and binary forms, with or without
4//* modification, are permitted provided that the following conditions are met:
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04005//*
Austin Engcc2516a2023-10-17 20:57:54 +00006//* 1. Redistributions of source code must retain the above copyright notice, this
7//* list of conditions and the following disclaimer.
Corentin Wallezf07e3bd2017-04-20 14:38:20 -04008//*
Austin Engcc2516a2023-10-17 20:57:54 +00009//* 2. Redistributions in binary form must reproduce the above copyright notice,
10//* this list of conditions and the following disclaimer in the documentation
11//* and/or other materials provided with the distribution.
12//*
13//* 3. Neither the name of the copyright holder nor the names of its
14//* contributors may be used to endorse or promote products derived from
15//* this software without specific prior written permission.
16//*
17//* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18//* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19//* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20//* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21//* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22//* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23//* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24//* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25//* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26//* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040027
fujunwei16ae3b82021-12-15 04:35:26 +000028{% set API = metadata.api.upper() %}
29{% set api = API.lower() %}
30#ifndef MOCK_{{API}}_H
31#define MOCK_{{API}}_H
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040032
fujunwei16ae3b82021-12-15 04:35:26 +000033{% set Prefix = metadata.proc_table_prefix %}
34{% set prefix = Prefix.lower() %}
dan sinclaird0fb4a32022-04-19 14:24:04 +000035#include "dawn/{{prefix}}_proc_table.h"
36#include "dawn/{{api}}.h"
Corentin Wallez96496822019-10-15 11:44:38 +000037#include <gmock/gmock.h>
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040038
Loko Kungd46120e2024-03-01 08:51:34 +000039#include <atomic>
Corentin Wallez944b60f2017-05-29 11:33:33 -070040#include <memory>
41
Loko Kungd46120e2024-03-01 08:51:34 +000042#include "dawn/common/FutureUtils.h"
43
Corentin Wallez1b7c5e32017-05-16 22:05:51 +020044// An abstract base class representing a proc table so that API calls can be mocked. Most API calls
45// are directly represented by a delete virtual method but others need minimal state tracking to be
46// useful as mocks.
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040047class ProcTableAsClass {
48 public:
49 virtual ~ProcTableAsClass();
50
fujunwei16ae3b82021-12-15 04:35:26 +000051 void GetProcTable({{Prefix}}ProcTable* table);
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040052
Corentin Wallez1b7c5e32017-05-16 22:05:51 +020053 // Creates an object that can be returned by a mocked call as in WillOnce(Return(foo)).
54 // It returns an object of the write type that isn't equal to any previously returned object.
55 // Otherwise some mock expectation could be triggered by two different objects having the same
56 // value.
Corentin Wallezf07e3bd2017-04-20 14:38:20 -040057 {% for type in by_category["object"] %}
58 {{as_cType(type.name)}} GetNew{{type.name.CamelCase()}}();
59 {% endfor %}
60
Loko Kungd46120e2024-03-01 08:51:34 +000061 //* Generate the older Call*Callback if there is no Future call equivalent.
62 //* Includes:
63 //* - setDeviceLostCallback
64 //* - setUncapturedErrorCallback
65 //* - setLoggingCallback
Loko Kung0a552b42024-04-10 03:39:38 +000066 {%- set LegacyCallbackFunctions = ['set uncaptured error callback', 'set logging callback'] %}
67
68 //* Manually implemented mock functions due to incompatibility.
69 {% set ManuallyMockedFunctions = ['set device lost callback'] %}
Loko Kungd46120e2024-03-01 08:51:34 +000070
71 {%- for type in by_category["object"] %}
Austin Eng8d38c012020-12-17 17:59:37 +000072
Corentin Wallez4910ae72024-04-18 16:55:19 +000073 virtual void {{as_MethodSuffix(type.name, Name("add ref"))}}({{as_cType(type.name)}} self) = 0;
Corentin Wallez1b7c5e32017-05-16 22:05:51 +020074 virtual void {{as_MethodSuffix(type.name, Name("release"))}}({{as_cType(type.name)}} self) = 0;
Loko Kung0a552b42024-04-10 03:39:38 +000075 {% for method in type.methods if method.name.get() not in ManuallyMockedFunctions %}
Loko Kungd46120e2024-03-01 08:51:34 +000076 {% set Suffix = as_CppMethodSuffix(type.name, method.name) %}
Loko Kung4e635252024-05-08 04:33:44 +000077 {% if not has_callback_arguments(method) and not has_callback_info(method) and not has_callbackInfoStruct(method) %}
Loko Kungd46120e2024-03-01 08:51:34 +000078 virtual {{as_cType(method.return_type.name)}} {{Suffix}}(
79 {{-as_cType(type.name)}} {{as_varName(type.name)}}
80 {%- for arg in method.arguments -%}
81 , {{as_annotated_cType(arg)}}
82 {%- endfor -%}
83 ) = 0;
84 {% else %}
85 //* For functions with callbacks, store callback and userdata and call the On* method.
86 {{as_cType(method.return_type.name)}} {{Suffix}}(
87 {{-as_cType(type.name)}} {{as_varName(type.name)}}
88 {%- for arg in method.arguments -%}
89 , {{as_annotated_cType(arg)}}
90 {%- endfor -%}
91 );
92 {% endif %}
93 {% endfor %}
Austin Eng8d38c012020-12-17 17:59:37 +000094
Loko Kung4e635252024-05-08 04:33:44 +000095 {% for method in type.methods if has_callbackInfoStruct(method) %}
96 {% set Suffix = as_CppMethodSuffix(type.name, method.name) %}
97 //* The virtual function to call after saving the callback and userdata in the proc.
98 //* This function can be mocked.
99 virtual void On{{Suffix}}(
100 {{-as_cType(type.name)}} {{as_varName(type.name)}}
101 {%- for arg in method.arguments -%}
102 , {{as_annotated_cType(arg)}}
103 {%- endfor -%}
104 ) = 0;
105 {% set CallbackInfoType = (method.arguments|last).type %}
106 {% set CallbackType = (CallbackInfoType.members|first).type %}
107 void Call{{Suffix}}Callback(
108 {{-as_cType(type.name)}} {{as_varName(type.name)}}
109 {%- for arg in CallbackType.arguments -%}
110 , {{as_annotated_cType(arg)}}
111 {%- endfor -%}
112 );
113 {% endfor %}
114
Loko Kungd46120e2024-03-01 08:51:34 +0000115 {%- for method in type.methods if has_callback_info(method) or method.name.get() in LegacyCallbackFunctions %}
116
117 {% set Suffix = as_CppMethodSuffix(type.name, method.name) %}
Austin Eng8d38c012020-12-17 17:59:37 +0000118 //* The virtual function to call after saving the callback and userdata in the proc.
119 //* This function can be mocked.
Loko Kungd46120e2024-03-01 08:51:34 +0000120 virtual void On{{Suffix}}(
Austin Eng8d38c012020-12-17 17:59:37 +0000121 {{-as_cType(type.name)}} {{as_varName(type.name)}}
122 {%- for arg in method.arguments -%}
123 , {{as_annotated_cType(arg)}}
124 {%- endfor -%}
125 ) = 0;
Loko Kungd46120e2024-03-01 08:51:34 +0000126 {% for arg in method.arguments %}
127 {% if arg.name.get() == 'callback info' %}
128 {% for callback in types[arg.type.name.get()].members if callback.type.category == 'function pointer' %}
129 void Call{{Suffix + callback.name.CamelCase()}}(
130 {{-as_cType(type.name)}} {{as_varName(type.name)}}
131 {%- for arg in callback.type.arguments -%}
132 {%- if not loop.last -%}, {{as_annotated_cType(arg)}}{%- endif -%}
133 {%- endfor -%}
134 );
135 {% endfor %}
136 {% elif arg.type.category == 'function pointer' %}
137 void Call{{Suffix + arg.name.CamelCase()}}(
138 {{-as_cType(type.name)}} {{as_varName(type.name)}}
139 {%- for arg in arg.type.arguments -%}
140 {%- if not loop.last -%}, {{as_annotated_cType(arg)}}{%- endif -%}
141 {%- endfor -%}
142 );
143 {% endif %}
Austin Eng8d38c012020-12-17 17:59:37 +0000144 {% endfor %}
145 {% endfor %}
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400146 {% endfor %}
147
Loko Kung0a552b42024-04-10 03:39:38 +0000148 // Manually implement device lost related callback helpers for testing.
149 void DeviceSetDeviceLostCallback(WGPUDevice device,
150 WGPUDeviceLostCallback callback,
151 void* userdata);
152 virtual void OnDeviceSetDeviceLostCallback(WGPUDevice device,
153 WGPUDeviceLostCallback callback,
154 void* userdata) = 0;
155 void CallDeviceSetDeviceLostCallbackCallback(WGPUDevice device,
156 WGPUDeviceLostReason reason,
157 char const* message);
158
Corentin Wallez1b7c5e32017-05-16 22:05:51 +0200159 struct Object {
160 ProcTableAsClass* procs = nullptr;
Austin Eng8d38c012020-12-17 17:59:37 +0000161 {% for type in by_category["object"] %}
Loko Kungd46120e2024-03-01 08:51:34 +0000162 {% for method in type.methods if has_callback_info(method) or method.name.get() in LegacyCallbackFunctions %}
163 void* m{{as_CppMethodSuffix(type.name, method.name)}}Userdata = 0;
164 {% for arg in method.arguments %}
165 {% if arg.name.get() == 'callback info' %}
166 {% for callback in types[arg.type.name.get()].members if callback.type.category == 'function pointer' %}
167 {{as_cType(callback.type.name)}} m{{as_CppMethodSuffix(type.name, method.name)}}{{callback.name.CamelCase()}} = nullptr;
168 {% endfor %}
169 {% elif arg.type.category == 'function pointer' %}
170 {{as_cType(arg.type.name)}} m{{as_CppMethodSuffix(type.name, method.name)}}{{arg.name.CamelCase()}} = nullptr;
171 {% endif %}
Austin Eng8d38c012020-12-17 17:59:37 +0000172 {% endfor %}
173 {% endfor %}
Loko Kung4e635252024-05-08 04:33:44 +0000174 {% for method in type.methods if has_callbackInfoStruct(method) %}
175 {% set CallbackInfoType = (method.arguments|last).type %}
176 {% set CallbackType = (CallbackInfoType.members|first).type %}
177 void* m{{as_CppMethodSuffix(type.name, method.name)}}Userdata1 = 0;
178 void* m{{as_CppMethodSuffix(type.name, method.name)}}Userdata2 = 0;
179 {{as_cType(CallbackType.name)}} m{{as_CppMethodSuffix(type.name, method.name)}}Callback = nullptr;
180 {% endfor %}
Austin Eng8d38c012020-12-17 17:59:37 +0000181 {% endfor %}
Loko Kung0a552b42024-04-10 03:39:38 +0000182 // Manually implement device lost related callback helpers for testing.
183 WGPUDeviceLostCallback mDeviceLostOldCallback = nullptr;
184 WGPUDeviceLostCallbackNew mDeviceLostCallback = nullptr;
185 void* mDeviceLostUserdata = 0;
Corentin Wallez1b7c5e32017-05-16 22:05:51 +0200186 };
187
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400188 private:
Corentin Wallez1b7c5e32017-05-16 22:05:51 +0200189 // Remembers the values returned by GetNew* so they can be freed.
Corentin Wallez42dbde12017-11-23 16:04:26 -0500190 std::vector<std::unique_ptr<Object>> mObjects;
Loko Kungd46120e2024-03-01 08:51:34 +0000191 // Increasing futureID for testing purposes.
192 std::atomic<dawn::FutureID> mNextFutureID = 1;
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400193};
194
195class MockProcTable : public ProcTableAsClass {
196 public:
Corentin Wallez82b65732018-08-22 15:37:29 +0200197 MockProcTable();
Corentin Wallez3741f732020-04-16 18:08:23 +0000198 ~MockProcTable() override;
Corentin Wallez82b65732018-08-22 15:37:29 +0200199
Corentin Wallezd754fb22019-03-28 10:44:41 +0000200 void IgnoreAllReleaseCalls();
201
Loko Kungd46120e2024-03-01 08:51:34 +0000202 {%- for type in by_category["object"] %}
203
Corentin Wallez4910ae72024-04-18 16:55:19 +0000204 MOCK_METHOD(void, {{as_MethodSuffix(type.name, Name("add ref"))}}, ({{as_cType(type.name)}} self), (override));
Loko Kungd46120e2024-03-01 08:51:34 +0000205 MOCK_METHOD(void, {{as_MethodSuffix(type.name, Name("release"))}}, ({{as_cType(type.name)}} self), (override));
Loko Kung4e635252024-05-08 04:33:44 +0000206 {% for method in type.methods if not has_callback_arguments(method) and not has_callback_info(method) and not has_callbackInfoStruct(method) %}
Corentin Wallezf9412052020-04-16 16:39:06 +0000207 MOCK_METHOD({{as_cType(method.return_type.name)}},{{" "}}
208 {{-as_MethodSuffix(type.name, method.name)}}, (
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400209 {{-as_cType(type.name)}} {{as_varName(type.name)}}
210 {%- for arg in method.arguments -%}
211 , {{as_annotated_cType(arg)}}
212 {%- endfor -%}
Corentin Wallezf9412052020-04-16 16:39:06 +0000213 ), (override));
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400214 {% endfor %}
215
Loko Kungd46120e2024-03-01 08:51:34 +0000216 {% for method in type.methods if has_callback_info(method) or method.name.get() in LegacyCallbackFunctions %}
217 MOCK_METHOD(void,{{" "-}}
218 On{{as_CppMethodSuffix(type.name, method.name)}}, (
Austin Eng8d38c012020-12-17 17:59:37 +0000219 {{-as_cType(type.name)}} {{as_varName(type.name)}}
220 {%- for arg in method.arguments -%}
221 , {{as_annotated_cType(arg)}}
222 {%- endfor -%}
223 ), (override));
224 {% endfor %}
Loko Kung4e635252024-05-08 04:33:44 +0000225 {% for method in type.methods if has_callbackInfoStruct(method) %}
226 MOCK_METHOD(void,{{" "-}}
227 On{{as_CppMethodSuffix(type.name, method.name)}}, (
228 {{-as_cType(type.name)}} {{as_varName(type.name)}}
229 {%- for arg in method.arguments -%}
230 , {{as_annotated_cType(arg)}}
231 {%- endfor -%}
232 ), (override));
233 {% endfor %}
Austin Eng8d38c012020-12-17 17:59:37 +0000234 {% endfor %}
Loko Kung0a552b42024-04-10 03:39:38 +0000235
236 // Manually implement device lost related callback helpers for testing.
237 MOCK_METHOD(void,
238 OnDeviceSetDeviceLostCallback,
239 (WGPUDevice device, WGPUDeviceLostCallback callback, void* userdata),
240 (override));
Corentin Wallezf07e3bd2017-04-20 14:38:20 -0400241};
242
fujunwei16ae3b82021-12-15 04:35:26 +0000243#endif // MOCK_{{API}}_H