1257e70f1SIgor Ostapenko // Copyright 2023 The Kyua Authors. 2257e70f1SIgor Ostapenko // All rights reserved. 3257e70f1SIgor Ostapenko // 4257e70f1SIgor Ostapenko // Redistribution and use in source and binary forms, with or without 5257e70f1SIgor Ostapenko // modification, are permitted provided that the following conditions are 6257e70f1SIgor Ostapenko // met: 7257e70f1SIgor Ostapenko // 8257e70f1SIgor Ostapenko // * Redistributions of source code must retain the above copyright 9257e70f1SIgor Ostapenko // notice, this list of conditions and the following disclaimer. 10257e70f1SIgor Ostapenko // * Redistributions in binary form must reproduce the above copyright 11257e70f1SIgor Ostapenko // notice, this list of conditions and the following disclaimer in the 12257e70f1SIgor Ostapenko // documentation and/or other materials provided with the distribution. 13257e70f1SIgor Ostapenko // * Neither the name of Google Inc. nor the names of its contributors 14257e70f1SIgor Ostapenko // may be used to endorse or promote products derived from this software 15257e70f1SIgor Ostapenko // without specific prior written permission. 16257e70f1SIgor Ostapenko // 17257e70f1SIgor Ostapenko // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18257e70f1SIgor Ostapenko // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19257e70f1SIgor Ostapenko // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20257e70f1SIgor Ostapenko // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21257e70f1SIgor Ostapenko // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22257e70f1SIgor Ostapenko // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23257e70f1SIgor Ostapenko // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24257e70f1SIgor Ostapenko // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25257e70f1SIgor Ostapenko // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26257e70f1SIgor Ostapenko // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27257e70f1SIgor Ostapenko // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28257e70f1SIgor Ostapenko 29257e70f1SIgor Ostapenko /// \file engine/execenv/execenv.hpp 30257e70f1SIgor Ostapenko /// Execution environment subsystem interface. 31257e70f1SIgor Ostapenko 32257e70f1SIgor Ostapenko #if !defined(ENGINE_EXECENV_EXECENV_HPP) 33257e70f1SIgor Ostapenko #define ENGINE_EXECENV_EXECENV_HPP 34257e70f1SIgor Ostapenko 35257e70f1SIgor Ostapenko #include "model/test_program.hpp" 36257e70f1SIgor Ostapenko #include "utils/optional.ipp" 37257e70f1SIgor Ostapenko #include "utils/process/operations_fwd.hpp" 38257e70f1SIgor Ostapenko 39257e70f1SIgor Ostapenko using utils::process::args_vector; 40257e70f1SIgor Ostapenko using utils::optional; 41257e70f1SIgor Ostapenko 42257e70f1SIgor Ostapenko namespace engine { 43257e70f1SIgor Ostapenko namespace execenv { 44257e70f1SIgor Ostapenko 45257e70f1SIgor Ostapenko 46257e70f1SIgor Ostapenko extern const char* default_execenv_name; 47257e70f1SIgor Ostapenko 48257e70f1SIgor Ostapenko 49257e70f1SIgor Ostapenko /// Abstract interface of an execution environment. 50257e70f1SIgor Ostapenko class interface { 51257e70f1SIgor Ostapenko protected: 52257e70f1SIgor Ostapenko const model::test_program& _test_program; 53257e70f1SIgor Ostapenko const std::string& _test_case_name; 54257e70f1SIgor Ostapenko 55257e70f1SIgor Ostapenko public: 56257e70f1SIgor Ostapenko /// Constructor. 57257e70f1SIgor Ostapenko /// 58257e70f1SIgor Ostapenko /// \param program The test program. 59257e70f1SIgor Ostapenko /// \param test_case_name Name of the test case. interface(const model::test_program & test_program,const std::string & test_case_name)60257e70f1SIgor Ostapenko interface(const model::test_program& test_program, 61257e70f1SIgor Ostapenko const std::string& test_case_name) : 62257e70f1SIgor Ostapenko _test_program(test_program), 63257e70f1SIgor Ostapenko _test_case_name(test_case_name) 64257e70f1SIgor Ostapenko {} 65257e70f1SIgor Ostapenko 66257e70f1SIgor Ostapenko /// Destructor. ~interface()67257e70f1SIgor Ostapenko virtual ~interface() {} 68257e70f1SIgor Ostapenko 69257e70f1SIgor Ostapenko /// Initializes execution environment. 70257e70f1SIgor Ostapenko /// 71257e70f1SIgor Ostapenko /// It's expected to be called inside a fork which runs 72257e70f1SIgor Ostapenko /// scheduler::interface::exec_test(), so we can fail a test fast if its 73257e70f1SIgor Ostapenko /// execution environment setup fails, and test execution could use the 74257e70f1SIgor Ostapenko /// configured proc environment, if expected. 75257e70f1SIgor Ostapenko virtual void init() const = 0; 76257e70f1SIgor Ostapenko 77257e70f1SIgor Ostapenko /// Cleanups or removes execution environment. 78257e70f1SIgor Ostapenko /// 79257e70f1SIgor Ostapenko /// It's expected to be called inside a fork for execenv cleanup. 80257e70f1SIgor Ostapenko virtual void cleanup() const = 0; 81257e70f1SIgor Ostapenko 82257e70f1SIgor Ostapenko /// Executes a test within the execution environment. 83257e70f1SIgor Ostapenko /// 84257e70f1SIgor Ostapenko /// It's expected to be called inside a fork which runs 85257e70f1SIgor Ostapenko /// scheduler::interface::exec_test() or exec_cleanup(). 86257e70f1SIgor Ostapenko /// 87257e70f1SIgor Ostapenko /// \param args The arguments to pass to the binary. 88257e70f1SIgor Ostapenko virtual void exec(const args_vector& args) const UTILS_NORETURN = 0; 89257e70f1SIgor Ostapenko }; 90257e70f1SIgor Ostapenko 91257e70f1SIgor Ostapenko 92257e70f1SIgor Ostapenko /// Abstract interface of an execution environment manager. 93257e70f1SIgor Ostapenko class manager { 94257e70f1SIgor Ostapenko public: 95257e70f1SIgor Ostapenko /// Destructor. ~manager()96257e70f1SIgor Ostapenko virtual ~manager() {} 97257e70f1SIgor Ostapenko 98257e70f1SIgor Ostapenko /// Returns name of an execution environment. 99257e70f1SIgor Ostapenko virtual const std::string& name() const = 0; 100257e70f1SIgor Ostapenko 101257e70f1SIgor Ostapenko /// Returns whether this execution environment is actually supported. 102257e70f1SIgor Ostapenko /// 103257e70f1SIgor Ostapenko /// It can be compile time and/or runtime check. 104257e70f1SIgor Ostapenko virtual bool is_supported() const = 0; 105257e70f1SIgor Ostapenko 106257e70f1SIgor Ostapenko /// Returns execution environment for a test. 107257e70f1SIgor Ostapenko /// 108257e70f1SIgor Ostapenko /// It checks if the given test is designed for this execution environment. 109257e70f1SIgor Ostapenko /// 110257e70f1SIgor Ostapenko /// \param program The test program. 111257e70f1SIgor Ostapenko /// \param test_case_name Name of the test case. 112257e70f1SIgor Ostapenko /// 113257e70f1SIgor Ostapenko /// \return An execenv object if the test conforms, or none. 114257e70f1SIgor Ostapenko virtual std::unique_ptr< interface > probe( 115257e70f1SIgor Ostapenko const model::test_program& test_program, 116257e70f1SIgor Ostapenko const std::string& test_case_name) const = 0; 117257e70f1SIgor Ostapenko 118257e70f1SIgor Ostapenko // TODO: execenv related extra metadata could be provided by a manager 119257e70f1SIgor Ostapenko // not to know how exactly and where it should be added to the kyua 120257e70f1SIgor Ostapenko }; 121257e70f1SIgor Ostapenko 122257e70f1SIgor Ostapenko 123257e70f1SIgor Ostapenko /// Registers an execution environment. 124257e70f1SIgor Ostapenko /// 125257e70f1SIgor Ostapenko /// \param manager Execution environment manager. 126257e70f1SIgor Ostapenko void register_execenv(const std::shared_ptr< manager > manager); 127257e70f1SIgor Ostapenko 128257e70f1SIgor Ostapenko 129257e70f1SIgor Ostapenko /// Returns list of registered execenv managers, except default host one. 130257e70f1SIgor Ostapenko /// 131257e70f1SIgor Ostapenko /// \return A vector of pointers to execenv managers. 132257e70f1SIgor Ostapenko const std::vector< std::shared_ptr< manager> > execenvs(); 133257e70f1SIgor Ostapenko 134257e70f1SIgor Ostapenko 135257e70f1SIgor Ostapenko /// Returns execution environment for a test case. 136257e70f1SIgor Ostapenko /// 137257e70f1SIgor Ostapenko /// \param program The test program. 138257e70f1SIgor Ostapenko /// \param test_case_name Name of the test case. 139257e70f1SIgor Ostapenko /// 140257e70f1SIgor Ostapenko /// \return An execution environment of a test. 141257e70f1SIgor Ostapenko std::unique_ptr< execenv::interface > get( 142257e70f1SIgor Ostapenko const model::test_program& test_program, 143257e70f1SIgor Ostapenko const std::string& test_case_name); 144257e70f1SIgor Ostapenko 145257e70f1SIgor Ostapenko 146257e70f1SIgor Ostapenko } // namespace execenv 147257e70f1SIgor Ostapenko } // namespace engine 148257e70f1SIgor Ostapenko 149257e70f1SIgor Ostapenko #endif // !defined(ENGINE_EXECENV_EXECENV_HPP) 150