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