1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker // system_utils: Defines common utility functions
8*8975f5c5SAndroid Build Coastguard Worker
9*8975f5c5SAndroid Build Coastguard Worker #include "util/test_utils.h"
10*8975f5c5SAndroid Build Coastguard Worker
11*8975f5c5SAndroid Build Coastguard Worker #include <EGL/egl.h>
12*8975f5c5SAndroid Build Coastguard Worker #include <EGL/eglext.h>
13*8975f5c5SAndroid Build Coastguard Worker
14*8975f5c5SAndroid Build Coastguard Worker #include <cstring>
15*8975f5c5SAndroid Build Coastguard Worker #include <fstream>
16*8975f5c5SAndroid Build Coastguard Worker #include <iostream>
17*8975f5c5SAndroid Build Coastguard Worker
18*8975f5c5SAndroid Build Coastguard Worker namespace angle
19*8975f5c5SAndroid Build Coastguard Worker {
20*8975f5c5SAndroid Build Coastguard Worker
21*8975f5c5SAndroid Build Coastguard Worker namespace
22*8975f5c5SAndroid Build Coastguard Worker {
DeleteArg(int * argc,char ** argv,int argIndex)23*8975f5c5SAndroid Build Coastguard Worker void DeleteArg(int *argc, char **argv, int argIndex)
24*8975f5c5SAndroid Build Coastguard Worker {
25*8975f5c5SAndroid Build Coastguard Worker // Shift the remainder of the argv list left by one. Note that argv has (*argc + 1) elements,
26*8975f5c5SAndroid Build Coastguard Worker // the last one always being NULL. The following loop moves the trailing NULL element as well.
27*8975f5c5SAndroid Build Coastguard Worker for (int index = argIndex; index < *argc; ++index)
28*8975f5c5SAndroid Build Coastguard Worker {
29*8975f5c5SAndroid Build Coastguard Worker argv[index] = argv[index + 1];
30*8975f5c5SAndroid Build Coastguard Worker }
31*8975f5c5SAndroid Build Coastguard Worker (*argc)--;
32*8975f5c5SAndroid Build Coastguard Worker }
33*8975f5c5SAndroid Build Coastguard Worker
GetSingleArg(const char * flag,int * argc,char ** argv,int argIndex,ArgHandling handling)34*8975f5c5SAndroid Build Coastguard Worker const char *GetSingleArg(const char *flag,
35*8975f5c5SAndroid Build Coastguard Worker int *argc,
36*8975f5c5SAndroid Build Coastguard Worker char **argv,
37*8975f5c5SAndroid Build Coastguard Worker int argIndex,
38*8975f5c5SAndroid Build Coastguard Worker ArgHandling handling)
39*8975f5c5SAndroid Build Coastguard Worker {
40*8975f5c5SAndroid Build Coastguard Worker if (strstr(argv[argIndex], flag) == argv[argIndex])
41*8975f5c5SAndroid Build Coastguard Worker {
42*8975f5c5SAndroid Build Coastguard Worker const char *ptr = argv[argIndex] + strlen(flag);
43*8975f5c5SAndroid Build Coastguard Worker
44*8975f5c5SAndroid Build Coastguard Worker if (*ptr == '=')
45*8975f5c5SAndroid Build Coastguard Worker {
46*8975f5c5SAndroid Build Coastguard Worker if (handling == ArgHandling::Delete)
47*8975f5c5SAndroid Build Coastguard Worker {
48*8975f5c5SAndroid Build Coastguard Worker DeleteArg(argc, argv, argIndex);
49*8975f5c5SAndroid Build Coastguard Worker }
50*8975f5c5SAndroid Build Coastguard Worker return ptr + 1;
51*8975f5c5SAndroid Build Coastguard Worker }
52*8975f5c5SAndroid Build Coastguard Worker
53*8975f5c5SAndroid Build Coastguard Worker if (*ptr == '\0' && argIndex < *argc - 1)
54*8975f5c5SAndroid Build Coastguard Worker {
55*8975f5c5SAndroid Build Coastguard Worker ptr = argv[argIndex + 1];
56*8975f5c5SAndroid Build Coastguard Worker if (handling == ArgHandling::Delete)
57*8975f5c5SAndroid Build Coastguard Worker {
58*8975f5c5SAndroid Build Coastguard Worker DeleteArg(argc, argv, argIndex);
59*8975f5c5SAndroid Build Coastguard Worker DeleteArg(argc, argv, argIndex);
60*8975f5c5SAndroid Build Coastguard Worker }
61*8975f5c5SAndroid Build Coastguard Worker return ptr;
62*8975f5c5SAndroid Build Coastguard Worker }
63*8975f5c5SAndroid Build Coastguard Worker }
64*8975f5c5SAndroid Build Coastguard Worker
65*8975f5c5SAndroid Build Coastguard Worker return nullptr;
66*8975f5c5SAndroid Build Coastguard Worker }
67*8975f5c5SAndroid Build Coastguard Worker
68*8975f5c5SAndroid Build Coastguard Worker using DisplayTypeInfo = std::pair<const char *, EGLint>;
69*8975f5c5SAndroid Build Coastguard Worker
70*8975f5c5SAndroid Build Coastguard Worker const DisplayTypeInfo kDisplayTypes[] = {
71*8975f5c5SAndroid Build Coastguard Worker {"d3d9", EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE},
72*8975f5c5SAndroid Build Coastguard Worker {"d3d11", EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE},
73*8975f5c5SAndroid Build Coastguard Worker {"gl", EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE},
74*8975f5c5SAndroid Build Coastguard Worker {"gles", EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE},
75*8975f5c5SAndroid Build Coastguard Worker {"metal", EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE},
76*8975f5c5SAndroid Build Coastguard Worker {"null", EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE},
77*8975f5c5SAndroid Build Coastguard Worker {"swiftshader", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
78*8975f5c5SAndroid Build Coastguard Worker {"vulkan", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
79*8975f5c5SAndroid Build Coastguard Worker {"vulkan-null", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
80*8975f5c5SAndroid Build Coastguard Worker {"webgpu", EGL_PLATFORM_ANGLE_TYPE_WEBGPU_ANGLE},
81*8975f5c5SAndroid Build Coastguard Worker };
82*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
83*8975f5c5SAndroid Build Coastguard Worker
GetFileSize(const char * filePath,uint32_t * sizeOut)84*8975f5c5SAndroid Build Coastguard Worker bool GetFileSize(const char *filePath, uint32_t *sizeOut)
85*8975f5c5SAndroid Build Coastguard Worker {
86*8975f5c5SAndroid Build Coastguard Worker std::ifstream stream(filePath);
87*8975f5c5SAndroid Build Coastguard Worker if (!stream)
88*8975f5c5SAndroid Build Coastguard Worker {
89*8975f5c5SAndroid Build Coastguard Worker return false;
90*8975f5c5SAndroid Build Coastguard Worker }
91*8975f5c5SAndroid Build Coastguard Worker
92*8975f5c5SAndroid Build Coastguard Worker stream.seekg(0, std::ios::end);
93*8975f5c5SAndroid Build Coastguard Worker *sizeOut = static_cast<uint32_t>(stream.tellg());
94*8975f5c5SAndroid Build Coastguard Worker return true;
95*8975f5c5SAndroid Build Coastguard Worker }
96*8975f5c5SAndroid Build Coastguard Worker
ReadEntireFileToString(const char * filePath,std::string * contentsOut)97*8975f5c5SAndroid Build Coastguard Worker bool ReadEntireFileToString(const char *filePath, std::string *contentsOut)
98*8975f5c5SAndroid Build Coastguard Worker {
99*8975f5c5SAndroid Build Coastguard Worker std::ifstream stream(filePath);
100*8975f5c5SAndroid Build Coastguard Worker if (!stream)
101*8975f5c5SAndroid Build Coastguard Worker {
102*8975f5c5SAndroid Build Coastguard Worker return false;
103*8975f5c5SAndroid Build Coastguard Worker }
104*8975f5c5SAndroid Build Coastguard Worker
105*8975f5c5SAndroid Build Coastguard Worker stream.seekg(0, std::ios::end);
106*8975f5c5SAndroid Build Coastguard Worker contentsOut->reserve(static_cast<unsigned int>(stream.tellg()));
107*8975f5c5SAndroid Build Coastguard Worker stream.seekg(0, std::ios::beg);
108*8975f5c5SAndroid Build Coastguard Worker
109*8975f5c5SAndroid Build Coastguard Worker contentsOut->assign((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
110*8975f5c5SAndroid Build Coastguard Worker
111*8975f5c5SAndroid Build Coastguard Worker return true;
112*8975f5c5SAndroid Build Coastguard Worker }
113*8975f5c5SAndroid Build Coastguard Worker
114*8975f5c5SAndroid Build Coastguard Worker // static
115*8975f5c5SAndroid Build Coastguard Worker Process::~Process() = default;
116*8975f5c5SAndroid Build Coastguard Worker
ProcessHandle()117*8975f5c5SAndroid Build Coastguard Worker ProcessHandle::ProcessHandle() : mProcess(nullptr) {}
118*8975f5c5SAndroid Build Coastguard Worker
ProcessHandle(Process * process)119*8975f5c5SAndroid Build Coastguard Worker ProcessHandle::ProcessHandle(Process *process) : mProcess(process) {}
120*8975f5c5SAndroid Build Coastguard Worker
ProcessHandle(const std::vector<const char * > & args,ProcessOutputCapture captureOutput)121*8975f5c5SAndroid Build Coastguard Worker ProcessHandle::ProcessHandle(const std::vector<const char *> &args,
122*8975f5c5SAndroid Build Coastguard Worker ProcessOutputCapture captureOutput)
123*8975f5c5SAndroid Build Coastguard Worker : mProcess(LaunchProcess(args, captureOutput))
124*8975f5c5SAndroid Build Coastguard Worker {}
125*8975f5c5SAndroid Build Coastguard Worker
~ProcessHandle()126*8975f5c5SAndroid Build Coastguard Worker ProcessHandle::~ProcessHandle()
127*8975f5c5SAndroid Build Coastguard Worker {
128*8975f5c5SAndroid Build Coastguard Worker reset();
129*8975f5c5SAndroid Build Coastguard Worker }
130*8975f5c5SAndroid Build Coastguard Worker
ProcessHandle(ProcessHandle && other)131*8975f5c5SAndroid Build Coastguard Worker ProcessHandle::ProcessHandle(ProcessHandle &&other) : mProcess(other.mProcess)
132*8975f5c5SAndroid Build Coastguard Worker {
133*8975f5c5SAndroid Build Coastguard Worker other.mProcess = nullptr;
134*8975f5c5SAndroid Build Coastguard Worker }
135*8975f5c5SAndroid Build Coastguard Worker
operator =(ProcessHandle && rhs)136*8975f5c5SAndroid Build Coastguard Worker ProcessHandle &ProcessHandle::operator=(ProcessHandle &&rhs)
137*8975f5c5SAndroid Build Coastguard Worker {
138*8975f5c5SAndroid Build Coastguard Worker std::swap(mProcess, rhs.mProcess);
139*8975f5c5SAndroid Build Coastguard Worker return *this;
140*8975f5c5SAndroid Build Coastguard Worker }
141*8975f5c5SAndroid Build Coastguard Worker
reset()142*8975f5c5SAndroid Build Coastguard Worker void ProcessHandle::reset()
143*8975f5c5SAndroid Build Coastguard Worker {
144*8975f5c5SAndroid Build Coastguard Worker if (mProcess)
145*8975f5c5SAndroid Build Coastguard Worker {
146*8975f5c5SAndroid Build Coastguard Worker delete mProcess;
147*8975f5c5SAndroid Build Coastguard Worker mProcess = nullptr;
148*8975f5c5SAndroid Build Coastguard Worker }
149*8975f5c5SAndroid Build Coastguard Worker }
150*8975f5c5SAndroid Build Coastguard Worker
ParseIntArgWithHandling(const char * flag,int * argc,char ** argv,int argIndex,int * valueOut,ArgHandling handling)151*8975f5c5SAndroid Build Coastguard Worker bool ParseIntArgWithHandling(const char *flag,
152*8975f5c5SAndroid Build Coastguard Worker int *argc,
153*8975f5c5SAndroid Build Coastguard Worker char **argv,
154*8975f5c5SAndroid Build Coastguard Worker int argIndex,
155*8975f5c5SAndroid Build Coastguard Worker int *valueOut,
156*8975f5c5SAndroid Build Coastguard Worker ArgHandling handling)
157*8975f5c5SAndroid Build Coastguard Worker {
158*8975f5c5SAndroid Build Coastguard Worker const char *value = GetSingleArg(flag, argc, argv, argIndex, handling);
159*8975f5c5SAndroid Build Coastguard Worker if (!value)
160*8975f5c5SAndroid Build Coastguard Worker {
161*8975f5c5SAndroid Build Coastguard Worker return false;
162*8975f5c5SAndroid Build Coastguard Worker }
163*8975f5c5SAndroid Build Coastguard Worker
164*8975f5c5SAndroid Build Coastguard Worker char *end = nullptr;
165*8975f5c5SAndroid Build Coastguard Worker const long longValue = strtol(value, &end, 10);
166*8975f5c5SAndroid Build Coastguard Worker
167*8975f5c5SAndroid Build Coastguard Worker if (*end != '\0')
168*8975f5c5SAndroid Build Coastguard Worker {
169*8975f5c5SAndroid Build Coastguard Worker printf("Error parsing integer flag value.\n");
170*8975f5c5SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
171*8975f5c5SAndroid Build Coastguard Worker }
172*8975f5c5SAndroid Build Coastguard Worker
173*8975f5c5SAndroid Build Coastguard Worker if (longValue == LONG_MAX || longValue == LONG_MIN || static_cast<int>(longValue) != longValue)
174*8975f5c5SAndroid Build Coastguard Worker {
175*8975f5c5SAndroid Build Coastguard Worker printf("Overflow when parsing integer flag value.\n");
176*8975f5c5SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
177*8975f5c5SAndroid Build Coastguard Worker }
178*8975f5c5SAndroid Build Coastguard Worker
179*8975f5c5SAndroid Build Coastguard Worker *valueOut = static_cast<int>(longValue);
180*8975f5c5SAndroid Build Coastguard Worker // Note: return value is always false with ArgHandling::Preserve handling
181*8975f5c5SAndroid Build Coastguard Worker return handling == ArgHandling::Delete;
182*8975f5c5SAndroid Build Coastguard Worker }
183*8975f5c5SAndroid Build Coastguard Worker
ParseIntArg(const char * flag,int * argc,char ** argv,int argIndex,int * valueOut)184*8975f5c5SAndroid Build Coastguard Worker bool ParseIntArg(const char *flag, int *argc, char **argv, int argIndex, int *valueOut)
185*8975f5c5SAndroid Build Coastguard Worker {
186*8975f5c5SAndroid Build Coastguard Worker return ParseIntArgWithHandling(flag, argc, argv, argIndex, valueOut, ArgHandling::Delete);
187*8975f5c5SAndroid Build Coastguard Worker }
188*8975f5c5SAndroid Build Coastguard Worker
ParseFlag(const char * flag,int * argc,char ** argv,int argIndex,bool * flagOut)189*8975f5c5SAndroid Build Coastguard Worker bool ParseFlag(const char *flag, int *argc, char **argv, int argIndex, bool *flagOut)
190*8975f5c5SAndroid Build Coastguard Worker {
191*8975f5c5SAndroid Build Coastguard Worker if (strcmp(flag, argv[argIndex]) == 0)
192*8975f5c5SAndroid Build Coastguard Worker {
193*8975f5c5SAndroid Build Coastguard Worker *flagOut = true;
194*8975f5c5SAndroid Build Coastguard Worker DeleteArg(argc, argv, argIndex);
195*8975f5c5SAndroid Build Coastguard Worker return true;
196*8975f5c5SAndroid Build Coastguard Worker }
197*8975f5c5SAndroid Build Coastguard Worker return false;
198*8975f5c5SAndroid Build Coastguard Worker }
199*8975f5c5SAndroid Build Coastguard Worker
ParseStringArg(const char * flag,int * argc,char ** argv,int argIndex,std::string * valueOut)200*8975f5c5SAndroid Build Coastguard Worker bool ParseStringArg(const char *flag, int *argc, char **argv, int argIndex, std::string *valueOut)
201*8975f5c5SAndroid Build Coastguard Worker {
202*8975f5c5SAndroid Build Coastguard Worker const char *value = GetSingleArg(flag, argc, argv, argIndex, ArgHandling::Delete);
203*8975f5c5SAndroid Build Coastguard Worker if (!value)
204*8975f5c5SAndroid Build Coastguard Worker {
205*8975f5c5SAndroid Build Coastguard Worker return false;
206*8975f5c5SAndroid Build Coastguard Worker }
207*8975f5c5SAndroid Build Coastguard Worker
208*8975f5c5SAndroid Build Coastguard Worker *valueOut = value;
209*8975f5c5SAndroid Build Coastguard Worker return true;
210*8975f5c5SAndroid Build Coastguard Worker }
211*8975f5c5SAndroid Build Coastguard Worker
ParseCStringArgWithHandling(const char * flag,int * argc,char ** argv,int argIndex,const char ** valueOut,ArgHandling handling)212*8975f5c5SAndroid Build Coastguard Worker bool ParseCStringArgWithHandling(const char *flag,
213*8975f5c5SAndroid Build Coastguard Worker int *argc,
214*8975f5c5SAndroid Build Coastguard Worker char **argv,
215*8975f5c5SAndroid Build Coastguard Worker int argIndex,
216*8975f5c5SAndroid Build Coastguard Worker const char **valueOut,
217*8975f5c5SAndroid Build Coastguard Worker ArgHandling handling)
218*8975f5c5SAndroid Build Coastguard Worker {
219*8975f5c5SAndroid Build Coastguard Worker const char *value = GetSingleArg(flag, argc, argv, argIndex, handling);
220*8975f5c5SAndroid Build Coastguard Worker if (!value)
221*8975f5c5SAndroid Build Coastguard Worker {
222*8975f5c5SAndroid Build Coastguard Worker return false;
223*8975f5c5SAndroid Build Coastguard Worker }
224*8975f5c5SAndroid Build Coastguard Worker
225*8975f5c5SAndroid Build Coastguard Worker *valueOut = value;
226*8975f5c5SAndroid Build Coastguard Worker // Note: return value is always false with ArgHandling::Preserve handling
227*8975f5c5SAndroid Build Coastguard Worker return handling == ArgHandling::Delete;
228*8975f5c5SAndroid Build Coastguard Worker }
229*8975f5c5SAndroid Build Coastguard Worker
ParseCStringArg(const char * flag,int * argc,char ** argv,int argIndex,const char ** valueOut)230*8975f5c5SAndroid Build Coastguard Worker bool ParseCStringArg(const char *flag, int *argc, char **argv, int argIndex, const char **valueOut)
231*8975f5c5SAndroid Build Coastguard Worker {
232*8975f5c5SAndroid Build Coastguard Worker return ParseCStringArgWithHandling(flag, argc, argv, argIndex, valueOut, ArgHandling::Delete);
233*8975f5c5SAndroid Build Coastguard Worker }
234*8975f5c5SAndroid Build Coastguard Worker
AddArg(int * argc,char ** argv,const char * arg)235*8975f5c5SAndroid Build Coastguard Worker void AddArg(int *argc, char **argv, const char *arg)
236*8975f5c5SAndroid Build Coastguard Worker {
237*8975f5c5SAndroid Build Coastguard Worker // This unsafe const_cast is necessary to work around gtest limitations.
238*8975f5c5SAndroid Build Coastguard Worker argv[*argc] = const_cast<char *>(arg);
239*8975f5c5SAndroid Build Coastguard Worker argv[*argc + 1] = nullptr;
240*8975f5c5SAndroid Build Coastguard Worker (*argc)++;
241*8975f5c5SAndroid Build Coastguard Worker }
242*8975f5c5SAndroid Build Coastguard Worker
GetPlatformANGLETypeFromArg(const char * useANGLEArg,uint32_t defaultPlatformType)243*8975f5c5SAndroid Build Coastguard Worker uint32_t GetPlatformANGLETypeFromArg(const char *useANGLEArg, uint32_t defaultPlatformType)
244*8975f5c5SAndroid Build Coastguard Worker {
245*8975f5c5SAndroid Build Coastguard Worker if (!useANGLEArg)
246*8975f5c5SAndroid Build Coastguard Worker {
247*8975f5c5SAndroid Build Coastguard Worker return defaultPlatformType;
248*8975f5c5SAndroid Build Coastguard Worker }
249*8975f5c5SAndroid Build Coastguard Worker
250*8975f5c5SAndroid Build Coastguard Worker for (const DisplayTypeInfo &displayTypeInfo : kDisplayTypes)
251*8975f5c5SAndroid Build Coastguard Worker {
252*8975f5c5SAndroid Build Coastguard Worker if (strcmp(displayTypeInfo.first, useANGLEArg) == 0)
253*8975f5c5SAndroid Build Coastguard Worker {
254*8975f5c5SAndroid Build Coastguard Worker std::cout << "Using ANGLE back-end API: " << displayTypeInfo.first << std::endl;
255*8975f5c5SAndroid Build Coastguard Worker return displayTypeInfo.second;
256*8975f5c5SAndroid Build Coastguard Worker }
257*8975f5c5SAndroid Build Coastguard Worker }
258*8975f5c5SAndroid Build Coastguard Worker
259*8975f5c5SAndroid Build Coastguard Worker std::cout << "Unknown ANGLE back-end API: " << useANGLEArg << std::endl;
260*8975f5c5SAndroid Build Coastguard Worker exit(EXIT_FAILURE);
261*8975f5c5SAndroid Build Coastguard Worker }
262*8975f5c5SAndroid Build Coastguard Worker
GetANGLEDeviceTypeFromArg(const char * useANGLEArg,uint32_t defaultDeviceType)263*8975f5c5SAndroid Build Coastguard Worker uint32_t GetANGLEDeviceTypeFromArg(const char *useANGLEArg, uint32_t defaultDeviceType)
264*8975f5c5SAndroid Build Coastguard Worker {
265*8975f5c5SAndroid Build Coastguard Worker if (useANGLEArg)
266*8975f5c5SAndroid Build Coastguard Worker {
267*8975f5c5SAndroid Build Coastguard Worker if (strcmp(useANGLEArg, "swiftshader") == 0)
268*8975f5c5SAndroid Build Coastguard Worker {
269*8975f5c5SAndroid Build Coastguard Worker return EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE;
270*8975f5c5SAndroid Build Coastguard Worker }
271*8975f5c5SAndroid Build Coastguard Worker if (strstr(useANGLEArg, "null") != 0)
272*8975f5c5SAndroid Build Coastguard Worker {
273*8975f5c5SAndroid Build Coastguard Worker return EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE;
274*8975f5c5SAndroid Build Coastguard Worker }
275*8975f5c5SAndroid Build Coastguard Worker }
276*8975f5c5SAndroid Build Coastguard Worker return defaultDeviceType;
277*8975f5c5SAndroid Build Coastguard Worker }
278*8975f5c5SAndroid Build Coastguard Worker } // namespace angle
279