1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program Tester Core
3e5c31af7Sopenharmony_ci * ----------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Command line parsing.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "tcuCommandLine.hpp"
25e5c31af7Sopenharmony_ci#include "tcuPlatform.hpp"
26e5c31af7Sopenharmony_ci#include "tcuTestCase.hpp"
27e5c31af7Sopenharmony_ci#include "tcuResource.hpp"
28e5c31af7Sopenharmony_ci#include "deFilePath.hpp"
29e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
30e5c31af7Sopenharmony_ci#include "deString.h"
31e5c31af7Sopenharmony_ci#include "deInt32.h"
32e5c31af7Sopenharmony_ci#include "deCommandLine.h"
33e5c31af7Sopenharmony_ci#include "qpTestLog.h"
34e5c31af7Sopenharmony_ci#include "qpDebugOut.h"
35e5c31af7Sopenharmony_ci
36e5c31af7Sopenharmony_ci#include <string>
37e5c31af7Sopenharmony_ci#include <vector>
38e5c31af7Sopenharmony_ci#include <sstream>
39e5c31af7Sopenharmony_ci#include <fstream>
40e5c31af7Sopenharmony_ci#include <iostream>
41e5c31af7Sopenharmony_ci#include <algorithm>
42e5c31af7Sopenharmony_ci#include <unordered_map>
43e5c31af7Sopenharmony_ci
44e5c31af7Sopenharmony_ciusing std::string;
45e5c31af7Sopenharmony_ciusing std::vector;
46e5c31af7Sopenharmony_ci
47e5c31af7Sopenharmony_ci// OOM tests are enabled by default only on platforms that don't do memory overcommit (Win32)
48e5c31af7Sopenharmony_ci#if (DE_OS == DE_OS_WIN32)
49e5c31af7Sopenharmony_ci#	define TEST_OOM_DEFAULT		"enable"
50e5c31af7Sopenharmony_ci#else
51e5c31af7Sopenharmony_ci#	define TEST_OOM_DEFAULT		"disable"
52e5c31af7Sopenharmony_ci#endif
53e5c31af7Sopenharmony_ci
54e5c31af7Sopenharmony_cinamespace tcu
55e5c31af7Sopenharmony_ci{
56e5c31af7Sopenharmony_ci
57e5c31af7Sopenharmony_cinamespace opt
58e5c31af7Sopenharmony_ci{
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(CasePath,					std::string);
61e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(CaseList,					std::string);
62e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(CaseListFile,				std::string);
63e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(CaseListResource,			std::string);
64e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(StdinCaseList,				bool);
65e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(LogFilename,				std::string);
66e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(RunMode,					tcu::RunMode);
67e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(ExportFilenamePattern,		std::string);
68e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(WatchDog,					bool);
69e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(CrashHandler,				bool);
70e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(BaseSeed,					int);
71e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(TestIterationCount,			int);
72e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(Visibility,					WindowVisibility);
73e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(SurfaceWidth,				int);
74e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(SurfaceHeight,				int);
75e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(SurfaceType,				tcu::SurfaceType);
76e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(ScreenRotation,				tcu::ScreenRotation);
77e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(GLContextType,				std::string);
78e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(GLConfigID,					int);
79e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(GLConfigName,				std::string);
80e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(GLContextFlags,				std::string);
81e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(CLPlatformID,				int);
82e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(CLDeviceIDs,				std::vector<int>);
83e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(CLBuildOptions,				std::string);
84e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(EGLDisplayType,				std::string);
85e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(EGLWindowType,				std::string);
86e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(EGLPixmapType,				std::string);
87e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(LogImages,					bool);
88e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(LogShaderSources,			bool);
89e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(LogDecompiledSpirv,			bool);
90e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(LogEmptyLoginfo,			bool);
91e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(TestOOM,					bool);
92e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(ArchiveDir,					std::string);
93e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(VKDeviceID,					int);
94e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(VKDeviceGroupID,			int);
95e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(LogFlush,					bool);
96e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(LogCompact,					bool);
97e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(Validation,					bool);
98e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(PrintValidationErrors,		bool);
99e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(ShaderCache,				bool);
100e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(ShaderCacheFilename,		std::string);
101e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(Optimization,				int);
102e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(OptimizeSpirv,				bool);
103e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(ShaderCacheTruncate,		bool);
104e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(ShaderCacheIPC,				bool);
105e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(RenderDoc,					bool);
106e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(CaseFraction,				std::vector<int>);
107e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(CaseFractionMandatoryTests,	std::string);
108e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(WaiverFile,					std::string);
109e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(RunnerType,					tcu::TestRunnerType);
110e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(TerminateOnFail,			bool);
111e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(SubProcess,					bool);
112e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(SubprocessTestCount,		int);
113e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(SubprocessConfigFile,		std::string);
114e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(ServerAddress,				std::string);
115e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(CommandPoolMinSize,			int);
116e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(CommandBufferMinSize,		int);
117e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(CommandDefaultSize,			int);
118e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(PipelineDefaultSize,		int);
119e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(PipelineCompilerPath,		std::string);
120e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(PipelineCompilerDataDir,	std::string);
121e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(PipelineCompilerArgs,		std::string);
122e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(PipelineCompilerOutputFile,	std::string);
123e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(PipelineCompilerLogFile,	std::string);
124e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(PipelineCompilerFilePrefix,	std::string);
125e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(VkLibraryPath,				std::string);
126e5c31af7Sopenharmony_ciDE_DECLARE_COMMAND_LINE_OPT(ApplicationParametersInputFile,	std::string);
127e5c31af7Sopenharmony_ci
128e5c31af7Sopenharmony_ci
129e5c31af7Sopenharmony_cistatic void parseIntList (const char* src, std::vector<int>* dst)
130e5c31af7Sopenharmony_ci{
131e5c31af7Sopenharmony_ci	std::istringstream	str	(src);
132e5c31af7Sopenharmony_ci	std::string			val;
133e5c31af7Sopenharmony_ci
134e5c31af7Sopenharmony_ci	while (std::getline(str, val, ','))
135e5c31af7Sopenharmony_ci	{
136e5c31af7Sopenharmony_ci		int intVal = 0;
137e5c31af7Sopenharmony_ci		de::cmdline::parseType(val.c_str(), &intVal);
138e5c31af7Sopenharmony_ci		dst->push_back(intVal);
139e5c31af7Sopenharmony_ci	}
140e5c31af7Sopenharmony_ci}
141e5c31af7Sopenharmony_ci
142e5c31af7Sopenharmony_civoid registerOptions (de::cmdline::Parser& parser)
143e5c31af7Sopenharmony_ci{
144e5c31af7Sopenharmony_ci	using de::cmdline::Option;
145e5c31af7Sopenharmony_ci	using de::cmdline::NamedValue;
146e5c31af7Sopenharmony_ci
147e5c31af7Sopenharmony_ci	static const NamedValue<bool> s_enableNames[] =
148e5c31af7Sopenharmony_ci	{
149e5c31af7Sopenharmony_ci		{ "enable",		true	},
150e5c31af7Sopenharmony_ci		{ "disable",	false	}
151e5c31af7Sopenharmony_ci	};
152e5c31af7Sopenharmony_ci	static const NamedValue<tcu::RunMode> s_runModes[] =
153e5c31af7Sopenharmony_ci	{
154e5c31af7Sopenharmony_ci		{ "execute",		RUNMODE_EXECUTE				  },
155e5c31af7Sopenharmony_ci		{ "xml-caselist",	RUNMODE_DUMP_XML_CASELIST	  },
156e5c31af7Sopenharmony_ci		{ "txt-caselist",	RUNMODE_DUMP_TEXT_CASELIST	  },
157e5c31af7Sopenharmony_ci		{ "stdout-caselist",RUNMODE_DUMP_STDOUT_CASELIST  },
158e5c31af7Sopenharmony_ci		{ "amber-verify",   RUNMODE_VERIFY_AMBER_COHERENCY}
159e5c31af7Sopenharmony_ci	};
160e5c31af7Sopenharmony_ci	static const NamedValue<WindowVisibility> s_visibilites[] =
161e5c31af7Sopenharmony_ci	{
162e5c31af7Sopenharmony_ci		{ "windowed",		WINDOWVISIBILITY_WINDOWED	},
163e5c31af7Sopenharmony_ci		{ "fullscreen",		WINDOWVISIBILITY_FULLSCREEN	},
164e5c31af7Sopenharmony_ci		{ "hidden",			WINDOWVISIBILITY_HIDDEN		}
165e5c31af7Sopenharmony_ci	};
166e5c31af7Sopenharmony_ci	static const NamedValue<tcu::SurfaceType> s_surfaceTypes[] =
167e5c31af7Sopenharmony_ci	{
168e5c31af7Sopenharmony_ci		{ "window",			SURFACETYPE_WINDOW				},
169e5c31af7Sopenharmony_ci		{ "pixmap",			SURFACETYPE_OFFSCREEN_NATIVE	},
170e5c31af7Sopenharmony_ci		{ "pbuffer",		SURFACETYPE_OFFSCREEN_GENERIC	},
171e5c31af7Sopenharmony_ci		{ "fbo",			SURFACETYPE_FBO					}
172e5c31af7Sopenharmony_ci	};
173e5c31af7Sopenharmony_ci	static const NamedValue<tcu::ScreenRotation> s_screenRotations[] =
174e5c31af7Sopenharmony_ci	{
175e5c31af7Sopenharmony_ci		{ "unspecified",	SCREENROTATION_UNSPECIFIED	},
176e5c31af7Sopenharmony_ci		{ "0",				SCREENROTATION_0			},
177e5c31af7Sopenharmony_ci		{ "90",				SCREENROTATION_90			},
178e5c31af7Sopenharmony_ci		{ "180",			SCREENROTATION_180			},
179e5c31af7Sopenharmony_ci		{ "270",			SCREENROTATION_270			}
180e5c31af7Sopenharmony_ci	};
181e5c31af7Sopenharmony_ci	static const NamedValue<tcu::TestRunnerType> s_runnerTypes[] =
182e5c31af7Sopenharmony_ci	{
183e5c31af7Sopenharmony_ci		{ "any",	tcu::RUNNERTYPE_ANY		},
184e5c31af7Sopenharmony_ci		{ "none",	tcu::RUNNERTYPE_NONE	},
185e5c31af7Sopenharmony_ci		{ "amber",	tcu::RUNNERTYPE_AMBER	},
186e5c31af7Sopenharmony_ci	};
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_ci	parser
189e5c31af7Sopenharmony_ci		<< Option<CasePath>						("n",		"deqp-case",								"Test case(s) to run, supports wildcards (e.g. dEQP-GLES2.info.*)")
190e5c31af7Sopenharmony_ci		<< Option<CaseList>						(DE_NULL,	"deqp-caselist",							"Case list to run in trie format (e.g. {dEQP-GLES2{info{version,renderer}}})")
191e5c31af7Sopenharmony_ci		<< Option<CaseListFile>					(DE_NULL,	"deqp-caselist-file",						"Read case list (in trie format) from given file")
192e5c31af7Sopenharmony_ci		<< Option<CaseListResource>				(DE_NULL,	"deqp-caselist-resource",					"Read case list (in trie format) from given file located application's assets")
193e5c31af7Sopenharmony_ci		<< Option<StdinCaseList>				(DE_NULL,	"deqp-stdin-caselist",						"Read case list (in trie format) from stdin")
194e5c31af7Sopenharmony_ci		<< Option<LogFilename>					(DE_NULL,	"deqp-log-filename",						"Write test results to given file",					"TestResults.qpa")
195e5c31af7Sopenharmony_ci		<< Option<RunMode>						(DE_NULL,	"deqp-runmode",								"Execute tests, write list of test cases into a file, or verify amber capability coherency",
196e5c31af7Sopenharmony_ci																																							s_runModes,			"execute")
197e5c31af7Sopenharmony_ci		<< Option<ExportFilenamePattern>		(DE_NULL,	"deqp-caselist-export-file",				"Set the target file name pattern for caselist export",					"${packageName}-cases.${typeExtension}")
198e5c31af7Sopenharmony_ci		<< Option<WatchDog>						(DE_NULL,	"deqp-watchdog",							"Enable test watchdog",								s_enableNames,		"disable")
199e5c31af7Sopenharmony_ci		<< Option<CrashHandler>					(DE_NULL,	"deqp-crashhandler",						"Enable crash handling",							s_enableNames,		"disable")
200e5c31af7Sopenharmony_ci		<< Option<BaseSeed>						(DE_NULL,	"deqp-base-seed",							"Base seed for test cases that use randomization",						"0")
201e5c31af7Sopenharmony_ci		<< Option<TestIterationCount>			(DE_NULL,	"deqp-test-iteration-count",				"Iteration count for cases that support variable number of iterations",	"0")
202e5c31af7Sopenharmony_ci		<< Option<Visibility>					(DE_NULL,	"deqp-visibility",							"Default test window visibility",					s_visibilites,		"windowed")
203e5c31af7Sopenharmony_ci		<< Option<SurfaceWidth>					(DE_NULL,	"deqp-surface-width",						"Use given surface width if possible",									"-1")
204e5c31af7Sopenharmony_ci		<< Option<SurfaceHeight>				(DE_NULL,	"deqp-surface-height",						"Use given surface height if possible",									"-1")
205e5c31af7Sopenharmony_ci		<< Option<SurfaceType>					(DE_NULL,	"deqp-surface-type",						"Use given surface type",							s_surfaceTypes,		"window")
206e5c31af7Sopenharmony_ci		<< Option<ScreenRotation>				(DE_NULL,	"deqp-screen-rotation",						"Screen rotation for platforms that support it",	s_screenRotations,	"0")
207e5c31af7Sopenharmony_ci		<< Option<GLContextType>				(DE_NULL,	"deqp-gl-context-type",						"OpenGL context type for platforms that support multiple")
208e5c31af7Sopenharmony_ci		<< Option<GLConfigID>					(DE_NULL,	"deqp-gl-config-id",						"OpenGL (ES) render config ID (EGL config id on EGL platforms)",		"-1")
209e5c31af7Sopenharmony_ci		<< Option<GLConfigName>					(DE_NULL,	"deqp-gl-config-name",						"Symbolic OpenGL (ES) render config name")
210e5c31af7Sopenharmony_ci		<< Option<GLContextFlags>				(DE_NULL,	"deqp-gl-context-flags",					"OpenGL context flags (comma-separated, supports debug and robust)")
211e5c31af7Sopenharmony_ci		<< Option<CLPlatformID>					(DE_NULL,	"deqp-cl-platform-id",						"Execute tests on given OpenCL platform (IDs start from 1)",			"1")
212e5c31af7Sopenharmony_ci		<< Option<CLDeviceIDs>					(DE_NULL,	"deqp-cl-device-ids",						"Execute tests on given CL devices (comma-separated, IDs start from 1)",	parseIntList,	"")
213e5c31af7Sopenharmony_ci		<< Option<CLBuildOptions>				(DE_NULL,	"deqp-cl-build-options",					"Extra build options for OpenCL compiler")
214e5c31af7Sopenharmony_ci		<< Option<EGLDisplayType>				(DE_NULL,	"deqp-egl-display-type",					"EGL native display type")
215e5c31af7Sopenharmony_ci		<< Option<EGLWindowType>				(DE_NULL,	"deqp-egl-window-type",						"EGL native window type")
216e5c31af7Sopenharmony_ci		<< Option<EGLPixmapType>				(DE_NULL,	"deqp-egl-pixmap-type",						"EGL native pixmap type")
217e5c31af7Sopenharmony_ci		<< Option<VKDeviceID>					(DE_NULL,	"deqp-vk-device-id",						"Vulkan device ID (IDs start from 1)",									"1")
218e5c31af7Sopenharmony_ci		<< Option<VKDeviceGroupID>				(DE_NULL,	"deqp-vk-device-group-id",					"Vulkan device Group ID (IDs start from 1)",							"1")
219e5c31af7Sopenharmony_ci		<< Option<LogImages>					(DE_NULL,	"deqp-log-images",							"Enable or disable logging of result images",		s_enableNames,		"enable")
220e5c31af7Sopenharmony_ci		<< Option<LogShaderSources>				(DE_NULL,	"deqp-log-shader-sources",					"Enable or disable logging of shader sources",		s_enableNames,		"enable")
221e5c31af7Sopenharmony_ci		<< Option<LogDecompiledSpirv>			(DE_NULL,	"deqp-log-decompiled-spirv",				"Enable or disable logging of decompiled spir-v",	s_enableNames,		"enable")
222e5c31af7Sopenharmony_ci		<< Option<LogEmptyLoginfo>				(DE_NULL,	"deqp-log-empty-loginfo",					"Logging of empty shader compile/link log info",	s_enableNames,		"enable")
223e5c31af7Sopenharmony_ci		<< Option<TestOOM>						(DE_NULL,	"deqp-test-oom",							"Run tests that exhaust memory on purpose",			s_enableNames,		TEST_OOM_DEFAULT)
224e5c31af7Sopenharmony_ci		<< Option<ArchiveDir>					(DE_NULL,	"deqp-archive-dir",							"Path to test resource files",											".")
225e5c31af7Sopenharmony_ci		<< Option<LogFlush>						(DE_NULL,	"deqp-log-flush",							"Enable or disable log file fflush",				s_enableNames,		"enable")
226e5c31af7Sopenharmony_ci		<< Option<LogCompact>					(DE_NULL,	"deqp-log-compact",							"Enable or disable the compact version of the log",								s_enableNames,		"disable")
227e5c31af7Sopenharmony_ci		<< Option<Validation>					(DE_NULL,	"deqp-validation",							"Enable or disable test case validation",			s_enableNames,		"disable")
228e5c31af7Sopenharmony_ci		<< Option<PrintValidationErrors>		(DE_NULL,	"deqp-print-validation-errors",				"Print validation errors to standard error")
229e5c31af7Sopenharmony_ci		<< Option<Optimization>					(DE_NULL,	"deqp-optimization-recipe",					"Shader optimization recipe (0=disabled, 1=performance, 2=size)",		"0")
230e5c31af7Sopenharmony_ci		<< Option<OptimizeSpirv>				(DE_NULL,	"deqp-optimize-spirv",						"Apply optimization to spir-v shaders as well",		s_enableNames,		"disable")
231e5c31af7Sopenharmony_ci		<< Option<ShaderCache>					(DE_NULL,	"deqp-shadercache",							"Enable or disable shader cache",					s_enableNames,		"enable")
232e5c31af7Sopenharmony_ci		<< Option<ShaderCacheFilename>			(DE_NULL,	"deqp-shadercache-filename",				"Write shader cache to given file",										"shadercache.bin")
233e5c31af7Sopenharmony_ci		<< Option<ShaderCacheTruncate>			(DE_NULL,	"deqp-shadercache-truncate",				"Truncate shader cache before running tests",		s_enableNames,		"enable")
234e5c31af7Sopenharmony_ci		<< Option<ShaderCacheIPC>				(DE_NULL,	"deqp-shadercache-ipc",						"Should shader cache use inter process comms",		s_enableNames,		"disable")
235e5c31af7Sopenharmony_ci		<< Option<RenderDoc>					(DE_NULL,	"deqp-renderdoc",							"Enable RenderDoc frame markers",					s_enableNames,		"disable")
236e5c31af7Sopenharmony_ci		<< Option<CaseFraction>					(DE_NULL,	"deqp-fraction",							"Run a fraction of the test cases (e.g. N,M means run group%M==N)",	parseIntList,	"")
237e5c31af7Sopenharmony_ci		<< Option<CaseFractionMandatoryTests>	(DE_NULL,	"deqp-fraction-mandatory-caselist-file",	"Case list file that must be run for each fraction",					"")
238e5c31af7Sopenharmony_ci		<< Option<WaiverFile>					(DE_NULL,	"deqp-waiver-file",							"Read waived tests from given file",									"")
239e5c31af7Sopenharmony_ci		<< Option<RunnerType>					(DE_NULL,	"deqp-runner-type",							"Filter test cases based on runner",				s_runnerTypes,		"any")
240e5c31af7Sopenharmony_ci		<< Option<TerminateOnFail>				(DE_NULL,	"deqp-terminate-on-fail",					"Terminate the run on first failure",				s_enableNames,		"disable")
241e5c31af7Sopenharmony_ci		<< Option<SubProcess>					(DE_NULL,	"deqp-subprocess",							"Inform app that it works as subprocess (Vulkan SC only, do not use manually)", s_enableNames, "disable")
242e5c31af7Sopenharmony_ci		<< Option<SubprocessTestCount>			(DE_NULL,	"deqp-subprocess-test-count",				"Define default number of tests performed in subprocess for specific test cases(Vulkan SC only)",	"65536")
243e5c31af7Sopenharmony_ci		<< Option<SubprocessConfigFile>			(DE_NULL,	"deqp-subprocess-cfg-file",					"Config file defining number of tests performed in subprocess for specific test branches (Vulkan SC only)", "")
244e5c31af7Sopenharmony_ci		<< Option<ServerAddress>				(DE_NULL,	"deqp-server-address",						"Server address (host:port) responsible for shader compilation (Vulkan SC only)", "")
245e5c31af7Sopenharmony_ci		<< Option<CommandPoolMinSize>			(DE_NULL,	"deqp-command-pool-min-size",				"Define minimum size of the command pool (in bytes) to use (Vulkan SC only)","0")
246e5c31af7Sopenharmony_ci		<< Option<CommandBufferMinSize>			(DE_NULL,	"deqp-command-buffer-min-size",				"Define minimum size of the command buffer (in bytes) to use (Vulkan SC only)", "0")
247e5c31af7Sopenharmony_ci		<< Option<CommandDefaultSize>			(DE_NULL,	"deqp-command-default-size",				"Define default single command size (in bytes) to use (Vulkan SC only)",	"256")
248e5c31af7Sopenharmony_ci		<< Option<PipelineDefaultSize>			(DE_NULL,	"deqp-pipeline-default-size",				"Define default pipeline size (in bytes) to use (Vulkan SC only)",		"16384")
249e5c31af7Sopenharmony_ci		<< Option<PipelineCompilerPath>			(DE_NULL,	"deqp-pipeline-compiler",					"Path to offline pipeline compiler (Vulkan SC only)", "")
250e5c31af7Sopenharmony_ci		<< Option<PipelineCompilerDataDir>		(DE_NULL,	"deqp-pipeline-dir",						"Offline pipeline data directory (Vulkan SC only)", "")
251e5c31af7Sopenharmony_ci		<< Option<PipelineCompilerArgs>			(DE_NULL,	"deqp-pipeline-args",						"Additional compiler parameters (Vulkan SC only)", "")
252e5c31af7Sopenharmony_ci		<< Option<PipelineCompilerOutputFile>	(DE_NULL,	"deqp-pipeline-file",						"Output file with pipeline cache (Vulkan SC only, do not use manually)", "")
253e5c31af7Sopenharmony_ci		<< Option<PipelineCompilerLogFile>		(DE_NULL,	"deqp-pipeline-logfile",					"Log file for pipeline compiler (Vulkan SC only, do not use manually)", "")
254e5c31af7Sopenharmony_ci		<< Option<PipelineCompilerFilePrefix>	(DE_NULL,	"deqp-pipeline-prefix",						"Prefix for input pipeline compiler files (Vulkan SC only, do not use manually)", "")
255e5c31af7Sopenharmony_ci		<< Option<VkLibraryPath>				(DE_NULL,	"deqp-vk-library-path",						"Path to Vulkan library (e.g. loader library vulkan-1.dll)", "")
256e5c31af7Sopenharmony_ci		<< Option<ApplicationParametersInputFile>    (DE_NULL,       "deqp-app-params-input-file",				"File that provides a default set of application parameters");
257e5c31af7Sopenharmony_ci}
258e5c31af7Sopenharmony_ci
259e5c31af7Sopenharmony_civoid registerLegacyOptions (de::cmdline::Parser& parser)
260e5c31af7Sopenharmony_ci{
261e5c31af7Sopenharmony_ci	using de::cmdline::Option;
262e5c31af7Sopenharmony_ci
263e5c31af7Sopenharmony_ci	parser
264e5c31af7Sopenharmony_ci		<< Option<GLConfigID>			(DE_NULL,	"deqp-egl-config-id",			"Legacy name for --deqp-gl-config-id",	"-1")
265e5c31af7Sopenharmony_ci		<< Option<GLConfigName>			(DE_NULL,	"deqp-egl-config-name",			"Legacy name for --deqp-gl-config-name");
266e5c31af7Sopenharmony_ci}
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ci} // opt
269e5c31af7Sopenharmony_ci
270e5c31af7Sopenharmony_ci
271e5c31af7Sopenharmony_ci// Used to store hashes of test case names
272e5c31af7Sopenharmony_citypedef uint64_t test_case_hash_t;
273e5c31af7Sopenharmony_ci
274e5c31af7Sopenharmony_ci// Source: https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp
275e5c31af7Sopenharmony_ci// MurmurHash2, 64-bit versions, by Austin Appleby
276e5c31af7Sopenharmony_cistatic uint64_t MurmurHash64B ( const void * key, int len, uint64_t seed )
277e5c31af7Sopenharmony_ci{
278e5c31af7Sopenharmony_ci	const uint32_t m = 0x5bd1e995;
279e5c31af7Sopenharmony_ci	const int r = 24;
280e5c31af7Sopenharmony_ci
281e5c31af7Sopenharmony_ci	uint32_t h1 = uint32_t(seed) ^ len;
282e5c31af7Sopenharmony_ci	uint32_t h2 = uint32_t(seed >> 32);
283e5c31af7Sopenharmony_ci
284e5c31af7Sopenharmony_ci	// Ensure that unaligned accesses to data are allowed.
285e5c31af7Sopenharmony_ci#ifdef WIN32
286e5c31af7Sopenharmony_ci	typedef __declspec(align(1)) uint32_t uint32_t_unaligned;
287e5c31af7Sopenharmony_ci#else
288e5c31af7Sopenharmony_ci	typedef __attribute__((aligned(1))) uint32_t uint32_t_unaligned;
289e5c31af7Sopenharmony_ci#endif
290e5c31af7Sopenharmony_ci	const uint32_t_unaligned * data = (const uint32_t_unaligned *)key;
291e5c31af7Sopenharmony_ci
292e5c31af7Sopenharmony_ci	while(len >= 8)
293e5c31af7Sopenharmony_ci	{
294e5c31af7Sopenharmony_ci		uint32_t k1 = *data++;
295e5c31af7Sopenharmony_ci		k1 *= m; k1 ^= k1 >> r; k1 *= m;
296e5c31af7Sopenharmony_ci		h1 *= m; h1 ^= k1;
297e5c31af7Sopenharmony_ci		len -= 4;
298e5c31af7Sopenharmony_ci
299e5c31af7Sopenharmony_ci		uint32_t k2 = *data++;
300e5c31af7Sopenharmony_ci		k2 *= m; k2 ^= k2 >> r; k2 *= m;
301e5c31af7Sopenharmony_ci		h2 *= m; h2 ^= k2;
302e5c31af7Sopenharmony_ci		len -= 4;
303e5c31af7Sopenharmony_ci	}
304e5c31af7Sopenharmony_ci
305e5c31af7Sopenharmony_ci	if(len >= 4)
306e5c31af7Sopenharmony_ci	{
307e5c31af7Sopenharmony_ci		uint32_t k1 = *data++;
308e5c31af7Sopenharmony_ci		k1 *= m; k1 ^= k1 >> r; k1 *= m;
309e5c31af7Sopenharmony_ci		h1 *= m; h1 ^= k1;
310e5c31af7Sopenharmony_ci		len -= 4;
311e5c31af7Sopenharmony_ci	}
312e5c31af7Sopenharmony_ci
313e5c31af7Sopenharmony_ci	switch(len)
314e5c31af7Sopenharmony_ci	{
315e5c31af7Sopenharmony_ci		case 3: h2 ^= ((unsigned char*)data)[2] << 16;
316e5c31af7Sopenharmony_ci			// fall through
317e5c31af7Sopenharmony_ci		case 2: h2 ^= ((unsigned char*)data)[1] << 8;
318e5c31af7Sopenharmony_ci			// fall through
319e5c31af7Sopenharmony_ci		case 1: h2 ^= ((unsigned char*)data)[0];
320e5c31af7Sopenharmony_ci			h2 *= m;
321e5c31af7Sopenharmony_ci	};
322e5c31af7Sopenharmony_ci
323e5c31af7Sopenharmony_ci	h1 ^= h2 >> 18; h1 *= m;
324e5c31af7Sopenharmony_ci	h2 ^= h1 >> 22; h2 *= m;
325e5c31af7Sopenharmony_ci	h1 ^= h2 >> 17; h1 *= m;
326e5c31af7Sopenharmony_ci	h2 ^= h1 >> 19; h2 *= m;
327e5c31af7Sopenharmony_ci
328e5c31af7Sopenharmony_ci	uint64_t h = h1;
329e5c31af7Sopenharmony_ci
330e5c31af7Sopenharmony_ci	h = (h << 32) | h2;
331e5c31af7Sopenharmony_ci
332e5c31af7Sopenharmony_ci	return h;
333e5c31af7Sopenharmony_ci}
334e5c31af7Sopenharmony_ci
335e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
336e5c31af7Sopenharmony_ci * \brief Generates an hash for the test case name part provided.
337e5c31af7Sopenharmony_ci * If a hashCollisionDetectionMap is passed, will detect hash
338e5c31af7Sopenharmony_ci * collisions using that map. hashCollisionDetectionMap can be NULL.
339e5c31af7Sopenharmony_ci * As an example, the standard std::hash<std::string> on a 32-bit
340e5c31af7Sopenharmony_ci * machine will collide with 'random_298' and 'subgroupand_int16_t_mesh_requiredsubgroupsize'
341e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
342e5c31af7Sopenharmony_cistatic test_case_hash_t hashTestNodeName (const std::string &name, std::unordered_map<test_case_hash_t, std::string> *hashCollisionDetectionMap)
343e5c31af7Sopenharmony_ci{
344e5c31af7Sopenharmony_ci	test_case_hash_t hash = MurmurHash64B(name.c_str(), (int)name.length(), 1);
345e5c31af7Sopenharmony_ci	if(hashCollisionDetectionMap != nullptr) {
346e5c31af7Sopenharmony_ci		auto search = hashCollisionDetectionMap->find(hash);
347e5c31af7Sopenharmony_ci		if (search != hashCollisionDetectionMap->end()) {
348e5c31af7Sopenharmony_ci			if (search->second != name) {
349e5c31af7Sopenharmony_ci				print("There was an hash collision between '%s' and '%s'\n", search->second.c_str(), name.c_str());
350e5c31af7Sopenharmony_ci				throw std::runtime_error("Hash collision detected!");
351e5c31af7Sopenharmony_ci			}
352e5c31af7Sopenharmony_ci		}
353e5c31af7Sopenharmony_ci		hashCollisionDetectionMap->insert({hash, name});
354e5c31af7Sopenharmony_ci	}
355e5c31af7Sopenharmony_ci	return hash;
356e5c31af7Sopenharmony_ci}
357e5c31af7Sopenharmony_ci
358e5c31af7Sopenharmony_ci// \todo [2014-02-13 pyry] This could be useful elsewhere as well.
359e5c31af7Sopenharmony_ciclass DebugOutStreambuf : public std::streambuf
360e5c31af7Sopenharmony_ci{
361e5c31af7Sopenharmony_cipublic:
362e5c31af7Sopenharmony_ci						DebugOutStreambuf	(void);
363e5c31af7Sopenharmony_ci						~DebugOutStreambuf	(void);
364e5c31af7Sopenharmony_ci
365e5c31af7Sopenharmony_ciprotected:
366e5c31af7Sopenharmony_ci	std::streamsize		xsputn				(const char* s, std::streamsize count);
367e5c31af7Sopenharmony_ci	int					overflow			(int ch = -1);
368e5c31af7Sopenharmony_ci
369e5c31af7Sopenharmony_ciprivate:
370e5c31af7Sopenharmony_ci	void				flushLine			(void);
371e5c31af7Sopenharmony_ci
372e5c31af7Sopenharmony_ci	std::ostringstream	m_curLine;
373e5c31af7Sopenharmony_ci};
374e5c31af7Sopenharmony_ci
375e5c31af7Sopenharmony_ciDebugOutStreambuf::DebugOutStreambuf (void)
376e5c31af7Sopenharmony_ci{
377e5c31af7Sopenharmony_ci}
378e5c31af7Sopenharmony_ci
379e5c31af7Sopenharmony_ciDebugOutStreambuf::~DebugOutStreambuf (void)
380e5c31af7Sopenharmony_ci{
381e5c31af7Sopenharmony_ci	if (m_curLine.tellp() != std::streampos(0))
382e5c31af7Sopenharmony_ci		flushLine();
383e5c31af7Sopenharmony_ci}
384e5c31af7Sopenharmony_ci
385e5c31af7Sopenharmony_cistd::streamsize DebugOutStreambuf::xsputn (const char* s, std::streamsize count)
386e5c31af7Sopenharmony_ci{
387e5c31af7Sopenharmony_ci	for (std::streamsize pos = 0; pos < count; pos++)
388e5c31af7Sopenharmony_ci	{
389e5c31af7Sopenharmony_ci		m_curLine.put(s[pos]);
390e5c31af7Sopenharmony_ci
391e5c31af7Sopenharmony_ci		if (s[pos] == '\n')
392e5c31af7Sopenharmony_ci			flushLine();
393e5c31af7Sopenharmony_ci	}
394e5c31af7Sopenharmony_ci
395e5c31af7Sopenharmony_ci	return count;
396e5c31af7Sopenharmony_ci}
397e5c31af7Sopenharmony_ci
398e5c31af7Sopenharmony_ciint DebugOutStreambuf::overflow (int ch)
399e5c31af7Sopenharmony_ci{
400e5c31af7Sopenharmony_ci	if (ch == -1)
401e5c31af7Sopenharmony_ci		return -1;
402e5c31af7Sopenharmony_ci	else
403e5c31af7Sopenharmony_ci	{
404e5c31af7Sopenharmony_ci		DE_ASSERT((ch & 0xff) == ch);
405e5c31af7Sopenharmony_ci		const char chVal = (char)(deUint8)(ch & 0xff);
406e5c31af7Sopenharmony_ci		return xsputn(&chVal, 1) == 1 ? ch : -1;
407e5c31af7Sopenharmony_ci	}
408e5c31af7Sopenharmony_ci}
409e5c31af7Sopenharmony_ci
410e5c31af7Sopenharmony_civoid DebugOutStreambuf::flushLine (void)
411e5c31af7Sopenharmony_ci{
412e5c31af7Sopenharmony_ci	qpPrint(m_curLine.str().c_str());
413e5c31af7Sopenharmony_ci	m_curLine.str("");
414e5c31af7Sopenharmony_ci}
415e5c31af7Sopenharmony_ci
416e5c31af7Sopenharmony_ciclass CaseTreeNode
417e5c31af7Sopenharmony_ci{
418e5c31af7Sopenharmony_cipublic:
419e5c31af7Sopenharmony_ci										CaseTreeNode		(const test_case_hash_t hash) : m_hash(hash) {}
420e5c31af7Sopenharmony_ci										~CaseTreeNode		(void);
421e5c31af7Sopenharmony_ci
422e5c31af7Sopenharmony_ci	test_case_hash_t					getHash				(void) const { return m_hash;				}
423e5c31af7Sopenharmony_ci	bool								hasChildren			(void) const { return !m_children.empty();	}
424e5c31af7Sopenharmony_ci
425e5c31af7Sopenharmony_ci	bool								hasChild			(test_case_hash_t hash) const;
426e5c31af7Sopenharmony_ci	CaseTreeNode*						getChild			(test_case_hash_t hash) const;
427e5c31af7Sopenharmony_ci
428e5c31af7Sopenharmony_ci	void								addChild			(CaseTreeNode* child) { m_children.push_back(child); }
429e5c31af7Sopenharmony_ci
430e5c31af7Sopenharmony_ciprivate:
431e5c31af7Sopenharmony_ci										CaseTreeNode		(const CaseTreeNode&);
432e5c31af7Sopenharmony_ci	CaseTreeNode&						operator=			(const CaseTreeNode&);
433e5c31af7Sopenharmony_ci
434e5c31af7Sopenharmony_ci	enum { NOT_FOUND = -1 };
435e5c31af7Sopenharmony_ci
436e5c31af7Sopenharmony_ci	int									findChildNdx		(test_case_hash_t hash) const;
437e5c31af7Sopenharmony_ci
438e5c31af7Sopenharmony_ci	test_case_hash_t					m_hash;
439e5c31af7Sopenharmony_ci	std::vector<CaseTreeNode*>			m_children;
440e5c31af7Sopenharmony_ci};
441e5c31af7Sopenharmony_ci
442e5c31af7Sopenharmony_ciCaseTreeNode::~CaseTreeNode (void)
443e5c31af7Sopenharmony_ci{
444e5c31af7Sopenharmony_ci	for (vector<CaseTreeNode*>::const_iterator i = m_children.begin(); i != m_children.end(); ++i)
445e5c31af7Sopenharmony_ci		delete *i;
446e5c31af7Sopenharmony_ci}
447e5c31af7Sopenharmony_ci
448e5c31af7Sopenharmony_ciint CaseTreeNode::findChildNdx (test_case_hash_t hash) const
449e5c31af7Sopenharmony_ci{
450e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)m_children.size(); ++ndx)
451e5c31af7Sopenharmony_ci	{
452e5c31af7Sopenharmony_ci		if (m_children[ndx]->getHash() == hash)
453e5c31af7Sopenharmony_ci			return ndx;
454e5c31af7Sopenharmony_ci	}
455e5c31af7Sopenharmony_ci	return NOT_FOUND;
456e5c31af7Sopenharmony_ci}
457e5c31af7Sopenharmony_ci
458e5c31af7Sopenharmony_ciinline bool CaseTreeNode::hasChild (test_case_hash_t hash) const
459e5c31af7Sopenharmony_ci{
460e5c31af7Sopenharmony_ci	return findChildNdx(hash) != NOT_FOUND;
461e5c31af7Sopenharmony_ci}
462e5c31af7Sopenharmony_ci
463e5c31af7Sopenharmony_ciinline CaseTreeNode* CaseTreeNode::getChild (test_case_hash_t hash) const
464e5c31af7Sopenharmony_ci{
465e5c31af7Sopenharmony_ci	const int ndx = findChildNdx(hash);
466e5c31af7Sopenharmony_ci	return ndx == NOT_FOUND ? DE_NULL : m_children[ndx];
467e5c31af7Sopenharmony_ci}
468e5c31af7Sopenharmony_ci
469e5c31af7Sopenharmony_cistatic int getCurrentComponentLen (const char* path)
470e5c31af7Sopenharmony_ci{
471e5c31af7Sopenharmony_ci	int ndx = 0;
472e5c31af7Sopenharmony_ci	for (; path[ndx] != 0 && path[ndx] != '.'; ++ndx);
473e5c31af7Sopenharmony_ci	return ndx;
474e5c31af7Sopenharmony_ci}
475e5c31af7Sopenharmony_ci
476e5c31af7Sopenharmony_cistatic const CaseTreeNode* findNode (const CaseTreeNode* root, const char* path)
477e5c31af7Sopenharmony_ci{
478e5c31af7Sopenharmony_ci	const CaseTreeNode*	curNode		= root;
479e5c31af7Sopenharmony_ci	const char*			curPath		= path;
480e5c31af7Sopenharmony_ci	int					curLen		= getCurrentComponentLen(curPath);
481e5c31af7Sopenharmony_ci
482e5c31af7Sopenharmony_ci	for (;;)
483e5c31af7Sopenharmony_ci	{
484e5c31af7Sopenharmony_ci		test_case_hash_t hash = hashTestNodeName(std::string(curPath, curPath + curLen), nullptr);
485e5c31af7Sopenharmony_ci		curNode = curNode->getChild(hash);
486e5c31af7Sopenharmony_ci
487e5c31af7Sopenharmony_ci		if (!curNode)
488e5c31af7Sopenharmony_ci			break;
489e5c31af7Sopenharmony_ci
490e5c31af7Sopenharmony_ci		curPath	+= curLen;
491e5c31af7Sopenharmony_ci
492e5c31af7Sopenharmony_ci		if (curPath[0] == 0)
493e5c31af7Sopenharmony_ci			break;
494e5c31af7Sopenharmony_ci		else
495e5c31af7Sopenharmony_ci		{
496e5c31af7Sopenharmony_ci			DE_ASSERT(curPath[0] == '.');
497e5c31af7Sopenharmony_ci			curPath		+= 1;
498e5c31af7Sopenharmony_ci			curLen		 = getCurrentComponentLen(curPath);
499e5c31af7Sopenharmony_ci		}
500e5c31af7Sopenharmony_ci	}
501e5c31af7Sopenharmony_ci
502e5c31af7Sopenharmony_ci	return curNode;
503e5c31af7Sopenharmony_ci}
504e5c31af7Sopenharmony_ci
505e5c31af7Sopenharmony_cistatic void parseCaseTrie (CaseTreeNode* root, std::istream& in, std::unordered_map<test_case_hash_t, string> &hashCollisionDetectionMap)
506e5c31af7Sopenharmony_ci{
507e5c31af7Sopenharmony_ci	vector<CaseTreeNode*>	nodeStack;
508e5c31af7Sopenharmony_ci	string					curName;
509e5c31af7Sopenharmony_ci	bool					expectNode		= true;
510e5c31af7Sopenharmony_ci
511e5c31af7Sopenharmony_ci	if (in.get() != '{')
512e5c31af7Sopenharmony_ci		throw std::invalid_argument("Malformed case trie");
513e5c31af7Sopenharmony_ci
514e5c31af7Sopenharmony_ci	nodeStack.push_back(root);
515e5c31af7Sopenharmony_ci
516e5c31af7Sopenharmony_ci	while (!nodeStack.empty())
517e5c31af7Sopenharmony_ci	{
518e5c31af7Sopenharmony_ci		const int	curChr	= in.get();
519e5c31af7Sopenharmony_ci
520e5c31af7Sopenharmony_ci		if (curChr == std::char_traits<char>::eof() || curChr == 0)
521e5c31af7Sopenharmony_ci			throw std::invalid_argument("Unterminated case tree");
522e5c31af7Sopenharmony_ci
523e5c31af7Sopenharmony_ci		if (curChr == '{' || curChr == ',' || curChr == '}')
524e5c31af7Sopenharmony_ci		{
525e5c31af7Sopenharmony_ci			if (!curName.empty() && expectNode)
526e5c31af7Sopenharmony_ci			{
527e5c31af7Sopenharmony_ci				test_case_hash_t hash = hashTestNodeName(curName, &hashCollisionDetectionMap);
528e5c31af7Sopenharmony_ci				CaseTreeNode* const newChild = new CaseTreeNode(hash);
529e5c31af7Sopenharmony_ci
530e5c31af7Sopenharmony_ci				try
531e5c31af7Sopenharmony_ci				{
532e5c31af7Sopenharmony_ci					nodeStack.back()->addChild(newChild);
533e5c31af7Sopenharmony_ci				}
534e5c31af7Sopenharmony_ci				catch (...)
535e5c31af7Sopenharmony_ci				{
536e5c31af7Sopenharmony_ci					delete newChild;
537e5c31af7Sopenharmony_ci					throw;
538e5c31af7Sopenharmony_ci				}
539e5c31af7Sopenharmony_ci
540e5c31af7Sopenharmony_ci				if (curChr == '{')
541e5c31af7Sopenharmony_ci					nodeStack.push_back(newChild);
542e5c31af7Sopenharmony_ci
543e5c31af7Sopenharmony_ci				curName.clear();
544e5c31af7Sopenharmony_ci			}
545e5c31af7Sopenharmony_ci			else if (curName.empty() == expectNode)
546e5c31af7Sopenharmony_ci				throw std::invalid_argument(expectNode ? "Empty node name" : "Missing node separator");
547e5c31af7Sopenharmony_ci
548e5c31af7Sopenharmony_ci			if (curChr == '}')
549e5c31af7Sopenharmony_ci			{
550e5c31af7Sopenharmony_ci				expectNode = false;
551e5c31af7Sopenharmony_ci				nodeStack.pop_back();
552e5c31af7Sopenharmony_ci
553e5c31af7Sopenharmony_ci				// consume trailing new line
554e5c31af7Sopenharmony_ci				if (nodeStack.empty())
555e5c31af7Sopenharmony_ci				{
556e5c31af7Sopenharmony_ci					if (in.peek() == '\r')
557e5c31af7Sopenharmony_ci					  in.get();
558e5c31af7Sopenharmony_ci					if (in.peek() == '\n')
559e5c31af7Sopenharmony_ci					  in.get();
560e5c31af7Sopenharmony_ci				}
561e5c31af7Sopenharmony_ci			}
562e5c31af7Sopenharmony_ci			else
563e5c31af7Sopenharmony_ci				expectNode = true;
564e5c31af7Sopenharmony_ci		}
565e5c31af7Sopenharmony_ci		else if (isValidTestCaseNameChar((char)curChr))
566e5c31af7Sopenharmony_ci			curName += (char)curChr;
567e5c31af7Sopenharmony_ci		else
568e5c31af7Sopenharmony_ci			throw std::invalid_argument("Illegal character in node name");
569e5c31af7Sopenharmony_ci	}
570e5c31af7Sopenharmony_ci}
571e5c31af7Sopenharmony_ci
572e5c31af7Sopenharmony_cistatic void parseSimpleCaseList (vector<CaseTreeNode*>& nodeStack, std::istream& in, bool reportDuplicates, std::unordered_map<test_case_hash_t, string> &hashCollisionDetectionMap)
573e5c31af7Sopenharmony_ci{
574e5c31af7Sopenharmony_ci	// \note Algorithm assumes that cases are sorted by groups, but will
575e5c31af7Sopenharmony_ci	//		 function fine, albeit more slowly, if that is not the case.
576e5c31af7Sopenharmony_ci	int		stackPos	= 0;
577e5c31af7Sopenharmony_ci	string	curName;
578e5c31af7Sopenharmony_ci
579e5c31af7Sopenharmony_ci	for (;;)
580e5c31af7Sopenharmony_ci	{
581e5c31af7Sopenharmony_ci		const int curChr = in.get();
582e5c31af7Sopenharmony_ci
583e5c31af7Sopenharmony_ci		if (curChr == std::char_traits<char>::eof() || curChr == 0 || curChr == '\n' || curChr == '\r')
584e5c31af7Sopenharmony_ci		{
585e5c31af7Sopenharmony_ci			if (curName.empty())
586e5c31af7Sopenharmony_ci				throw std::invalid_argument("Empty test case name");
587e5c31af7Sopenharmony_ci
588e5c31af7Sopenharmony_ci			test_case_hash_t hash = hashTestNodeName(curName, &hashCollisionDetectionMap);
589e5c31af7Sopenharmony_ci			if (!nodeStack[stackPos]->hasChild(hash))
590e5c31af7Sopenharmony_ci			{
591e5c31af7Sopenharmony_ci				CaseTreeNode* const newChild = new CaseTreeNode(hash);
592e5c31af7Sopenharmony_ci
593e5c31af7Sopenharmony_ci				try
594e5c31af7Sopenharmony_ci				{
595e5c31af7Sopenharmony_ci					nodeStack[stackPos]->addChild(newChild);
596e5c31af7Sopenharmony_ci				}
597e5c31af7Sopenharmony_ci				catch (...)
598e5c31af7Sopenharmony_ci				{
599e5c31af7Sopenharmony_ci					delete newChild;
600e5c31af7Sopenharmony_ci					throw;
601e5c31af7Sopenharmony_ci				}
602e5c31af7Sopenharmony_ci			}
603e5c31af7Sopenharmony_ci			else if (reportDuplicates)
604e5c31af7Sopenharmony_ci				throw std::invalid_argument("Duplicate test case");
605e5c31af7Sopenharmony_ci
606e5c31af7Sopenharmony_ci			curName.clear();
607e5c31af7Sopenharmony_ci			stackPos = 0;
608e5c31af7Sopenharmony_ci
609e5c31af7Sopenharmony_ci			if (curChr == '\r' && in.peek() == '\n')
610e5c31af7Sopenharmony_ci				in.get();
611e5c31af7Sopenharmony_ci
612e5c31af7Sopenharmony_ci			{
613e5c31af7Sopenharmony_ci				const int nextChr = in.peek();
614e5c31af7Sopenharmony_ci
615e5c31af7Sopenharmony_ci				if (nextChr == std::char_traits<char>::eof() || nextChr == 0)
616e5c31af7Sopenharmony_ci					break;
617e5c31af7Sopenharmony_ci			}
618e5c31af7Sopenharmony_ci		}
619e5c31af7Sopenharmony_ci		else if (curChr == '.')
620e5c31af7Sopenharmony_ci		{
621e5c31af7Sopenharmony_ci			if (curName.empty())
622e5c31af7Sopenharmony_ci				throw std::invalid_argument("Empty test group name");
623e5c31af7Sopenharmony_ci
624e5c31af7Sopenharmony_ci			if ((int)nodeStack.size() <= stackPos+1)
625e5c31af7Sopenharmony_ci				nodeStack.resize(nodeStack.size()*2, DE_NULL);
626e5c31af7Sopenharmony_ci
627e5c31af7Sopenharmony_ci			test_case_hash_t hash = hashTestNodeName(curName, &hashCollisionDetectionMap);
628e5c31af7Sopenharmony_ci			if (!nodeStack[stackPos+1] || nodeStack[stackPos+1]->getHash() != hash)
629e5c31af7Sopenharmony_ci			{
630e5c31af7Sopenharmony_ci				CaseTreeNode* curGroup = nodeStack[stackPos]->getChild(hash);
631e5c31af7Sopenharmony_ci
632e5c31af7Sopenharmony_ci				if (!curGroup)
633e5c31af7Sopenharmony_ci				{
634e5c31af7Sopenharmony_ci					curGroup = new CaseTreeNode(hash);
635e5c31af7Sopenharmony_ci
636e5c31af7Sopenharmony_ci					try
637e5c31af7Sopenharmony_ci					{
638e5c31af7Sopenharmony_ci						nodeStack[stackPos]->addChild(curGroup);
639e5c31af7Sopenharmony_ci					}
640e5c31af7Sopenharmony_ci					catch (...)
641e5c31af7Sopenharmony_ci					{
642e5c31af7Sopenharmony_ci						delete curGroup;
643e5c31af7Sopenharmony_ci						throw;
644e5c31af7Sopenharmony_ci					}
645e5c31af7Sopenharmony_ci				}
646e5c31af7Sopenharmony_ci
647e5c31af7Sopenharmony_ci				nodeStack[stackPos+1] = curGroup;
648e5c31af7Sopenharmony_ci
649e5c31af7Sopenharmony_ci				if ((int)nodeStack.size() > stackPos+2)
650e5c31af7Sopenharmony_ci					nodeStack[stackPos+2] = DE_NULL; // Invalidate rest of entries
651e5c31af7Sopenharmony_ci			}
652e5c31af7Sopenharmony_ci
653e5c31af7Sopenharmony_ci			DE_ASSERT(nodeStack[stackPos+1]->getHash() == hash);
654e5c31af7Sopenharmony_ci
655e5c31af7Sopenharmony_ci			curName.clear();
656e5c31af7Sopenharmony_ci			stackPos += 1;
657e5c31af7Sopenharmony_ci		}
658e5c31af7Sopenharmony_ci		else if (isValidTestCaseNameChar((char)curChr))
659e5c31af7Sopenharmony_ci			curName += (char)curChr;
660e5c31af7Sopenharmony_ci		else
661e5c31af7Sopenharmony_ci			throw std::invalid_argument("Illegal character in test case name");
662e5c31af7Sopenharmony_ci	}
663e5c31af7Sopenharmony_ci}
664e5c31af7Sopenharmony_ci
665e5c31af7Sopenharmony_cistatic void parseCaseList (CaseTreeNode* root, std::istream& in, bool reportDuplicates, std::unordered_map<test_case_hash_t, string> &hashCollisionDetectionMap)
666e5c31af7Sopenharmony_ci{
667e5c31af7Sopenharmony_ci	vector<CaseTreeNode*> nodeStack(8, root);
668e5c31af7Sopenharmony_ci	parseSimpleCaseList(nodeStack, in, reportDuplicates, hashCollisionDetectionMap);
669e5c31af7Sopenharmony_ci}
670e5c31af7Sopenharmony_ci
671e5c31af7Sopenharmony_cistatic void parseGroupFile(CaseTreeNode* root, std::istream& inGroupList, const tcu::Archive& archive, bool reportDuplicates, std::unordered_map<test_case_hash_t, string> &hashCollisionDetectionMap)
672e5c31af7Sopenharmony_ci{
673e5c31af7Sopenharmony_ci	// read whole file and remove all '\r'
674e5c31af7Sopenharmony_ci	std::string buffer(std::istreambuf_iterator<char>(inGroupList), {});
675e5c31af7Sopenharmony_ci	buffer.erase(std::remove(buffer.begin(), buffer.end(), '\r'), buffer.end());
676e5c31af7Sopenharmony_ci
677e5c31af7Sopenharmony_ci	vector<CaseTreeNode*>	nodeStack(8, root);
678e5c31af7Sopenharmony_ci	std::stringstream		namesStream(buffer);
679e5c31af7Sopenharmony_ci	std::string				fileName;
680e5c31af7Sopenharmony_ci
681e5c31af7Sopenharmony_ci	while (std::getline(namesStream, fileName))
682e5c31af7Sopenharmony_ci	{
683e5c31af7Sopenharmony_ci		de::FilePath			groupPath		(fileName);
684e5c31af7Sopenharmony_ci		de::UniquePtr<Resource>	groupResource	(archive.getResource(groupPath.normalize().getPath()));
685e5c31af7Sopenharmony_ci		const int				groupBufferSize	(groupResource->getSize());
686e5c31af7Sopenharmony_ci		std::vector<char>		groupBuffer		(static_cast<size_t>(groupBufferSize));
687e5c31af7Sopenharmony_ci
688e5c31af7Sopenharmony_ci		groupResource->read(reinterpret_cast<deUint8*>(&groupBuffer[0]), groupBufferSize);
689e5c31af7Sopenharmony_ci		if (groupBuffer.empty())
690e5c31af7Sopenharmony_ci			throw Exception("Empty case list resource");
691e5c31af7Sopenharmony_ci
692e5c31af7Sopenharmony_ci		std::istringstream groupIn(std::string(groupBuffer.begin(), groupBuffer.end()));
693e5c31af7Sopenharmony_ci		parseSimpleCaseList(nodeStack, groupIn, reportDuplicates, hashCollisionDetectionMap);
694e5c31af7Sopenharmony_ci	}
695e5c31af7Sopenharmony_ci}
696e5c31af7Sopenharmony_ci
697e5c31af7Sopenharmony_cistatic CaseTreeNode* parseCaseList (std::istream& in, const tcu::Archive& archive, const char* path = DE_NULL)
698e5c31af7Sopenharmony_ci{
699e5c31af7Sopenharmony_ci	std::unordered_map<test_case_hash_t, std::string> hashCollisionDetectionMap{};
700e5c31af7Sopenharmony_ci	auto rootName = "";
701e5c31af7Sopenharmony_ci	test_case_hash_t hash = hashTestNodeName(rootName, &hashCollisionDetectionMap);
702e5c31af7Sopenharmony_ci	CaseTreeNode* const root = new CaseTreeNode(hash);
703e5c31af7Sopenharmony_ci	try
704e5c31af7Sopenharmony_ci	{
705e5c31af7Sopenharmony_ci		if (in.peek() == '{')
706e5c31af7Sopenharmony_ci			parseCaseTrie(root, in, hashCollisionDetectionMap);
707e5c31af7Sopenharmony_ci		else
708e5c31af7Sopenharmony_ci		{
709e5c31af7Sopenharmony_ci			// if we are reading cases from file determine if we are
710e5c31af7Sopenharmony_ci			// reading group file or plain list of cases; this is done by
711e5c31af7Sopenharmony_ci			// reading single line and checking if it ends with ".txt"
712e5c31af7Sopenharmony_ci			bool readGroupFile = false;
713e5c31af7Sopenharmony_ci			if (path)
714e5c31af7Sopenharmony_ci			{
715e5c31af7Sopenharmony_ci				// read the first line and make sure it doesn't contain '\r'
716e5c31af7Sopenharmony_ci				std::string line;
717e5c31af7Sopenharmony_ci				std::getline(in, line);
718e5c31af7Sopenharmony_ci				line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
719e5c31af7Sopenharmony_ci
720e5c31af7Sopenharmony_ci				const std::string ending = ".txt";
721e5c31af7Sopenharmony_ci				readGroupFile = (line.length() > ending.length()) &&
722e5c31af7Sopenharmony_ci								std::equal(ending.rbegin(), ending.rend(), line.rbegin());
723e5c31af7Sopenharmony_ci
724e5c31af7Sopenharmony_ci				// move to the beginning of the file to parse first line too
725e5c31af7Sopenharmony_ci				in.seekg(0, in.beg);
726e5c31af7Sopenharmony_ci			}
727e5c31af7Sopenharmony_ci
728e5c31af7Sopenharmony_ci			if (readGroupFile)
729e5c31af7Sopenharmony_ci				parseGroupFile(root, in, archive, true, hashCollisionDetectionMap);
730e5c31af7Sopenharmony_ci			else
731e5c31af7Sopenharmony_ci				parseCaseList(root, in, true, hashCollisionDetectionMap);
732e5c31af7Sopenharmony_ci		}
733e5c31af7Sopenharmony_ci
734e5c31af7Sopenharmony_ci		{
735e5c31af7Sopenharmony_ci			const int curChr = in.get();
736e5c31af7Sopenharmony_ci			if (curChr != std::char_traits<char>::eof() && curChr != 0)
737e5c31af7Sopenharmony_ci				throw std::invalid_argument("Trailing characters at end of case list");
738e5c31af7Sopenharmony_ci		}
739e5c31af7Sopenharmony_ci
740e5c31af7Sopenharmony_ci		return root;
741e5c31af7Sopenharmony_ci	}
742e5c31af7Sopenharmony_ci	catch (...)
743e5c31af7Sopenharmony_ci	{
744e5c31af7Sopenharmony_ci		delete root;
745e5c31af7Sopenharmony_ci		throw;
746e5c31af7Sopenharmony_ci	}
747e5c31af7Sopenharmony_ci}
748e5c31af7Sopenharmony_ci
749e5c31af7Sopenharmony_ciclass CasePaths
750e5c31af7Sopenharmony_ci{
751e5c31af7Sopenharmony_cipublic:
752e5c31af7Sopenharmony_ci	CasePaths(const string& pathList);
753e5c31af7Sopenharmony_ci	CasePaths(const vector<string>& pathList);
754e5c31af7Sopenharmony_ci	bool					matches(const string& caseName, bool allowPrefix = false) const;
755e5c31af7Sopenharmony_ci
756e5c31af7Sopenharmony_ciprivate:
757e5c31af7Sopenharmony_ci	const vector<string>	m_casePatterns;
758e5c31af7Sopenharmony_ci};
759e5c31af7Sopenharmony_ci
760e5c31af7Sopenharmony_ciCasePaths::CasePaths (const string& pathList)
761e5c31af7Sopenharmony_ci	: m_casePatterns(de::splitString(pathList, ','))
762e5c31af7Sopenharmony_ci{
763e5c31af7Sopenharmony_ci}
764e5c31af7Sopenharmony_ci
765e5c31af7Sopenharmony_ciCasePaths::CasePaths(const vector<string>& pathList)
766e5c31af7Sopenharmony_ci	: m_casePatterns(pathList)
767e5c31af7Sopenharmony_ci{
768e5c31af7Sopenharmony_ci}
769e5c31af7Sopenharmony_ci
770e5c31af7Sopenharmony_ci// Match a single path component against a pattern component that may contain *-wildcards.
771e5c31af7Sopenharmony_cibool matchWildcards(string::const_iterator	patternStart,
772e5c31af7Sopenharmony_ci					string::const_iterator	patternEnd,
773e5c31af7Sopenharmony_ci					string::const_iterator	pathStart,
774e5c31af7Sopenharmony_ci					string::const_iterator	pathEnd,
775e5c31af7Sopenharmony_ci					bool					allowPrefix)
776e5c31af7Sopenharmony_ci{
777e5c31af7Sopenharmony_ci	string::const_iterator	pattern	= patternStart;
778e5c31af7Sopenharmony_ci	string::const_iterator	path	= pathStart;
779e5c31af7Sopenharmony_ci
780e5c31af7Sopenharmony_ci	while (pattern != patternEnd && path != pathEnd && *pattern == *path)
781e5c31af7Sopenharmony_ci	{
782e5c31af7Sopenharmony_ci		++pattern;
783e5c31af7Sopenharmony_ci		++path;
784e5c31af7Sopenharmony_ci	}
785e5c31af7Sopenharmony_ci
786e5c31af7Sopenharmony_ci	if (pattern == patternEnd)
787e5c31af7Sopenharmony_ci		return (path == pathEnd);
788e5c31af7Sopenharmony_ci	else if (*pattern == '*')
789e5c31af7Sopenharmony_ci	{
790e5c31af7Sopenharmony_ci		string::const_iterator patternNext = pattern + 1;
791e5c31af7Sopenharmony_ci		if (patternNext != patternEnd) {
792e5c31af7Sopenharmony_ci			for (; path != pathEnd; ++path)
793e5c31af7Sopenharmony_ci			{
794e5c31af7Sopenharmony_ci				if (*patternNext == *path)
795e5c31af7Sopenharmony_ci					if (matchWildcards(patternNext, patternEnd, path, pathEnd, allowPrefix))
796e5c31af7Sopenharmony_ci						return true;
797e5c31af7Sopenharmony_ci			}
798e5c31af7Sopenharmony_ci		}
799e5c31af7Sopenharmony_ci
800e5c31af7Sopenharmony_ci		if (matchWildcards(pattern + 1, patternEnd, pathEnd, pathEnd, allowPrefix))
801e5c31af7Sopenharmony_ci			return true;
802e5c31af7Sopenharmony_ci	}
803e5c31af7Sopenharmony_ci	else if (path == pathEnd && allowPrefix)
804e5c31af7Sopenharmony_ci		return true;
805e5c31af7Sopenharmony_ci
806e5c31af7Sopenharmony_ci	return false;
807e5c31af7Sopenharmony_ci}
808e5c31af7Sopenharmony_ci
809e5c31af7Sopenharmony_ci#if defined(TCU_HIERARCHICAL_CASEPATHS)
810e5c31af7Sopenharmony_ci// Match a list of pattern components to a list of path components. A pattern
811e5c31af7Sopenharmony_ci// component may contain *-wildcards. A pattern component "**" matches zero or
812e5c31af7Sopenharmony_ci// more whole path components.
813e5c31af7Sopenharmony_cistatic bool patternMatches(vector<string>::const_iterator	patternStart,
814e5c31af7Sopenharmony_ci						   vector<string>::const_iterator	patternEnd,
815e5c31af7Sopenharmony_ci						   vector<string>::const_iterator	pathStart,
816e5c31af7Sopenharmony_ci						   vector<string>::const_iterator	pathEnd,
817e5c31af7Sopenharmony_ci						   bool								allowPrefix)
818e5c31af7Sopenharmony_ci{
819e5c31af7Sopenharmony_ci	vector<string>::const_iterator	pattern	= patternStart;
820e5c31af7Sopenharmony_ci	vector<string>::const_iterator	path	= pathStart;
821e5c31af7Sopenharmony_ci
822e5c31af7Sopenharmony_ci	while (pattern != patternEnd && path != pathEnd && *pattern != "**" &&
823e5c31af7Sopenharmony_ci		   (*pattern == *path || matchWildcards(pattern->begin(), pattern->end(),
824e5c31af7Sopenharmony_ci												path->begin(), path->end(), false)))
825e5c31af7Sopenharmony_ci	{
826e5c31af7Sopenharmony_ci		++pattern;
827e5c31af7Sopenharmony_ci		++path;
828e5c31af7Sopenharmony_ci	}
829e5c31af7Sopenharmony_ci
830e5c31af7Sopenharmony_ci	if (path == pathEnd && (allowPrefix || pattern == patternEnd))
831e5c31af7Sopenharmony_ci		return true;
832e5c31af7Sopenharmony_ci	else if (pattern != patternEnd && *pattern == "**")
833e5c31af7Sopenharmony_ci	{
834e5c31af7Sopenharmony_ci		for (; path != pathEnd; ++path)
835e5c31af7Sopenharmony_ci			if (patternMatches(pattern + 1, patternEnd, path, pathEnd, allowPrefix))
836e5c31af7Sopenharmony_ci				return true;
837e5c31af7Sopenharmony_ci		if (patternMatches(pattern + 1, patternEnd, path, pathEnd, allowPrefix))
838e5c31af7Sopenharmony_ci			return true;
839e5c31af7Sopenharmony_ci	}
840e5c31af7Sopenharmony_ci
841e5c31af7Sopenharmony_ci	return false;
842e5c31af7Sopenharmony_ci}
843e5c31af7Sopenharmony_ci#endif
844e5c31af7Sopenharmony_ci
845e5c31af7Sopenharmony_cibool CasePaths::matches (const string& caseName, bool allowPrefix) const
846e5c31af7Sopenharmony_ci{
847e5c31af7Sopenharmony_ci#if defined(TCU_HIERARCHICAL_CASEPATHS)
848e5c31af7Sopenharmony_ci	const vector<string> components = de::splitString(caseName, '.');
849e5c31af7Sopenharmony_ci#endif
850e5c31af7Sopenharmony_ci
851e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < m_casePatterns.size(); ++ndx)
852e5c31af7Sopenharmony_ci	{
853e5c31af7Sopenharmony_ci#if defined(TCU_HIERARCHICAL_CASEPATHS)
854e5c31af7Sopenharmony_ci		const vector<string> patternComponents = de::splitString(m_casePatterns[ndx], '.');
855e5c31af7Sopenharmony_ci
856e5c31af7Sopenharmony_ci		if (patternMatches(patternComponents.begin(), patternComponents.end(),
857e5c31af7Sopenharmony_ci						   components.begin(), components.end(), allowPrefix))
858e5c31af7Sopenharmony_ci			return true;
859e5c31af7Sopenharmony_ci#else
860e5c31af7Sopenharmony_ci		if (matchWildcards(m_casePatterns[ndx].begin(), m_casePatterns[ndx].end(),
861e5c31af7Sopenharmony_ci						   caseName.begin(), caseName.end(), allowPrefix))
862e5c31af7Sopenharmony_ci			return true;
863e5c31af7Sopenharmony_ci#endif
864e5c31af7Sopenharmony_ci	}
865e5c31af7Sopenharmony_ci
866e5c31af7Sopenharmony_ci	return false;
867e5c31af7Sopenharmony_ci}
868e5c31af7Sopenharmony_ci
869e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
870e5c31af7Sopenharmony_ci * \brief Construct command line
871e5c31af7Sopenharmony_ci * \note CommandLine is not fully initialized until parse() has been called.
872e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
873e5c31af7Sopenharmony_ciCommandLine::CommandLine (void)
874e5c31af7Sopenharmony_ci	: m_appName(), m_logFlags(0), m_hadHelpSpecified(false)
875e5c31af7Sopenharmony_ci{
876e5c31af7Sopenharmony_ci}
877e5c31af7Sopenharmony_ci
878e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
879e5c31af7Sopenharmony_ci * \brief Construct command line from standard argc, argv pair.
880e5c31af7Sopenharmony_ci *
881e5c31af7Sopenharmony_ci * Calls parse() with given arguments
882e5c31af7Sopenharmony_ci * \param archive application's assets
883e5c31af7Sopenharmony_ci * \param argc Number of arguments
884e5c31af7Sopenharmony_ci * \param argv Command line arguments
885e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
886e5c31af7Sopenharmony_ciCommandLine::CommandLine (int argc, const char* const* argv)
887e5c31af7Sopenharmony_ci	: m_appName(argv[0]), m_logFlags (0), m_hadHelpSpecified(false)
888e5c31af7Sopenharmony_ci{
889e5c31af7Sopenharmony_ci	if (argc > 1)
890e5c31af7Sopenharmony_ci	{
891e5c31af7Sopenharmony_ci		int loop = 1;		// skip application name
892e5c31af7Sopenharmony_ci		while (true)
893e5c31af7Sopenharmony_ci		{
894e5c31af7Sopenharmony_ci			m_initialCmdLine += std::string(argv[loop++]);
895e5c31af7Sopenharmony_ci			if (loop >= argc)
896e5c31af7Sopenharmony_ci				break;
897e5c31af7Sopenharmony_ci			m_initialCmdLine += " ";
898e5c31af7Sopenharmony_ci		}
899e5c31af7Sopenharmony_ci	}
900e5c31af7Sopenharmony_ci
901e5c31af7Sopenharmony_ci	if (!parse(argc, argv))
902e5c31af7Sopenharmony_ci	{
903e5c31af7Sopenharmony_ci		if (m_hadHelpSpecified)
904e5c31af7Sopenharmony_ci			exit(EXIT_SUCCESS);
905e5c31af7Sopenharmony_ci		else
906e5c31af7Sopenharmony_ci			throw Exception("Failed to parse command line");
907e5c31af7Sopenharmony_ci	}
908e5c31af7Sopenharmony_ci}
909e5c31af7Sopenharmony_ci
910e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
911e5c31af7Sopenharmony_ci * \brief Construct command line from string.
912e5c31af7Sopenharmony_ci *
913e5c31af7Sopenharmony_ci * Calls parse() with given argument.
914e5c31af7Sopenharmony_ci * \param archive application's assets
915e5c31af7Sopenharmony_ci * \param cmdLine Full command line string.
916e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
917e5c31af7Sopenharmony_ciCommandLine::CommandLine (const std::string& cmdLine)
918e5c31af7Sopenharmony_ci	: m_appName(), m_initialCmdLine	(cmdLine), m_hadHelpSpecified(false)
919e5c31af7Sopenharmony_ci{
920e5c31af7Sopenharmony_ci	if (!parse(cmdLine))
921e5c31af7Sopenharmony_ci		throw Exception("Failed to parse command line");
922e5c31af7Sopenharmony_ci}
923e5c31af7Sopenharmony_ci
924e5c31af7Sopenharmony_ciCommandLine::~CommandLine (void)
925e5c31af7Sopenharmony_ci{
926e5c31af7Sopenharmony_ci}
927e5c31af7Sopenharmony_ci
928e5c31af7Sopenharmony_civoid CommandLine::clear (void)
929e5c31af7Sopenharmony_ci{
930e5c31af7Sopenharmony_ci	m_cmdLine.clear();
931e5c31af7Sopenharmony_ci	m_logFlags = 0;
932e5c31af7Sopenharmony_ci}
933e5c31af7Sopenharmony_ci
934e5c31af7Sopenharmony_ciconst de::cmdline::CommandLine& CommandLine::getCommandLine (void) const
935e5c31af7Sopenharmony_ci{
936e5c31af7Sopenharmony_ci	return m_cmdLine;
937e5c31af7Sopenharmony_ci}
938e5c31af7Sopenharmony_ci
939e5c31af7Sopenharmony_ciconst std::string& CommandLine::getApplicationName(void) const
940e5c31af7Sopenharmony_ci{
941e5c31af7Sopenharmony_ci	return m_appName;
942e5c31af7Sopenharmony_ci}
943e5c31af7Sopenharmony_ci
944e5c31af7Sopenharmony_ciconst std::string& CommandLine::getInitialCmdLine(void) const
945e5c31af7Sopenharmony_ci{
946e5c31af7Sopenharmony_ci	return m_initialCmdLine;
947e5c31af7Sopenharmony_ci}
948e5c31af7Sopenharmony_ci
949e5c31af7Sopenharmony_civoid CommandLine::registerExtendedOptions (de::cmdline::Parser& parser)
950e5c31af7Sopenharmony_ci{
951e5c31af7Sopenharmony_ci	DE_UNREF(parser);
952e5c31af7Sopenharmony_ci}
953e5c31af7Sopenharmony_ci
954e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
955e5c31af7Sopenharmony_ci * \brief Parse command line from standard argc, argv pair.
956e5c31af7Sopenharmony_ci * \note parse() must be called exactly once.
957e5c31af7Sopenharmony_ci * \param argc Number of arguments
958e5c31af7Sopenharmony_ci * \param argv Command line arguments
959e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
960e5c31af7Sopenharmony_cibool CommandLine::parse (int argc, const char* const* argv)
961e5c31af7Sopenharmony_ci{
962e5c31af7Sopenharmony_ci	DebugOutStreambuf	sbuf;
963e5c31af7Sopenharmony_ci	std::ostream		debugOut	(&sbuf);
964e5c31af7Sopenharmony_ci	de::cmdline::Parser	parser;
965e5c31af7Sopenharmony_ci
966e5c31af7Sopenharmony_ci	opt::registerOptions(parser);
967e5c31af7Sopenharmony_ci	opt::registerLegacyOptions(parser);
968e5c31af7Sopenharmony_ci	registerExtendedOptions(parser);
969e5c31af7Sopenharmony_ci
970e5c31af7Sopenharmony_ci	clear();
971e5c31af7Sopenharmony_ci
972e5c31af7Sopenharmony_ci	if (!parser.parse(argc-1, argv+1, &m_cmdLine, std::cerr))
973e5c31af7Sopenharmony_ci	{
974e5c31af7Sopenharmony_ci		debugOut << "\n" << de::FilePath(argv[0]).getBaseName() << " [options]\n\n";
975e5c31af7Sopenharmony_ci		parser.help(debugOut);
976e5c31af7Sopenharmony_ci
977e5c31af7Sopenharmony_ci		// We need to save this to avoid exiting with error later, and before the clear() call that wipes its value.
978e5c31af7Sopenharmony_ci		m_hadHelpSpecified = m_cmdLine.helpSpecified();
979e5c31af7Sopenharmony_ci
980e5c31af7Sopenharmony_ci		clear();
981e5c31af7Sopenharmony_ci		return false;
982e5c31af7Sopenharmony_ci	}
983e5c31af7Sopenharmony_ci
984e5c31af7Sopenharmony_ci	if (!m_cmdLine.getOption<opt::LogImages>())
985e5c31af7Sopenharmony_ci		m_logFlags |= QP_TEST_LOG_EXCLUDE_IMAGES;
986e5c31af7Sopenharmony_ci
987e5c31af7Sopenharmony_ci	if (!m_cmdLine.getOption<opt::LogShaderSources>())
988e5c31af7Sopenharmony_ci		m_logFlags |= QP_TEST_LOG_EXCLUDE_SHADER_SOURCES;
989e5c31af7Sopenharmony_ci
990e5c31af7Sopenharmony_ci	if (!m_cmdLine.getOption<opt::LogFlush>())
991e5c31af7Sopenharmony_ci		m_logFlags |= QP_TEST_LOG_NO_FLUSH;
992e5c31af7Sopenharmony_ci
993e5c31af7Sopenharmony_ci	if (m_cmdLine.getOption<opt::LogCompact>())
994e5c31af7Sopenharmony_ci		m_logFlags |= QP_TEST_LOG_COMPACT;
995e5c31af7Sopenharmony_ci
996e5c31af7Sopenharmony_ci	if (!m_cmdLine.getOption<opt::LogEmptyLoginfo>())
997e5c31af7Sopenharmony_ci		m_logFlags |= QP_TEST_LOG_EXCLUDE_EMPTY_LOGINFO;
998e5c31af7Sopenharmony_ci
999e5c31af7Sopenharmony_ci	if (m_cmdLine.getOption<opt::SubProcess>())
1000e5c31af7Sopenharmony_ci		m_logFlags |= QP_TEST_LOG_NO_INITIAL_OUTPUT;
1001e5c31af7Sopenharmony_ci
1002e5c31af7Sopenharmony_ci	if ((m_cmdLine.hasOption<opt::CasePath>()?1:0) +
1003e5c31af7Sopenharmony_ci		(m_cmdLine.hasOption<opt::CaseList>()?1:0) +
1004e5c31af7Sopenharmony_ci		(m_cmdLine.hasOption<opt::CaseListFile>()?1:0) +
1005e5c31af7Sopenharmony_ci		(m_cmdLine.hasOption<opt::CaseListResource>()?1:0) +
1006e5c31af7Sopenharmony_ci		(m_cmdLine.getOption<opt::StdinCaseList>()?1:0) > 1)
1007e5c31af7Sopenharmony_ci	{
1008e5c31af7Sopenharmony_ci		debugOut << "ERROR: multiple test case list options given!\n" << std::endl;
1009e5c31af7Sopenharmony_ci		clear();
1010e5c31af7Sopenharmony_ci		return false;
1011e5c31af7Sopenharmony_ci	}
1012e5c31af7Sopenharmony_ci
1013e5c31af7Sopenharmony_ci	if (m_cmdLine.getArgs().size() > 0)
1014e5c31af7Sopenharmony_ci	{
1015e5c31af7Sopenharmony_ci		debugOut << "ERROR: arguments not starting with '-' or '--' are not supported by this application!\n" << std::endl;
1016e5c31af7Sopenharmony_ci
1017e5c31af7Sopenharmony_ci		debugOut << "\n" << de::FilePath(argv[0]).getBaseName() << " [options]\n\n";
1018e5c31af7Sopenharmony_ci		parser.help(debugOut);
1019e5c31af7Sopenharmony_ci
1020e5c31af7Sopenharmony_ci		clear();
1021e5c31af7Sopenharmony_ci		return false;
1022e5c31af7Sopenharmony_ci	}
1023e5c31af7Sopenharmony_ci
1024e5c31af7Sopenharmony_ci	return true;
1025e5c31af7Sopenharmony_ci}
1026e5c31af7Sopenharmony_ci
1027e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*!
1028e5c31af7Sopenharmony_ci * \brief Parse command line from string.
1029e5c31af7Sopenharmony_ci * \note parse() must be called exactly once.
1030e5c31af7Sopenharmony_ci * \param cmdLine Full command line string.
1031e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
1032e5c31af7Sopenharmony_cibool CommandLine::parse (const std::string& cmdLine)
1033e5c31af7Sopenharmony_ci{
1034e5c31af7Sopenharmony_ci	deCommandLine* parsedCmdLine = deCommandLine_parse(cmdLine.c_str());
1035e5c31af7Sopenharmony_ci	if (!parsedCmdLine)
1036e5c31af7Sopenharmony_ci		throw std::bad_alloc();
1037e5c31af7Sopenharmony_ci
1038e5c31af7Sopenharmony_ci	bool isOk = false;
1039e5c31af7Sopenharmony_ci	try
1040e5c31af7Sopenharmony_ci	{
1041e5c31af7Sopenharmony_ci		isOk = parse(parsedCmdLine->numArgs, parsedCmdLine->args);
1042e5c31af7Sopenharmony_ci	}
1043e5c31af7Sopenharmony_ci	catch (...)
1044e5c31af7Sopenharmony_ci	{
1045e5c31af7Sopenharmony_ci		deCommandLine_destroy(parsedCmdLine);
1046e5c31af7Sopenharmony_ci		throw;
1047e5c31af7Sopenharmony_ci	}
1048e5c31af7Sopenharmony_ci
1049e5c31af7Sopenharmony_ci	deCommandLine_destroy(parsedCmdLine);
1050e5c31af7Sopenharmony_ci	return isOk;
1051e5c31af7Sopenharmony_ci}
1052e5c31af7Sopenharmony_ci
1053e5c31af7Sopenharmony_ciconst char*				CommandLine::getLogFileName					(void) const	{ return m_cmdLine.getOption<opt::LogFilename>().c_str();					}
1054e5c31af7Sopenharmony_cideUint32				CommandLine::getLogFlags					(void) const	{ return m_logFlags;														}
1055e5c31af7Sopenharmony_ciRunMode					CommandLine::getRunMode						(void) const	{ return m_cmdLine.getOption<opt::RunMode>();								}
1056e5c31af7Sopenharmony_ciconst char*				CommandLine::getCaseListExportFile			(void) const	{ return m_cmdLine.getOption<opt::ExportFilenamePattern>().c_str();			}
1057e5c31af7Sopenharmony_ciWindowVisibility		CommandLine::getVisibility					(void) const	{ return m_cmdLine.getOption<opt::Visibility>();							}
1058e5c31af7Sopenharmony_cibool					CommandLine::isWatchDogEnabled				(void) const	{ return m_cmdLine.getOption<opt::WatchDog>();								}
1059e5c31af7Sopenharmony_cibool					CommandLine::isCrashHandlingEnabled			(void) const	{ return m_cmdLine.getOption<opt::CrashHandler>();							}
1060e5c31af7Sopenharmony_ciint						CommandLine::getBaseSeed					(void) const	{ return m_cmdLine.getOption<opt::BaseSeed>();								}
1061e5c31af7Sopenharmony_ciint						CommandLine::getTestIterationCount			(void) const	{ return m_cmdLine.getOption<opt::TestIterationCount>();					}
1062e5c31af7Sopenharmony_ciint						CommandLine::getSurfaceWidth				(void) const	{ return m_cmdLine.getOption<opt::SurfaceWidth>();							}
1063e5c31af7Sopenharmony_ciint						CommandLine::getSurfaceHeight				(void) const	{ return m_cmdLine.getOption<opt::SurfaceHeight>();							}
1064e5c31af7Sopenharmony_ciSurfaceType				CommandLine::getSurfaceType					(void) const	{ return m_cmdLine.getOption<opt::SurfaceType>();							}
1065e5c31af7Sopenharmony_ciScreenRotation			CommandLine::getScreenRotation				(void) const	{ return m_cmdLine.getOption<opt::ScreenRotation>();						}
1066e5c31af7Sopenharmony_ciint						CommandLine::getGLConfigId					(void) const	{ return m_cmdLine.getOption<opt::GLConfigID>();							}
1067e5c31af7Sopenharmony_ciint						CommandLine::getCLPlatformId				(void) const	{ return m_cmdLine.getOption<opt::CLPlatformID>();							}
1068e5c31af7Sopenharmony_ciconst std::vector<int>&	CommandLine::getCLDeviceIds					(void) const	{ return m_cmdLine.getOption<opt::CLDeviceIDs>();							}
1069e5c31af7Sopenharmony_ciint						CommandLine::getVKDeviceId					(void) const	{ return m_cmdLine.getOption<opt::VKDeviceID>();							}
1070e5c31af7Sopenharmony_ciint						CommandLine::getVKDeviceGroupId				(void) const	{ return m_cmdLine.getOption<opt::VKDeviceGroupID>();						}
1071e5c31af7Sopenharmony_cibool					CommandLine::isValidationEnabled			(void) const	{ return m_cmdLine.getOption<opt::Validation>();							}
1072e5c31af7Sopenharmony_cibool					CommandLine::printValidationErrors			(void) const	{ return m_cmdLine.getOption<opt::PrintValidationErrors>();					}
1073e5c31af7Sopenharmony_cibool					CommandLine::isLogDecompiledSpirvEnabled	(void) const	{ return m_cmdLine.getOption<opt::LogDecompiledSpirv>();					}
1074e5c31af7Sopenharmony_cibool					CommandLine::isOutOfMemoryTestEnabled		(void) const	{ return m_cmdLine.getOption<opt::TestOOM>();								}
1075e5c31af7Sopenharmony_cibool					CommandLine::isShadercacheEnabled			(void) const	{ return m_cmdLine.getOption<opt::ShaderCache>();							}
1076e5c31af7Sopenharmony_ciconst char*				CommandLine::getShaderCacheFilename			(void) const	{ return m_cmdLine.getOption<opt::ShaderCacheFilename>().c_str();			}
1077e5c31af7Sopenharmony_cibool					CommandLine::isShaderCacheTruncateEnabled	(void) const	{ return m_cmdLine.getOption<opt::ShaderCacheTruncate>();					}
1078e5c31af7Sopenharmony_cibool					CommandLine::isShaderCacheIPCEnabled		(void) const	{ return m_cmdLine.getOption<opt::ShaderCacheIPC>();						}
1079e5c31af7Sopenharmony_ciint						CommandLine::getOptimizationRecipe			(void) const	{ return m_cmdLine.getOption<opt::Optimization>();							}
1080e5c31af7Sopenharmony_cibool					CommandLine::isSpirvOptimizationEnabled		(void) const	{ return m_cmdLine.getOption<opt::OptimizeSpirv>();							}
1081e5c31af7Sopenharmony_cibool					CommandLine::isRenderDocEnabled				(void) const	{ return m_cmdLine.getOption<opt::RenderDoc>();								}
1082e5c31af7Sopenharmony_ciconst char*				CommandLine::getWaiverFileName				(void) const	{ return m_cmdLine.getOption<opt::WaiverFile>().c_str();					}
1083e5c31af7Sopenharmony_ciconst std::vector<int>&	CommandLine::getCaseFraction				(void) const	{ return m_cmdLine.getOption<opt::CaseFraction>();							}
1084e5c31af7Sopenharmony_ciconst char*				CommandLine::getCaseFractionMandatoryTests	(void) const	{ return m_cmdLine.getOption<opt::CaseFractionMandatoryTests>().c_str();	}
1085e5c31af7Sopenharmony_ciconst char*				CommandLine::getArchiveDir					(void) const	{ return m_cmdLine.getOption<opt::ArchiveDir>().c_str();					}
1086e5c31af7Sopenharmony_citcu::TestRunnerType		CommandLine::getRunnerType					(void) const	{ return m_cmdLine.getOption<opt::RunnerType>();							}
1087e5c31af7Sopenharmony_cibool					CommandLine::isTerminateOnFailEnabled		(void) const	{ return m_cmdLine.getOption<opt::TerminateOnFail>();						}
1088e5c31af7Sopenharmony_cibool					CommandLine::isSubProcess					(void) const	{ return m_cmdLine.getOption<opt::SubProcess>();							}
1089e5c31af7Sopenharmony_ciint						CommandLine::getSubprocessTestCount			(void) const	{ return m_cmdLine.getOption<opt::SubprocessTestCount>();					}
1090e5c31af7Sopenharmony_ciint						CommandLine::getCommandPoolMinSize			(void) const	{ return m_cmdLine.getOption<opt::CommandPoolMinSize>();					}
1091e5c31af7Sopenharmony_ciint						CommandLine::getCommandBufferMinSize		(void) const	{ return m_cmdLine.getOption<opt::CommandBufferMinSize>();					}
1092e5c31af7Sopenharmony_ciint						CommandLine::getCommandDefaultSize			(void) const	{ return m_cmdLine.getOption<opt::CommandDefaultSize>();					}
1093e5c31af7Sopenharmony_ciint						CommandLine::getPipelineDefaultSize			(void) const	{ return m_cmdLine.getOption<opt::PipelineDefaultSize>();					}
1094e5c31af7Sopenharmony_ci
1095e5c31af7Sopenharmony_ciconst char* CommandLine::getGLContextType (void) const
1096e5c31af7Sopenharmony_ci{
1097e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::GLContextType>())
1098e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::GLContextType>().c_str();
1099e5c31af7Sopenharmony_ci	else
1100e5c31af7Sopenharmony_ci		return DE_NULL;
1101e5c31af7Sopenharmony_ci}
1102e5c31af7Sopenharmony_ciconst char* CommandLine::getGLConfigName (void) const
1103e5c31af7Sopenharmony_ci{
1104e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::GLConfigName>())
1105e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::GLConfigName>().c_str();
1106e5c31af7Sopenharmony_ci	else
1107e5c31af7Sopenharmony_ci		return DE_NULL;
1108e5c31af7Sopenharmony_ci}
1109e5c31af7Sopenharmony_ci
1110e5c31af7Sopenharmony_ciconst char* CommandLine::getGLContextFlags (void) const
1111e5c31af7Sopenharmony_ci{
1112e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::GLContextFlags>())
1113e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::GLContextFlags>().c_str();
1114e5c31af7Sopenharmony_ci	else
1115e5c31af7Sopenharmony_ci		return DE_NULL;
1116e5c31af7Sopenharmony_ci}
1117e5c31af7Sopenharmony_ci
1118e5c31af7Sopenharmony_ciconst char* CommandLine::getCLBuildOptions (void) const
1119e5c31af7Sopenharmony_ci{
1120e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::CLBuildOptions>())
1121e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::CLBuildOptions>().c_str();
1122e5c31af7Sopenharmony_ci	else
1123e5c31af7Sopenharmony_ci		return DE_NULL;
1124e5c31af7Sopenharmony_ci}
1125e5c31af7Sopenharmony_ci
1126e5c31af7Sopenharmony_ciconst char* CommandLine::getEGLDisplayType (void) const
1127e5c31af7Sopenharmony_ci{
1128e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::EGLDisplayType>())
1129e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::EGLDisplayType>().c_str();
1130e5c31af7Sopenharmony_ci	else
1131e5c31af7Sopenharmony_ci		return DE_NULL;
1132e5c31af7Sopenharmony_ci}
1133e5c31af7Sopenharmony_ci
1134e5c31af7Sopenharmony_ciconst char* CommandLine::getEGLWindowType (void) const
1135e5c31af7Sopenharmony_ci{
1136e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::EGLWindowType>())
1137e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::EGLWindowType>().c_str();
1138e5c31af7Sopenharmony_ci	else
1139e5c31af7Sopenharmony_ci		return DE_NULL;
1140e5c31af7Sopenharmony_ci}
1141e5c31af7Sopenharmony_ci
1142e5c31af7Sopenharmony_ciconst char* CommandLine::getEGLPixmapType (void) const
1143e5c31af7Sopenharmony_ci{
1144e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::EGLPixmapType>())
1145e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::EGLPixmapType>().c_str();
1146e5c31af7Sopenharmony_ci	else
1147e5c31af7Sopenharmony_ci		return DE_NULL;
1148e5c31af7Sopenharmony_ci}
1149e5c31af7Sopenharmony_ci
1150e5c31af7Sopenharmony_ciconst char* CommandLine::getSubprocessConfigFile (void) const
1151e5c31af7Sopenharmony_ci{
1152e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::SubprocessConfigFile>())
1153e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::SubprocessConfigFile>().c_str();
1154e5c31af7Sopenharmony_ci	else
1155e5c31af7Sopenharmony_ci		return DE_NULL;
1156e5c31af7Sopenharmony_ci}
1157e5c31af7Sopenharmony_ci
1158e5c31af7Sopenharmony_ci
1159e5c31af7Sopenharmony_ciconst char* CommandLine::getServerAddress (void) const
1160e5c31af7Sopenharmony_ci{
1161e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::ServerAddress>())
1162e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::ServerAddress>().c_str();
1163e5c31af7Sopenharmony_ci	else
1164e5c31af7Sopenharmony_ci		return DE_NULL;
1165e5c31af7Sopenharmony_ci}
1166e5c31af7Sopenharmony_ci
1167e5c31af7Sopenharmony_ciconst char* CommandLine::getPipelineCompilerPath(void) const
1168e5c31af7Sopenharmony_ci{
1169e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::PipelineCompilerPath>())
1170e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::PipelineCompilerPath>().c_str();
1171e5c31af7Sopenharmony_ci	else
1172e5c31af7Sopenharmony_ci		return DE_NULL;
1173e5c31af7Sopenharmony_ci}
1174e5c31af7Sopenharmony_ci
1175e5c31af7Sopenharmony_ciconst char* CommandLine::getPipelineCompilerDataDir(void) const
1176e5c31af7Sopenharmony_ci{
1177e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::PipelineCompilerDataDir>())
1178e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::PipelineCompilerDataDir>().c_str();
1179e5c31af7Sopenharmony_ci	else
1180e5c31af7Sopenharmony_ci		return DE_NULL;
1181e5c31af7Sopenharmony_ci}
1182e5c31af7Sopenharmony_ci
1183e5c31af7Sopenharmony_ciconst char* CommandLine::getPipelineCompilerArgs(void) const
1184e5c31af7Sopenharmony_ci{
1185e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::PipelineCompilerArgs>())
1186e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::PipelineCompilerArgs>().c_str();
1187e5c31af7Sopenharmony_ci	else
1188e5c31af7Sopenharmony_ci		return DE_NULL;
1189e5c31af7Sopenharmony_ci}
1190e5c31af7Sopenharmony_ci
1191e5c31af7Sopenharmony_ciconst char* CommandLine::getPipelineCompilerOutputFile(void) const
1192e5c31af7Sopenharmony_ci{
1193e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::PipelineCompilerOutputFile>())
1194e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::PipelineCompilerOutputFile>().c_str();
1195e5c31af7Sopenharmony_ci	else
1196e5c31af7Sopenharmony_ci		return DE_NULL;
1197e5c31af7Sopenharmony_ci}
1198e5c31af7Sopenharmony_ci
1199e5c31af7Sopenharmony_ciconst char* CommandLine::getPipelineCompilerLogFile(void) const
1200e5c31af7Sopenharmony_ci{
1201e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::PipelineCompilerLogFile>())
1202e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::PipelineCompilerLogFile>().c_str();
1203e5c31af7Sopenharmony_ci	else
1204e5c31af7Sopenharmony_ci		return DE_NULL;
1205e5c31af7Sopenharmony_ci}
1206e5c31af7Sopenharmony_ci
1207e5c31af7Sopenharmony_ciconst char* CommandLine::getPipelineCompilerFilePrefix(void) const
1208e5c31af7Sopenharmony_ci{
1209e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::PipelineCompilerFilePrefix>())
1210e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::PipelineCompilerFilePrefix>().c_str();
1211e5c31af7Sopenharmony_ci	else
1212e5c31af7Sopenharmony_ci		return DE_NULL;
1213e5c31af7Sopenharmony_ci}
1214e5c31af7Sopenharmony_ci
1215e5c31af7Sopenharmony_ciconst char* CommandLine::getVkLibraryPath(void) const
1216e5c31af7Sopenharmony_ci{
1217e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::VkLibraryPath>())
1218e5c31af7Sopenharmony_ci		return (m_cmdLine.getOption<opt::VkLibraryPath>() != "") ? m_cmdLine.getOption<opt::VkLibraryPath>().c_str() : DE_NULL;
1219e5c31af7Sopenharmony_ci	else
1220e5c31af7Sopenharmony_ci		return DE_NULL;
1221e5c31af7Sopenharmony_ci}
1222e5c31af7Sopenharmony_ci
1223e5c31af7Sopenharmony_ciconst char* CommandLine::getAppParamsInputFilePath(void) const
1224e5c31af7Sopenharmony_ci{
1225e5c31af7Sopenharmony_ci	if (m_cmdLine.hasOption<opt::ApplicationParametersInputFile>())
1226e5c31af7Sopenharmony_ci		return m_cmdLine.getOption<opt::ApplicationParametersInputFile>().c_str();
1227e5c31af7Sopenharmony_ci	else
1228e5c31af7Sopenharmony_ci		return DE_NULL;
1229e5c31af7Sopenharmony_ci}
1230e5c31af7Sopenharmony_ci
1231e5c31af7Sopenharmony_cistatic bool checkTestGroupName (const CaseTreeNode* root, const char* groupPath)
1232e5c31af7Sopenharmony_ci{
1233e5c31af7Sopenharmony_ci	const CaseTreeNode* node = findNode(root, groupPath);
1234e5c31af7Sopenharmony_ci	return node && node->hasChildren();
1235e5c31af7Sopenharmony_ci}
1236e5c31af7Sopenharmony_ci
1237e5c31af7Sopenharmony_cistatic bool checkTestCaseName (const CaseTreeNode* root, const char* casePath)
1238e5c31af7Sopenharmony_ci{
1239e5c31af7Sopenharmony_ci	const CaseTreeNode* node = findNode(root, casePath);
1240e5c31af7Sopenharmony_ci	return node && !node->hasChildren();
1241e5c31af7Sopenharmony_ci}
1242e5c31af7Sopenharmony_ci
1243e5c31af7Sopenharmony_cide::MovePtr<CaseListFilter> CommandLine::createCaseListFilter (const tcu::Archive& archive) const
1244e5c31af7Sopenharmony_ci{
1245e5c31af7Sopenharmony_ci	return de::MovePtr<CaseListFilter>(new CaseListFilter(m_cmdLine, archive));
1246e5c31af7Sopenharmony_ci}
1247e5c31af7Sopenharmony_ci
1248e5c31af7Sopenharmony_cibool CaseListFilter::checkTestGroupName (const char* groupName) const
1249e5c31af7Sopenharmony_ci{
1250e5c31af7Sopenharmony_ci	bool result = false;
1251e5c31af7Sopenharmony_ci	if (m_casePaths)
1252e5c31af7Sopenharmony_ci		result = m_casePaths->matches(groupName, true);
1253e5c31af7Sopenharmony_ci	else if (m_caseTree)
1254e5c31af7Sopenharmony_ci		result = ( groupName[0] == 0 || tcu::checkTestGroupName(m_caseTree, groupName) );
1255e5c31af7Sopenharmony_ci	else
1256e5c31af7Sopenharmony_ci		return true;
1257e5c31af7Sopenharmony_ci	if (!result && m_caseFractionMandatoryTests.get() != DE_NULL)
1258e5c31af7Sopenharmony_ci		result = m_caseFractionMandatoryTests->matches(groupName, true);
1259e5c31af7Sopenharmony_ci	return result;
1260e5c31af7Sopenharmony_ci}
1261e5c31af7Sopenharmony_ci
1262e5c31af7Sopenharmony_cibool CaseListFilter::checkTestCaseName (const char* caseName) const
1263e5c31af7Sopenharmony_ci{
1264e5c31af7Sopenharmony_ci	bool result = false;
1265e5c31af7Sopenharmony_ci	if (m_casePaths)
1266e5c31af7Sopenharmony_ci		result = m_casePaths->matches(caseName, false);
1267e5c31af7Sopenharmony_ci	else if (m_caseTree)
1268e5c31af7Sopenharmony_ci		result = tcu::checkTestCaseName(m_caseTree, caseName);
1269e5c31af7Sopenharmony_ci	else
1270e5c31af7Sopenharmony_ci		return true;
1271e5c31af7Sopenharmony_ci	if (!result && m_caseFractionMandatoryTests.get() != DE_NULL)
1272e5c31af7Sopenharmony_ci		result = m_caseFractionMandatoryTests->matches(caseName, false);
1273e5c31af7Sopenharmony_ci	return result;
1274e5c31af7Sopenharmony_ci}
1275e5c31af7Sopenharmony_ci
1276e5c31af7Sopenharmony_cibool CaseListFilter::checkCaseFraction (int i, const std::string& testCaseName) const
1277e5c31af7Sopenharmony_ci{
1278e5c31af7Sopenharmony_ci	return	m_caseFraction.size() != 2 ||
1279e5c31af7Sopenharmony_ci		((i % m_caseFraction[1]) == m_caseFraction[0]) ||
1280e5c31af7Sopenharmony_ci		(m_caseFractionMandatoryTests.get()!=DE_NULL && m_caseFractionMandatoryTests->matches(testCaseName));
1281e5c31af7Sopenharmony_ci}
1282e5c31af7Sopenharmony_ci
1283e5c31af7Sopenharmony_ciCaseListFilter::CaseListFilter (void)
1284e5c31af7Sopenharmony_ci	: m_caseTree	(DE_NULL)
1285e5c31af7Sopenharmony_ci	, m_runnerType	(tcu::RUNNERTYPE_ANY)
1286e5c31af7Sopenharmony_ci{
1287e5c31af7Sopenharmony_ci}
1288e5c31af7Sopenharmony_ci
1289e5c31af7Sopenharmony_ciCaseListFilter::CaseListFilter (const de::cmdline::CommandLine& cmdLine, const tcu::Archive& archive)
1290e5c31af7Sopenharmony_ci	: m_caseTree	(DE_NULL)
1291e5c31af7Sopenharmony_ci{
1292e5c31af7Sopenharmony_ci	if (cmdLine.getOption<opt::RunMode>() == RUNMODE_VERIFY_AMBER_COHERENCY)
1293e5c31af7Sopenharmony_ci	{
1294e5c31af7Sopenharmony_ci		m_runnerType = RUNNERTYPE_AMBER;
1295e5c31af7Sopenharmony_ci	}
1296e5c31af7Sopenharmony_ci	else
1297e5c31af7Sopenharmony_ci	{
1298e5c31af7Sopenharmony_ci		m_runnerType = cmdLine.getOption<opt::RunnerType>();
1299e5c31af7Sopenharmony_ci	}
1300e5c31af7Sopenharmony_ci
1301e5c31af7Sopenharmony_ci	if (cmdLine.hasOption<opt::CaseList>())
1302e5c31af7Sopenharmony_ci	{
1303e5c31af7Sopenharmony_ci		std::istringstream str(cmdLine.getOption<opt::CaseList>());
1304e5c31af7Sopenharmony_ci
1305e5c31af7Sopenharmony_ci		m_caseTree = parseCaseList(str, archive);
1306e5c31af7Sopenharmony_ci	}
1307e5c31af7Sopenharmony_ci	else if (cmdLine.hasOption<opt::CaseListFile>())
1308e5c31af7Sopenharmony_ci	{
1309e5c31af7Sopenharmony_ci		std::string caseListFile = cmdLine.getOption<opt::CaseListFile>();
1310e5c31af7Sopenharmony_ci		std::ifstream in(caseListFile.c_str(), std::ios_base::binary);
1311e5c31af7Sopenharmony_ci
1312e5c31af7Sopenharmony_ci		if (!in.is_open() || !in.good())
1313e5c31af7Sopenharmony_ci			throw Exception("Failed to open case list file '" + caseListFile + "'");
1314e5c31af7Sopenharmony_ci
1315e5c31af7Sopenharmony_ci		m_caseTree = parseCaseList(in, archive, caseListFile.c_str());
1316e5c31af7Sopenharmony_ci	}
1317e5c31af7Sopenharmony_ci	else if (cmdLine.hasOption<opt::CaseListResource>())
1318e5c31af7Sopenharmony_ci	{
1319e5c31af7Sopenharmony_ci		// \todo [2016-11-14 pyry] We are cloning potentially large buffers here. Consider writing
1320e5c31af7Sopenharmony_ci		//						   istream adaptor for tcu::Resource.
1321e5c31af7Sopenharmony_ci		de::UniquePtr<Resource>	caseListResource	(archive.getResource(cmdLine.getOption<opt::CaseListResource>().c_str()));
1322e5c31af7Sopenharmony_ci		const int				bufferSize			= caseListResource->getSize();
1323e5c31af7Sopenharmony_ci		std::vector<char>		buffer				((size_t)bufferSize);
1324e5c31af7Sopenharmony_ci
1325e5c31af7Sopenharmony_ci		if (buffer.empty())
1326e5c31af7Sopenharmony_ci			throw Exception("Empty case list resource");
1327e5c31af7Sopenharmony_ci
1328e5c31af7Sopenharmony_ci		caseListResource->read(reinterpret_cast<deUint8*>(&buffer[0]), bufferSize);
1329e5c31af7Sopenharmony_ci
1330e5c31af7Sopenharmony_ci		{
1331e5c31af7Sopenharmony_ci			std::istringstream	in	(std::string(&buffer[0], (size_t)bufferSize));
1332e5c31af7Sopenharmony_ci
1333e5c31af7Sopenharmony_ci			m_caseTree = parseCaseList(in, archive);
1334e5c31af7Sopenharmony_ci		}
1335e5c31af7Sopenharmony_ci	}
1336e5c31af7Sopenharmony_ci	else if (cmdLine.getOption<opt::StdinCaseList>())
1337e5c31af7Sopenharmony_ci	{
1338e5c31af7Sopenharmony_ci		m_caseTree = parseCaseList(std::cin, archive);
1339e5c31af7Sopenharmony_ci	}
1340e5c31af7Sopenharmony_ci	else if (cmdLine.hasOption<opt::CasePath>())
1341e5c31af7Sopenharmony_ci		m_casePaths = de::MovePtr<const CasePaths>(new CasePaths(cmdLine.getOption<opt::CasePath>()));
1342e5c31af7Sopenharmony_ci
1343e5c31af7Sopenharmony_ci	if (!cmdLine.getOption<opt::SubProcess>())
1344e5c31af7Sopenharmony_ci		m_caseFraction = cmdLine.getOption<opt::CaseFraction>();
1345e5c31af7Sopenharmony_ci
1346e5c31af7Sopenharmony_ci	if (m_caseFraction.size() == 2 &&
1347e5c31af7Sopenharmony_ci		(m_caseFraction[0] < 0 || m_caseFraction[1] <= 0 || m_caseFraction[0] >= m_caseFraction[1] ))
1348e5c31af7Sopenharmony_ci		throw Exception("Invalid case fraction. First element must be non-negative and less than second element. Second element must be greater than 0.");
1349e5c31af7Sopenharmony_ci
1350e5c31af7Sopenharmony_ci	if (m_caseFraction.size() != 0 && m_caseFraction.size() != 2)
1351e5c31af7Sopenharmony_ci		throw Exception("Invalid case fraction. Must have two components.");
1352e5c31af7Sopenharmony_ci
1353e5c31af7Sopenharmony_ci	if (m_caseFraction.size() == 2)
1354e5c31af7Sopenharmony_ci	{
1355e5c31af7Sopenharmony_ci		std::string					caseFractionMandatoryTestsFilename = cmdLine.getOption<opt::CaseFractionMandatoryTests>();
1356e5c31af7Sopenharmony_ci
1357e5c31af7Sopenharmony_ci		if (!caseFractionMandatoryTestsFilename.empty())
1358e5c31af7Sopenharmony_ci		{
1359e5c31af7Sopenharmony_ci			std::ifstream fileStream(caseFractionMandatoryTestsFilename.c_str(), std::ios_base::binary);
1360e5c31af7Sopenharmony_ci			if (!fileStream.is_open() || !fileStream.good())
1361e5c31af7Sopenharmony_ci				throw Exception("Failed to open case fraction mandatory test list: '" + caseFractionMandatoryTestsFilename + "'");
1362e5c31af7Sopenharmony_ci
1363e5c31af7Sopenharmony_ci			std::vector<std::string>	cfPaths;
1364e5c31af7Sopenharmony_ci			std::string					line;
1365e5c31af7Sopenharmony_ci
1366e5c31af7Sopenharmony_ci			while (std::getline(fileStream, line))
1367e5c31af7Sopenharmony_ci			{
1368e5c31af7Sopenharmony_ci				line.erase(std::remove(std::begin(line), std::end(line), '\r'), std::end(line));
1369e5c31af7Sopenharmony_ci				cfPaths.push_back(line);
1370e5c31af7Sopenharmony_ci			}
1371e5c31af7Sopenharmony_ci			if (!cfPaths.empty())
1372e5c31af7Sopenharmony_ci			{
1373e5c31af7Sopenharmony_ci				m_caseFractionMandatoryTests = de::MovePtr<const CasePaths>(new CasePaths(cfPaths));
1374e5c31af7Sopenharmony_ci				if (m_caseTree != DE_NULL)
1375e5c31af7Sopenharmony_ci				{
1376e5c31af7Sopenharmony_ci					fileStream.clear();
1377e5c31af7Sopenharmony_ci					fileStream.seekg(0, fileStream.beg);
1378e5c31af7Sopenharmony_ci					std::unordered_map<test_case_hash_t, std::string> hashCollisionDetectionMap{};
1379e5c31af7Sopenharmony_ci					parseCaseList(m_caseTree, fileStream, false, hashCollisionDetectionMap);
1380e5c31af7Sopenharmony_ci				}
1381e5c31af7Sopenharmony_ci			}
1382e5c31af7Sopenharmony_ci		}
1383e5c31af7Sopenharmony_ci	}
1384e5c31af7Sopenharmony_ci}
1385e5c31af7Sopenharmony_ci
1386e5c31af7Sopenharmony_ciCaseListFilter::~CaseListFilter (void)
1387e5c31af7Sopenharmony_ci{
1388e5c31af7Sopenharmony_ci	delete m_caseTree;
1389e5c31af7Sopenharmony_ci}
1390e5c31af7Sopenharmony_ci
1391e5c31af7Sopenharmony_ci} // tcu
1392