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 "Capability.h" 13 : 14 : #include <map> 15 : #include <set> 16 : #include <string> 17 : #include <utility> 18 : 19 : #ifdef MOOSE_UNIT_TEST 20 : class CapabilitiesTest; 21 : #endif 22 : 23 : namespace Moose::internal 24 : { 25 : 26 : class Capabilities; 27 : 28 : /** 29 : * Registry of capabilities that checks capability requirements. 30 : * 31 : * This registry is used both within MOOSE (in framework/src/base/Capabilities.C) 32 : * and within the python interface (in python/pycapabilities/_pycapabilities.C). 33 : */ 34 : class CapabilityRegistry 35 : { 36 : public: 37 : /// Capabilities that are reserved and can only be augmented 38 : static const std::set<std::string, std::less<>> augmented_capability_names; 39 : 40 32 : ~CapabilityRegistry() = default; 41 : 42 : /// Type for the registry 43 : using RegistryType = std::map<std::string, Capability, std::less<>>; 44 : 45 : /** 46 : * Return state for check. We use a plain enum because we rely on implicit conversion to int. 47 : * Capability checks are run in the test harness using the JSON dump exported from the 48 : * executable using `--show-capabilities`. This static check does not take dynamic loading into 49 : * account, as capabilities that would be registered after initializing the dynamically loaded 50 : * application will not exist with `--show-capabilities`. 51 : * 52 : * A requested capability that is not registered at all is considered in a "possible" state, 53 : * as we cannot guarantee that it does or not exist with a dynamic application. If no dynamic 54 : * application loading is used, the possible states can be considered certain states. 55 : * 56 : * When the test harness Tester specification "dynamic_capabilities" is set to True, 57 : * it will run the test unless the result of the check is CERTAIN_FAIL. In this case, 58 : * the runtime check in the executable will terminate if the result is either CERTAIN_FAIL 59 : * or POSSIBLE_FAIL. 60 : */ 61 : enum CheckState 62 : { 63 : CERTAIN_FAIL = 0, 64 : POSSIBLE_FAIL = 1, 65 : UNKNOWN = 2, 66 : POSSIBLE_PASS = 3, 67 : CERTAIN_PASS = 4, 68 : IGNORE = 5 69 : }; 70 : 71 : /** 72 : * Storage for the result from check(). 73 : */ 74 : struct CheckResult 75 : { 76 : /// State of the check 77 : CheckState state; 78 : /// The capability names that existed in the check string 79 : std::set<std::string> capability_names; 80 : }; 81 : 82 : /** 83 : * Options for check(). 84 : */ 85 : struct CheckOptions 86 : { 87 8493 : CheckOptions() : certain(true), ignore_capabilities() {} 88 : 89 : /// Whether or not all capabilities must be known 90 : bool certain; 91 : /// Capabilities to ignore; checks using them will always pass 92 : std::set<std::string> ignore_capabilities; 93 : }; 94 : 95 : /** 96 : * Add a capability. 97 : * 98 : * @param registry The registry 99 : * @param capability The name of the capability 100 : * @param value The value of the capability 101 : * @param doc The documentation string 102 : * @return The capability 103 : */ 104 : Capability & add(const std::string_view name, 105 : const Moose::Capability::Value & value, 106 : const std::string_view doc); 107 : 108 : /** 109 : * Query a capability, if it exists, otherwise nullptr. 110 : * 111 : * Will convert the capability name to lowercase. 112 : */ 113 : ///@{ 114 : const Capability * query(std::string capability) const; 115 : #if defined(MOOSE_UNIT_TEST) || defined(FOR_PYCAPABILITIES) 116 : inline Capability * query(std::string capability); 117 : #endif 118 : ///@} 119 : 120 : /** 121 : * Get a capability. 122 : * 123 : * Will convert the capability name to lowercase. 124 : */ 125 : ///@{ 126 : const Capability & get(const std::string & capability) const; 127 : #ifdef MOOSE_UNIT_TEST 128 : inline Capability & get(const std::string & capability); 129 : #endif 130 : ///@} 131 : 132 : /** 133 : * @return The size of the registry (number of capabilities registered). 134 : */ 135 8 : std::size_t size() const { return _registry.size(); } 136 : 137 : /** 138 : * Checks if a set of requirements is satisified by the capabilities 139 : * 140 : * @param requirements The requirement string 141 : * @param options Options to apply to the check 142 : * 143 : * This method is exposed to Python within pycapabilities.Capabilities.check in 144 : * python/pycapabilities/_pycapabilities.C. This external method is used 145 : * significantly by the TestHarness to check capabilities for individual test specs. 146 : * 147 : * Additionally, this method is used by the MooseApp command line option 148 : * "--required-capabilities ...". 149 : * 150 : * Requirements can use comparison operators (>,<,>=,<=,=!,=), where the name of 151 : * the capability must always be on the left hand side. Comparisons can be performed 152 : * on strings "compiler!=GCC" (which are case insensitive), integer numbers 153 : * "ad_size>=50", and version numbers "petsc>3.8.0". The state of a boolean 154 : * valued capability can be tested by just specifying the capability name "chaco". 155 : * This check can be inverted using the ! operator as "!chaco". 156 : * 157 : * The logic operators & and | can be used to chain multiple checks as 158 : * "thermochimica & thermochimica>1.0". Parenthesis can be used to build 159 : * complex logic expressions. 160 : */ 161 : CheckResult check( 162 : std::string requirements, 163 : const CapabilityRegistry::CheckOptions & options = CapabilityRegistry::CheckOptions()) const; 164 : 165 : protected: 166 : #ifdef MOOSE_UNIT_TEST 167 : friend class ::CapabilitiesTest; 168 : #endif 169 : 170 : /// Registry storage 171 : RegistryType _registry; 172 : }; 173 : 174 : #if defined(MOOSE_UNIT_TEST) || defined(FOR_PYCAPABILITIES) 175 : Capability * 176 32 : CapabilityRegistry::query(std::string capability) 177 : { 178 32 : return const_cast<Capability *>(std::as_const(*this).query(capability)); 179 : } 180 : #endif 181 : 182 : #ifdef MOOSE_UNIT_TEST 183 : Capability & 184 20 : CapabilityRegistry::get(const std::string & capability) 185 : { 186 20 : return const_cast<Capability &>(std::as_const(*this).get(capability)); 187 : } 188 : #endif 189 : } // namespace Moose::internal