From 3ddbb44524c39b04a2f1462f648517342b0ed27f Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 14 Sep 2016 17:49:17 +0200 Subject: [PATCH] Add documentation/specification for ConfigurationManager Add documentation testing to ConfigurationManager --- .../openspace/documentation/documentation.h | 9 +- include/openspace/documentation/documented.h | 45 +++ src/CMakeLists.txt | 2 + src/documentation/documentation.cpp | 4 + src/engine/configurationmanager.cpp | 15 +- src/engine/configurationmanager_doc.inl | 279 ++++++++++++++++++ 6 files changed, 352 insertions(+), 2 deletions(-) create mode 100644 include/openspace/documentation/documented.h create mode 100644 src/engine/configurationmanager_doc.inl diff --git a/include/openspace/documentation/documentation.h b/include/openspace/documentation/documentation.h index de85ca0c0d..87785a13c8 100644 --- a/include/openspace/documentation/documentation.h +++ b/include/openspace/documentation/documentation.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -39,12 +40,18 @@ namespace openspace { namespace documentation { +using Optional = ghoul::Boolean; + struct TestResult { bool success; std::vector offenders; }; -using Optional = ghoul::Boolean; +struct SpecificationError : public ghoul::RuntimeError { + SpecificationError(TestResult result, std::string component); + + TestResult result; +}; struct Verifier { virtual TestResult operator()(const ghoul::Dictionary& dict, diff --git a/include/openspace/documentation/documented.h b/include/openspace/documentation/documented.h new file mode 100644 index 0000000000..8082830bf1 --- /dev/null +++ b/include/openspace/documentation/documented.h @@ -0,0 +1,45 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __DOCUMENTED_H__ +#define __DOCUMENTED_H__ + +#include + +namespace openspace { +namespace documentation { + +template +struct Documented { + static Documentation Documentation() { + static_assert(false, "Missing template specialization for type" + typeid(T)); + } +}; + +} // namespace documentation +} // namespace openspace + + + +#endif // __DOCUMENTED_H__ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 244b299a35..ddcabb3938 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,6 +27,7 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/documentation/documentation.cpp ${OPENSPACE_BASE_DIR}/src/documentation/documentationengine.cpp ${OPENSPACE_BASE_DIR}/src/engine/configurationmanager.cpp + ${OPENSPACE_BASE_DIR}/src/engine/configurationmanager_doc.inl ${OPENSPACE_BASE_DIR}/src/engine/downloadmanager.cpp ${OPENSPACE_BASE_DIR}/src/engine/logfactory.cpp ${OPENSPACE_BASE_DIR}/src/engine/moduleengine.cpp @@ -107,6 +108,7 @@ set(OPENSPACE_SOURCE set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/openspace.h + ${OPENSPACE_BASE_DIR}/include/openspace/documentation/documented.h ${OPENSPACE_BASE_DIR}/include/openspace/documentation/documentation.h ${OPENSPACE_BASE_DIR}/include/openspace/documentation/documentation.inl ${OPENSPACE_BASE_DIR}/include/openspace/documentation/documentationengine.h diff --git a/src/documentation/documentation.cpp b/src/documentation/documentation.cpp index 9cc663a924..1ab399c01d 100644 --- a/src/documentation/documentation.cpp +++ b/src/documentation/documentation.cpp @@ -76,6 +76,10 @@ template struct AnnotationVerifier; template struct AnnotationVerifier; template struct AnnotationVerifier; +SpecificationError::SpecificationError(TestResult result, std::string component) + : ghoul::RuntimeError("Error in specification", std::move(component)) + , result(std::move(result)) +{} TestResult Verifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const diff --git a/src/engine/configurationmanager.cpp b/src/engine/configurationmanager.cpp index e72939c75d..dbc275ea28 100644 --- a/src/engine/configurationmanager.cpp +++ b/src/engine/configurationmanager.cpp @@ -32,6 +32,8 @@ using std::string; +#include "configurationmanager_doc.inl" + namespace { const string _configurationFile = "openspace.cfg"; const string _keyBasePath = "BASE_PATH"; @@ -94,8 +96,9 @@ string ConfigurationManager::findConfiguration(const string& filename) { void ConfigurationManager::loadFromFile(const string& filename) { using ghoul::filesystem::FileSystem; - if (!FileSys.fileExists(filename)) + if (!FileSys.fileExists(filename)) { throw ghoul::FileNotFoundError(filename, "ConfigurationManager"); + } // ${BASE_PATH} string basePathToken = FileSystem::TokenOpeningBraces + _keyBasePath @@ -109,6 +112,16 @@ void ConfigurationManager::loadFromFile(const string& filename) { // Loading the configuration file into ourselves ghoul::lua::loadDictionaryFromFile(filename, *this); + // Perform testing against the documentation/specification + using namespace openspace::documentation; + TestResult result = testSpecification( + Documented::Documentation(), + *this + ); + if (!result.success) { + throw SpecificationError(result, "ConfigurationManager"); + } + // Register all the paths ghoul::Dictionary dictionary = value(KeyPaths); diff --git a/src/engine/configurationmanager_doc.inl b/src/engine/configurationmanager_doc.inl new file mode 100644 index 0000000000..adee85ebac --- /dev/null +++ b/src/engine/configurationmanager_doc.inl @@ -0,0 +1,279 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +namespace openspace { +namespace documentation { + +template <> +struct Documented { + static Documentation Documentation() { + return { + { + "SGCTConfig", + new StringAnnotationVerifier("A valid SGCT configuration file"), + "The SGCT configuration file that determines the window and view frustum " + "settings that are being used when OpenSpace is started." + }, + { + "Scene", + new StringAnnotationVerifier( + "A valid scene file as described in the Scene documentation"), + "The scene description that is used to populate the application after " + "startup. The scene determines which objects are loaded, the startup " + "time and other scene-specific settings. More information is provided in " + "the Scene documentation." + }, + { + "Paths", + new TableVerifier({ + { "*", new StringVerifier } + }), + "A list of paths that are automatically registered with the file system. " + "If a key X is used in the table, it is then useable by referencing ${X} " + "in all other configuration files or scripts.", + Optional::Yes + }, + { + "Fonts", + new TableVerifier({ + { "*", new StringVerifier, "Font paths loadable by FreeType" } + }), + "A list of all fonts that will automatically be loaded on startup. Each " + "key-value pair contained in the table will become the name and the file " + "for a font.", + Optional::Yes + }, + { + "Logging", + new TableVerifier({ + { + "LogLevel", + new StringInListVerifier( + // List from logmanager.cpp::levelFromString + {"Debug", "Info", "Warning", "Error", "Fatal", "None" } + ), + "The severity of log messages that will be displayed. Only " + "messages of the selected level or higher will be displayed. All " + "levels below will be silently discarded. The order of " + "severities is: Debug < Info < Warning < Error < Fatal < None.", + Optional::Yes + }, + { + "ImmediateFlush", + new BoolVerifier, + "Determines whether error messages will be displayed immediately " + "or if it is acceptable to have a short delay, but being more " + "performant. If the delay is allowed ('true'), messages might " + "get lost if the application crashes shortly after a message was " + "logged.", + Optional::Yes + }, + { + "Logs", + new TableVerifier({ + { + "*", + new TableVerifier({ + { + "Type", + new StringInListVerifier({ + // List from logfactory.cpp::createLog + "text", "html" + }), + "The type of the new log to be generated." + }, + { + "FileName", + new StringVerifier, + "The filename to which the log will be written." + }, + { + "Append", + new BoolVerifier, + "Determines whether the file will be cleared at " + "startup or if the contents will be appended to " + "previous runs.", + Optional::Yes + } + }), + "Additional log files", + Optional::Yes + } + }), + "Per default, log messages are written to the console, the " + "onscreen text, and (if available) the Visual Studio output " + "window. This table can define other logging methods that will " + "be used additionally.", + Optional::Yes + }, + { + "CapabilitiesVerbosity", + new StringInListVerifier( + // List from OpenspaceEngine::initialize + { "None", "Minimal", "Default", "Full" } + ), + "At startup, a list of system capabilities is created and logged." + "This value determines how verbose this listing should be.", + Optional::Yes + } + }), + "Configurations for the logging of messages that are generated " + "throughout the code and are useful for debugging potential errors or " + "other information.", + Optional::Yes + }, + { + "LuaDocumentationFile", + new TableVerifier({ + { + "Type", + new StringInListVerifier( + // List from ScriptEngine::writeDocumentation + { "text", "html" } + ), + "The type of documentation that will be written." + }, + { + "File", + new StringVerifier, + "The filename that will be created on startup containing the " + "documentation of available Lua functions. Any existing file " + "will be silently overwritten." + } + }), + "Descriptions of whether and where to create a documentation file that " + "describes the available Lua functions that can be executed in scene " + "files or per console.", + Optional::Yes + }, + { + "PropertyDocumentationFile", + new TableVerifier({ + { + "Type", + new StringInListVerifier( + // List taken from Scene::writePropertyDocumentation + { "text", "html" } + ), + "The type of property documentation file that is created." + }, + { + "File", + new StringVerifier, + "The file that will be created on startup containing a list of " + "all properties in the scene. Any existing file will be silently " + "overwritten." + } + }), + "Descriptions of whether and where to create a list of all properties " + "that were created in the current scene.", + Optional::Yes + }, + { + "ScriptLogFile", + new TableVerifier({ + { + "Type", + new StringInListVerifier( + // List taken from ScriptEngine::writeLog + { "text" } + ), + "The type of logfile that will be created." + }, + { + "File", + new StringVerifier, + "The file that will be created on startup containing the log of " + "all Lua scripts that are executed. Any existing file (including " + "the results from previous runs) will be silently overwritten." + } + }), + "Contains a log of all Lua scripts that were executed in the last " + "session.", + Optional::Yes + }, + { + "KeyboardShortcuts", + new TableVerifier({ + { + "Type", + new StringInListVerifier( + // List from InteractionHandler::writeKeyboardDocumentation + { "text", "html" } + ), + "The type of keyboard binding documentation that should be " + "written." + }, + { + "File", + new StringVerifier, + "The file that will be created on startup containing the list of " + "all keyboard bindings with their respective Lua scripts." + } + }), + "Contains the collection of all keyboard shortcuts that were collected " + "during startup. For each key, it mentions which scripts will be " + "executed in the current session.", + Optional::Yes + }, + { + "ShutdownCountdown", + new DoubleGreaterEqualVerifier(0.0), + "The countdown that the application will wait between pressing ESC and " + "actually shutting down. If ESC is pressed again in this time, the " + "shutdown is aborted.", + Optional::Yes + }, + { + "DownloadRequestURL", + new OrVerifier( + new StringVerifier, + new TableVerifier({ + { "*", new StringVerifier } + }) + ), + "The URL from which files will be downloaded by the Launcher. This can " + "either be a single URL or a list of possible URLs from which the " + "Launcher can then choose.", + Optional::Yes + }, + { + "RenderingMethod", + new StringInListVerifier( + // List from RenderEngine::setRendererFromString + { "Framebuffer", "ABuffer" } + ), + "The renderer that is use after startup. The renderer 'ABuffer' requires " + "support for at least OpenGL 4.3", + Optional::Yes + } + }; + } +}; + + +} // namespace documentation +} // namespace openspace \ No newline at end of file