Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #pragma once 11 : 12 : #include "StreamArguments.h" 13 : 14 : #include <exception> 15 : #include <variant> 16 : #include <string> 17 : #include <sstream> 18 : #include <tuple> 19 : #include <map> 20 : 21 : /** 22 : * Shared code for the Capabilities Registry and the python bindings to the Capabilities system. 23 : */ 24 : namespace CapabilityUtils 25 : { 26 : 27 : class CapabilityException : public std::runtime_error 28 : { 29 : public: 30 : CapabilityException(const CapabilityException &) = default; 31 : 32 : template <typename... Args> 33 13 : static std::string stringify(Args &&... args) 34 : { 35 13 : std::ostringstream ss; 36 13 : streamArguments(ss, args...); 37 26 : return ss.str(); 38 13 : } 39 : 40 : template <typename... Args> 41 13 : explicit CapabilityException(Args &&... args) : std::runtime_error(stringify(args...)) 42 : { 43 13 : } 44 : 45 13 : ~CapabilityException() throw() {} 46 : }; 47 : 48 : /** 49 : * Return state for check. We use a plain enum because we rely on implicit conversion to int. 50 : * Capability checks are run in the test harness using the JSON dump exported from the executable 51 : * using `--show-capabilities`. This static check does not take dynamic loading into account, 52 : * as capabilities that would be registered after initializing the dynamically loaded application 53 : * will not exist with `--show-capabilities`. 54 : * 55 : * A requested capability that is not registered at all is considered in a "possible" state, 56 : * as we cannot guarantee that it does or not exist with a dynamic application. If no dynamic 57 : * application loading is used, the possible states can be considered certain states. 58 : * 59 : * When the test harness Tester specification "dynamic_capabilities" is set to True, 60 : * it will run the test unless the result of the check is CERTAIN_FAIL. In this case, 61 : * the runtime check in the executable will terminate if the result is either CERTAIN_FAIL 62 : * or POSSIBLE_FAIL. 63 : */ 64 : enum CheckState 65 : { 66 : CERTAIN_FAIL = 0, 67 : POSSIBLE_FAIL = 1, 68 : UNKNOWN = 2, 69 : POSSIBLE_PASS = 3, 70 : CERTAIN_PASS = 4, 71 : PARSE_FAIL = 5 72 : }; 73 : 74 : /// A capability can have a bool, int, or string value 75 : typedef std::variant<bool, int, std::string> Type; 76 : /// Result from a capability check: the state, the reason, and the documentation 77 : typedef std::tuple<CheckState, std::string, std::string> Result; 78 : /// The registry that stores the registered capabilities 79 : typedef std::map<std::string, std::pair<Type, std::string>> Registry; 80 : 81 : /** 82 : * Checks if a set of requirements is satisified by the given capability registry 83 : * 84 : * @param requirements The requirement string 85 : * @param capabilities The registry that contains the capabilities 86 : * 87 : * This method is exposed to Python within the capabilities_check method in 88 : * framework/contrib/capabilities/capabilities.C. This external method is used 89 : * significantly by the TestHarness to check capabilities for individual test specs. 90 : * 91 : * Additionally, this method is used by the MooseApp command line option 92 : * "--required-capabilities ...". 93 : * 94 : * Requirements can use comparison operators (>,<,>=,<=,=!,=), where the name of 95 : * the capability must always be on the left hand side. Comparisons can be performed 96 : * on strings "compiler!=GCC" (which are case insensitive), integer numbers 97 : * "ad_size>=50", and version numbers "petsc>3.8.0". The state of a boolean 98 : * valued capability can be tested by just specifying the capability name "chaco". 99 : * This check can be inverted using the ! operator as "!chaco". 100 : * 101 : * The logic operators & and | can be used to chain multiple checks as 102 : * "thermochimica & thermochimica>1.0". Parenthesis can be used to build 103 : * complex logic expressions. 104 : * 105 : * See the description for CheckState for more information on why a 106 : * certain state would be returned. 107 : */ 108 : Result check(std::string requirements, const Registry & capabilities); 109 : 110 : } // namespace CapabilityUtils