1*257e70f1SIgor Ostapenko // Copyright 2023 The Kyua Authors. 2*257e70f1SIgor Ostapenko // All rights reserved. 3*257e70f1SIgor Ostapenko // 4*257e70f1SIgor Ostapenko // Redistribution and use in source and binary forms, with or without 5*257e70f1SIgor Ostapenko // modification, are permitted provided that the following conditions are 6*257e70f1SIgor Ostapenko // met: 7*257e70f1SIgor Ostapenko // 8*257e70f1SIgor Ostapenko // * Redistributions of source code must retain the above copyright 9*257e70f1SIgor Ostapenko // notice, this list of conditions and the following disclaimer. 10*257e70f1SIgor Ostapenko // * Redistributions in binary form must reproduce the above copyright 11*257e70f1SIgor Ostapenko // notice, this list of conditions and the following disclaimer in the 12*257e70f1SIgor Ostapenko // documentation and/or other materials provided with the distribution. 13*257e70f1SIgor Ostapenko // * Neither the name of Google Inc. nor the names of its contributors 14*257e70f1SIgor Ostapenko // may be used to endorse or promote products derived from this software 15*257e70f1SIgor Ostapenko // without specific prior written permission. 16*257e70f1SIgor Ostapenko // 17*257e70f1SIgor Ostapenko // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18*257e70f1SIgor Ostapenko // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*257e70f1SIgor Ostapenko // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20*257e70f1SIgor Ostapenko // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21*257e70f1SIgor Ostapenko // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22*257e70f1SIgor Ostapenko // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23*257e70f1SIgor Ostapenko // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24*257e70f1SIgor Ostapenko // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25*257e70f1SIgor Ostapenko // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26*257e70f1SIgor Ostapenko // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27*257e70f1SIgor Ostapenko // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*257e70f1SIgor Ostapenko 29*257e70f1SIgor Ostapenko /// \file engine/execenv/execenv.hpp 30*257e70f1SIgor Ostapenko /// Execution environment subsystem interface. 31*257e70f1SIgor Ostapenko 32*257e70f1SIgor Ostapenko #if !defined(ENGINE_EXECENV_EXECENV_HPP) 33*257e70f1SIgor Ostapenko #define ENGINE_EXECENV_EXECENV_HPP 34*257e70f1SIgor Ostapenko 35*257e70f1SIgor Ostapenko #include "model/test_program.hpp" 36*257e70f1SIgor Ostapenko #include "utils/optional.ipp" 37*257e70f1SIgor Ostapenko #include "utils/process/operations_fwd.hpp" 38*257e70f1SIgor Ostapenko 39*257e70f1SIgor Ostapenko using utils::process::args_vector; 40*257e70f1SIgor Ostapenko using utils::optional; 41*257e70f1SIgor Ostapenko 42*257e70f1SIgor Ostapenko namespace engine { 43*257e70f1SIgor Ostapenko namespace execenv { 44*257e70f1SIgor Ostapenko 45*257e70f1SIgor Ostapenko 46*257e70f1SIgor Ostapenko extern const char* default_execenv_name; 47*257e70f1SIgor Ostapenko 48*257e70f1SIgor Ostapenko 49*257e70f1SIgor Ostapenko /// Abstract interface of an execution environment. 50*257e70f1SIgor Ostapenko class interface { 51*257e70f1SIgor Ostapenko protected: 52*257e70f1SIgor Ostapenko const model::test_program& _test_program; 53*257e70f1SIgor Ostapenko const std::string& _test_case_name; 54*257e70f1SIgor Ostapenko 55*257e70f1SIgor Ostapenko public: 56*257e70f1SIgor Ostapenko /// Constructor. 57*257e70f1SIgor Ostapenko /// 58*257e70f1SIgor Ostapenko /// \param program The test program. 59*257e70f1SIgor Ostapenko /// \param test_case_name Name of the test case. interface(const model::test_program & test_program,const std::string & test_case_name)60*257e70f1SIgor Ostapenko interface(const model::test_program& test_program, 61*257e70f1SIgor Ostapenko const std::string& test_case_name) : 62*257e70f1SIgor Ostapenko _test_program(test_program), 63*257e70f1SIgor Ostapenko _test_case_name(test_case_name) 64*257e70f1SIgor Ostapenko {} 65*257e70f1SIgor Ostapenko 66*257e70f1SIgor Ostapenko /// Destructor. ~interface()67*257e70f1SIgor Ostapenko virtual ~interface() {} 68*257e70f1SIgor Ostapenko 69*257e70f1SIgor Ostapenko /// Initializes execution environment. 70*257e70f1SIgor Ostapenko /// 71*257e70f1SIgor Ostapenko /// It's expected to be called inside a fork which runs 72*257e70f1SIgor Ostapenko /// scheduler::interface::exec_test(), so we can fail a test fast if its 73*257e70f1SIgor Ostapenko /// execution environment setup fails, and test execution could use the 74*257e70f1SIgor Ostapenko /// configured proc environment, if expected. 75*257e70f1SIgor Ostapenko virtual void init() const = 0; 76*257e70f1SIgor Ostapenko 77*257e70f1SIgor Ostapenko /// Cleanups or removes execution environment. 78*257e70f1SIgor Ostapenko /// 79*257e70f1SIgor Ostapenko /// It's expected to be called inside a fork for execenv cleanup. 80*257e70f1SIgor Ostapenko virtual void cleanup() const = 0; 81*257e70f1SIgor Ostapenko 82*257e70f1SIgor Ostapenko /// Executes a test within the execution environment. 83*257e70f1SIgor Ostapenko /// 84*257e70f1SIgor Ostapenko /// It's expected to be called inside a fork which runs 85*257e70f1SIgor Ostapenko /// scheduler::interface::exec_test() or exec_cleanup(). 86*257e70f1SIgor Ostapenko /// 87*257e70f1SIgor Ostapenko /// \param args The arguments to pass to the binary. 88*257e70f1SIgor Ostapenko virtual void exec(const args_vector& args) const UTILS_NORETURN = 0; 89*257e70f1SIgor Ostapenko }; 90*257e70f1SIgor Ostapenko 91*257e70f1SIgor Ostapenko 92*257e70f1SIgor Ostapenko /// Abstract interface of an execution environment manager. 93*257e70f1SIgor Ostapenko class manager { 94*257e70f1SIgor Ostapenko public: 95*257e70f1SIgor Ostapenko /// Destructor. ~manager()96*257e70f1SIgor Ostapenko virtual ~manager() {} 97*257e70f1SIgor Ostapenko 98*257e70f1SIgor Ostapenko /// Returns name of an execution environment. 99*257e70f1SIgor Ostapenko virtual const std::string& name() const = 0; 100*257e70f1SIgor Ostapenko 101*257e70f1SIgor Ostapenko /// Returns whether this execution environment is actually supported. 102*257e70f1SIgor Ostapenko /// 103*257e70f1SIgor Ostapenko /// It can be compile time and/or runtime check. 104*257e70f1SIgor Ostapenko virtual bool is_supported() const = 0; 105*257e70f1SIgor Ostapenko 106*257e70f1SIgor Ostapenko /// Returns execution environment for a test. 107*257e70f1SIgor Ostapenko /// 108*257e70f1SIgor Ostapenko /// It checks if the given test is designed for this execution environment. 109*257e70f1SIgor Ostapenko /// 110*257e70f1SIgor Ostapenko /// \param program The test program. 111*257e70f1SIgor Ostapenko /// \param test_case_name Name of the test case. 112*257e70f1SIgor Ostapenko /// 113*257e70f1SIgor Ostapenko /// \return An execenv object if the test conforms, or none. 114*257e70f1SIgor Ostapenko virtual std::unique_ptr< interface > probe( 115*257e70f1SIgor Ostapenko const model::test_program& test_program, 116*257e70f1SIgor Ostapenko const std::string& test_case_name) const = 0; 117*257e70f1SIgor Ostapenko 118*257e70f1SIgor Ostapenko // TODO: execenv related extra metadata could be provided by a manager 119*257e70f1SIgor Ostapenko // not to know how exactly and where it should be added to the kyua 120*257e70f1SIgor Ostapenko }; 121*257e70f1SIgor Ostapenko 122*257e70f1SIgor Ostapenko 123*257e70f1SIgor Ostapenko /// Registers an execution environment. 124*257e70f1SIgor Ostapenko /// 125*257e70f1SIgor Ostapenko /// \param manager Execution environment manager. 126*257e70f1SIgor Ostapenko void register_execenv(const std::shared_ptr< manager > manager); 127*257e70f1SIgor Ostapenko 128*257e70f1SIgor Ostapenko 129*257e70f1SIgor Ostapenko /// Returns list of registered execenv managers, except default host one. 130*257e70f1SIgor Ostapenko /// 131*257e70f1SIgor Ostapenko /// \return A vector of pointers to execenv managers. 132*257e70f1SIgor Ostapenko const std::vector< std::shared_ptr< manager> > execenvs(); 133*257e70f1SIgor Ostapenko 134*257e70f1SIgor Ostapenko 135*257e70f1SIgor Ostapenko /// Returns execution environment for a test case. 136*257e70f1SIgor Ostapenko /// 137*257e70f1SIgor Ostapenko /// \param program The test program. 138*257e70f1SIgor Ostapenko /// \param test_case_name Name of the test case. 139*257e70f1SIgor Ostapenko /// 140*257e70f1SIgor Ostapenko /// \return An execution environment of a test. 141*257e70f1SIgor Ostapenko std::unique_ptr< execenv::interface > get( 142*257e70f1SIgor Ostapenko const model::test_program& test_program, 143*257e70f1SIgor Ostapenko const std::string& test_case_name); 144*257e70f1SIgor Ostapenko 145*257e70f1SIgor Ostapenko 146*257e70f1SIgor Ostapenko } // namespace execenv 147*257e70f1SIgor Ostapenko } // namespace engine 148*257e70f1SIgor Ostapenko 149*257e70f1SIgor Ostapenko #endif // !defined(ENGINE_EXECENV_EXECENV_HPP) 150