1 /*
2  * Copyright (c) 2015-2016 The Khronos Group Inc.
3  * Copyright (c) 2015-2016 Valve Corporation
4  * Copyright (c) 2015-2016 LunarG, Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Author: Chia-I Wu <olvaffe@gmail.com>
19  * Author: Chris Forbes <chrisf@ijw.co.nz>
20  * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
21  * Author: Mark Lobodzinski <mark@lunarg.com>
22  * Author: Mike Stroyan <mike@LunarG.com>
23  * Author: Tobin Ehlis <tobine@google.com>
24  * Author: Tony Barbour <tony@LunarG.com>
25  */
26 
27 #ifndef TEST_COMMON_H
28 #define TEST_COMMON_H
29 
30 #include <assert.h>
31 #include <stdbool.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #ifdef _WIN32
37 #define NOMINMAX
38 // WinSock2.h must be included *BEFORE* windows.h
39 #include <winsock2.h>
40 #endif
41 
42 #include <vulkan/vk_sdk_platform.h>
43 #include <vulkan/vulkan.h>
44 
45 #ifdef _WIN32
46 #pragma warning(push)
47 /*
48     warnings 4251 and 4275 have to do with potential dll-interface mismatch
49     between library (gtest) and users. Since we build the gtest library
50     as part of the test build we know that the dll-interface will match and
51     can disable these warnings.
52  */
53 #pragma warning(disable : 4251)
54 #pragma warning(disable : 4275)
55 #endif
56 
57 // GTest and Xlib collide due to redefinitions of "None" and "Bool"
58 #ifdef VK_USE_PLATFORM_XLIB_KHR
59 #pragma push_macro("None")
60 #pragma push_macro("Bool")
61 #undef None
62 #undef Bool
63 #endif
64 
65 // Use the NDK's header on Android
66 #ifndef __ANDROID__
67 #include "gtest/gtest.h"
68 #else
69 #include "gtest/gtest.h"
70 #endif
71 
72 // Redefine Xlib definitions
73 #ifdef VK_USE_PLATFORM_XLIB_KHR
74 #pragma pop_macro("Bool")
75 #pragma pop_macro("None")
76 #endif
77 
78 #ifdef _WIN32
79 #pragma warning(pop)
80 #endif
81 #include "vktestbinding.h"
82 
83 #define ASSERT_VK_SUCCESS(err) ASSERT_EQ(VK_SUCCESS, err) << vk_result_string(err)
84 
vk_result_string(VkResult err)85 static inline const char *vk_result_string(VkResult err) {
86     switch (err) {
87 #define STR(r) \
88     case r:    \
89         return #r
90         STR(VK_SUCCESS);
91         STR(VK_NOT_READY);
92         STR(VK_TIMEOUT);
93         STR(VK_EVENT_SET);
94         STR(VK_EVENT_RESET);
95         STR(VK_ERROR_INITIALIZATION_FAILED);
96         STR(VK_ERROR_OUT_OF_HOST_MEMORY);
97         STR(VK_ERROR_OUT_OF_DEVICE_MEMORY);
98         STR(VK_ERROR_DEVICE_LOST);
99         STR(VK_ERROR_EXTENSION_NOT_PRESENT);
100         STR(VK_ERROR_LAYER_NOT_PRESENT);
101         STR(VK_ERROR_MEMORY_MAP_FAILED);
102         STR(VK_ERROR_INCOMPATIBLE_DRIVER);
103 #undef STR
104         default:
105             return "UNKNOWN_RESULT";
106     }
107 }
108 
test_error_callback(const char * expr,const char * file,unsigned int line,const char * function)109 static inline void test_error_callback(const char *expr, const char *file, unsigned int line, const char *function) {
110     ADD_FAILURE_AT(file, line) << "Assertion: `" << expr << "'";
111 }
112 
113 #if defined(__linux__) || defined(__APPLE__)
114     /* Linux-specific common code: */
115 
116 #include <pthread.h>
117 
118 // Threads:
119 typedef pthread_t test_platform_thread;
120 
test_platform_thread_create(test_platform_thread * thread,void * (* func)(void *),void * data)121 static inline int test_platform_thread_create(test_platform_thread *thread, void *(*func)(void *), void *data) {
122     pthread_attr_t thread_attr;
123     pthread_attr_init(&thread_attr);
124     return pthread_create(thread, &thread_attr, func, data);
125 }
test_platform_thread_join(test_platform_thread thread,void ** retval)126 static inline int test_platform_thread_join(test_platform_thread thread, void **retval) { return pthread_join(thread, retval); }
127 
128 // Thread IDs:
129 typedef pthread_t test_platform_thread_id;
test_platform_get_thread_id()130 static inline test_platform_thread_id test_platform_get_thread_id() { return pthread_self(); }
131 
132 // Thread mutex:
133 typedef pthread_mutex_t test_platform_thread_mutex;
test_platform_thread_create_mutex(test_platform_thread_mutex * pMutex)134 static inline void test_platform_thread_create_mutex(test_platform_thread_mutex *pMutex) { pthread_mutex_init(pMutex, NULL); }
test_platform_thread_lock_mutex(test_platform_thread_mutex * pMutex)135 static inline void test_platform_thread_lock_mutex(test_platform_thread_mutex *pMutex) { pthread_mutex_lock(pMutex); }
test_platform_thread_unlock_mutex(test_platform_thread_mutex * pMutex)136 static inline void test_platform_thread_unlock_mutex(test_platform_thread_mutex *pMutex) { pthread_mutex_unlock(pMutex); }
test_platform_thread_delete_mutex(test_platform_thread_mutex * pMutex)137 static inline void test_platform_thread_delete_mutex(test_platform_thread_mutex *pMutex) { pthread_mutex_destroy(pMutex); }
138 typedef pthread_cond_t test_platform_thread_cond;
test_platform_thread_init_cond(test_platform_thread_cond * pCond)139 static inline void test_platform_thread_init_cond(test_platform_thread_cond *pCond) { pthread_cond_init(pCond, NULL); }
test_platform_thread_cond_wait(test_platform_thread_cond * pCond,test_platform_thread_mutex * pMutex)140 static inline void test_platform_thread_cond_wait(test_platform_thread_cond *pCond, test_platform_thread_mutex *pMutex) {
141     pthread_cond_wait(pCond, pMutex);
142 }
test_platform_thread_cond_broadcast(test_platform_thread_cond * pCond)143 static inline void test_platform_thread_cond_broadcast(test_platform_thread_cond *pCond) { pthread_cond_broadcast(pCond); }
144 
145 #elif defined(_WIN32)  // defined(__linux__)
146 // Threads:
147 typedef HANDLE test_platform_thread;
test_platform_thread_create(test_platform_thread * thread,void * (* func)(void *),void * data)148 static inline int test_platform_thread_create(test_platform_thread *thread, void *(*func)(void *), void *data) {
149     DWORD threadID;
150     *thread = CreateThread(NULL,  // default security attributes
151                            0,     // use default stack size
152                            (LPTHREAD_START_ROUTINE)func,
153                            data,        // thread function argument
154                            0,           // use default creation flags
155                            &threadID);  // returns thread identifier
156     return (*thread != NULL);
157 }
test_platform_thread_join(test_platform_thread thread,void ** retval)158 static inline int test_platform_thread_join(test_platform_thread thread, void **retval) {
159     return WaitForSingleObject(thread, INFINITE);
160 }
161 
162 // Thread IDs:
163 typedef DWORD test_platform_thread_id;
test_platform_get_thread_id()164 static test_platform_thread_id test_platform_get_thread_id() { return GetCurrentThreadId(); }
165 
166 // Thread mutex:
167 typedef CRITICAL_SECTION test_platform_thread_mutex;
test_platform_thread_create_mutex(test_platform_thread_mutex * pMutex)168 static void test_platform_thread_create_mutex(test_platform_thread_mutex *pMutex) { InitializeCriticalSection(pMutex); }
test_platform_thread_lock_mutex(test_platform_thread_mutex * pMutex)169 static void test_platform_thread_lock_mutex(test_platform_thread_mutex *pMutex) { EnterCriticalSection(pMutex); }
test_platform_thread_unlock_mutex(test_platform_thread_mutex * pMutex)170 static void test_platform_thread_unlock_mutex(test_platform_thread_mutex *pMutex) { LeaveCriticalSection(pMutex); }
test_platform_thread_delete_mutex(test_platform_thread_mutex * pMutex)171 static void test_platform_thread_delete_mutex(test_platform_thread_mutex *pMutex) { DeleteCriticalSection(pMutex); }
172 typedef CONDITION_VARIABLE test_platform_thread_cond;
test_platform_thread_init_cond(test_platform_thread_cond * pCond)173 static void test_platform_thread_init_cond(test_platform_thread_cond *pCond) { InitializeConditionVariable(pCond); }
test_platform_thread_cond_wait(test_platform_thread_cond * pCond,test_platform_thread_mutex * pMutex)174 static void test_platform_thread_cond_wait(test_platform_thread_cond *pCond, test_platform_thread_mutex *pMutex) {
175     SleepConditionVariableCS(pCond, pMutex, INFINITE);
176 }
test_platform_thread_cond_broadcast(test_platform_thread_cond * pCond)177 static void test_platform_thread_cond_broadcast(test_platform_thread_cond *pCond) { WakeAllConditionVariable(pCond); }
178 #else                  // defined(_WIN32)
179 
180 #error The "test_common.h" file must be modified for this OS.
181 
182     // NOTE: In order to support another OS, an #elif needs to be added (above the
183     // "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
184     // contents of this file must be created.
185 
186     // NOTE: Other OS-specific changes are also needed for this OS.  Search for
187     // files with "WIN32" in it, as a quick way to find files that must be changed.
188 
189 #endif  // defined(_WIN32)
190 
191 #endif  // TEST_COMMON_H
192