/***********************************************************************//** * @brief Save test report into XML file. * * @param[in] filename Name of XML file. * * Saves the test results in a JUnit compliant format into an XML file. ***************************************************************************/ void GTestSuites::save(const std::string& filename) const { // Declare empty XML document GXml xml; // Write observations into XML file write(xml); // Save XML document xml.save(filename); // Return return; }
/***********************************************************************//** * @brief Returns value for a SAMP Hub response parameter * * @param[in] xml Hub response XML document. * @param[in] name Parameter name. * @return Parameter value. * * Returns value for a SAMP Hub response parameter. If the specified * parameter was not found or if the response structure is not compliant, * an empty string is returned. ***************************************************************************/ std::string GVOClient::get_response_value(const GXml& xml, const std::string& name) const { // Declare value std::string value = ""; // Search for value of specified member const GXmlNode* node = xml.element("methodResponse > params > param > value > struct"); if (node != NULL) { int num = node->elements("member"); for (int i = 0; i < num; ++i) { const GXmlNode* member = node->element("member", i); std::string one_name; std::string one_value; get_name_value_pair(member, one_name, one_value); if (one_name == name) { value = one_value; break; } } } // Return value return value; }
/***********************************************************************//** * @brief Write observations into XML document * * @param[in] xml XML document. * * Write observations into the first observation library that is found in the * XML document. In case that no observation library exists, one is added to * the document. ***************************************************************************/ void GObservations::write(GXml& xml) const { // If there is no observation library then append one if (xml.elements("observation_list") == 0) { xml.append(new GXmlElement("observation_list title=\"observation list\"")); } // Get pointer on observation library GXmlElement* lib = xml.element("observation_list", 0); // Write all observations into library for (int i = 0; i < size(); ++i) { // Initialise pointer on observation GXmlElement* obs = NULL; // Search corresponding observation int n = xml.elements("observation"); for (int k = 0; k < n; ++k) { GXmlElement* element = static_cast<GXmlElement*>(xml.element("observation", k)); if (element->attribute("name") == m_obs[i]->name() && element->attribute("id") == m_obs[i]->id() && element->attribute("instrument") == m_obs[i]->instrument()) { obs = element; break; } } // If no observation with corresponding name, ID and instrument was found // then append one now if (obs == NULL) { obs = new GXmlElement("observation"); obs->attribute("name", m_obs[i]->name()); obs->attribute("id", m_obs[i]->id()); obs->attribute("instrument", m_obs[i]->instrument()); lib->append(obs); } // Write now observation m_obs[i]->write(*obs); } // endfor: looped over all observaitons // Return return; }
/***********************************************************************//** * @brief Read observations from XML document * * @param[in] xml XML document. * * @exception GException::invalid_instrument * Invalid instrument encountered in XML file. * * Reads observations from the first observation list that is found in the * XML document. The decoding of the instrument specific observation * definition is done within the observation's GCTAOnOffObservation::read() method. * The following file structure is expected: * * <observation_list title="observation library"> * <observation name="..." id="..." instrument="..."> * ... * </observation> * <observation name="..." id="..." instrument="..."> * ... * </observation> * ... * </observation_list> * * The @p name and @p id attributes allow for a unique identification of an * observation within the observation container. The @p instrument * attributes specifies the instrument to which the observation applies. * At the moment there is only CTA but more instruments may be implemented * later and require the need for a registry (see GObservations.cpp). * * The structure within the @p observation tag is defined by the instrument * specific GCTAOnOffObservation class. * ***************************************************************************/ void GCTAOnOffObservations::read(const GXml& xml) { // Get pointer on observation library const GXmlElement* lib = xml.element("observation_list", 0); // Loop over all observations int n = lib->elements("observation"); for (int i = 0; i < n; ++i) { // Get pointer on observation const GXmlElement* obs = lib->element("observation", i); // Get attributes std::string name = obs->attribute("name"); std::string id = obs->attribute("id"); std::string instrument = obs->attribute("instrument"); // Allocate observation // (only CTA at the moment, implement registry if more) GCTAOnOffObservation* ptr = new GCTAOnOffObservation; // If observation is valid then read its definition from XML file if (ptr != NULL) { // Read definition ptr->read(*obs); // Set attributes ptr->name(name); ptr->id(id); } // endif: observation was valid // ... otherwise throw an exception else { std::string msg = "Problem allocating GCTAOnOffObservation object."; throw GException::invalid_instrument(G_READ, msg); } // Append observation to container append(*ptr); // Free observation (the append method made a deep copy) delete ptr; } // endfor: looped over all observations // Return return; }
/***********************************************************************//** * @brief Checks if response is valid * * @return True if response is valid, false otherwise. ***************************************************************************/ bool GVOClient::response_is_valid(const GXml& xml) const { // Initialise validity flag bool valid = true; // Check for data const GXmlNode* node = xml.element("methodResponse > params > param > value"); if (node == NULL) { valid = false; } // Return validity return valid; }
/***********************************************************************//** * @brief Read observations from XML document * * @param[in] xml XML document. * * @exception GException::invalid_instrument * Invalid instrument encountered. * * Reads observations from the first observation list that is found in the * XML document. The decoding of the instrument specific observation * definition is done within the observation's read() method. * * @todo Observation names and IDs are not verified so far for uniqueness. * This would be required to achieve an unambiguous update of parameters * in an already existing XML file when using the write method. ***************************************************************************/ void GObservations::read(const GXml& xml) { // Get pointer on observation library GXmlElement* lib = xml.element("observation_list", 0); // Loop over all observations int n = lib->elements("observation"); for (int i = 0; i < n; ++i) { // Get pointer on observation GXmlElement* obs = static_cast<GXmlElement*>(lib->element("observation", i)); // Get attributes std::string name = obs->attribute("name"); std::string id = obs->attribute("id"); std::string instrument = obs->attribute("instrument"); // Get model GObservationRegistry registry; GObservation* ptr = registry.alloc(instrument); // If observation is valid then read its definition from XML file if (ptr != NULL) { // Read definition ptr->read(*obs); // Set attributes ptr->name(name); ptr->id(id); } // endif: observation was valid // ... otherwise throw an exception else { throw GException::invalid_instrument(G_READ, instrument); } // Append observation to container append(*ptr); // Free model (appending clones the observation) delete ptr; } // endfor: looped over all observations // Return return; }
/***********************************************************************//** * @brief Return response error message * * @return Response error message (blank if no error occured). ***************************************************************************/ std::string GVOClient::response_error_message(const GXml& xml) const { // Initialise error message std::string error_message; // Extract error message const GXmlNode* node = xml.element("methodResponse > fault > value > struct"); if (node != NULL) { const GXmlNode* msg = node->element("member[1] > value"); if (msg != NULL) { error_message = static_cast<const GXmlText*>((*msg)[0])->text(); } } // Return error message return error_message; }
/***********************************************************************//** * @brief Return response error code * * @return Response error core (0 if no error occured). ***************************************************************************/ int GVOClient::response_error_code(const GXml& xml) const { // Initialise error code int error_code = 0; // Extract error code const GXmlNode* node = xml.element("methodResponse > fault > value > struct"); if (node != NULL) { const GXmlNode* code = node->element("member[0] > value > int"); if (code != NULL) { error_code = gammalib::toint(static_cast<const GXmlText*>((*code)[0])->text()); } } // Return error code return error_code; }
/***********************************************************************//** * @brief Test XML loading/saving **************************************************************************/ void TestGXml::test_GXml_load(void) { // Test loading test_try("Test loading"); try { GXml xml; xml.load(m_xml_file); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test saving test_try("Test saving"); try { GXml xml; xml.load(m_xml_file); xml.save("test.xml"); xml.load("test.xml"); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test loading of saved XML document test_try("Test loading of saved XML document"); try { GXml xml; xml.load("test.xml"); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Return return; }
/***********************************************************************//** * @brief Write Test Suites into XML document * * @param[in] xml XML document. * * Write test suites into the XML document. ***************************************************************************/ void GTestSuites::write(GXml& xml) const { // Create XML element for Test Suites GXmlElement *element_testsuites = new GXmlElement("testsuites"); // Set attributes element_testsuites->attribute("name", "GammaLib"); /* element_testsuites->attribute("test",str(tests())); element_testsuites->attribute("errors",str(errors())); element_testsuites->attribute("failures",str(failures())); element_testsuites->attribute("time","0"); // not used element_testsuites->attribute("timestamp",str(timestamp())); */ // Loop over all test suites in the container for (int i = 0; i < m_testsuites.size(); ++i) { // Get a pointer on the current test suite GTestSuite *testsuite = m_testsuites[i]; // Create XML element for this test suite GXmlElement *element_testsuite = new GXmlElement("testsuite"); // Set attributes element_testsuite->attribute("disabled",""); // not used element_testsuite->attribute("errors",str(testsuite->errors())); element_testsuite->attribute("failures",str(testsuite->failures())); element_testsuite->attribute("hostname",""); // not used element_testsuite->attribute("id",str(i)); element_testsuite->attribute("name",testsuite->name()); element_testsuite->attribute("package",""); // not used element_testsuite->attribute("skipped",""); // not used element_testsuite->attribute("tests",str(testsuite->size())); element_testsuite->attribute("time",str(testsuite->duration())); element_testsuite->attribute("timestamp",str(testsuite->timestamp())); // Loop over all test cases in the test suite for (int j = 0; j < testsuite->size(); ++j) { // Reference to the current test case GTestCase& testcase = (*testsuite)[j]; // Create XML element for this test case GXmlElement *element_testcase = new GXmlElement("testcase"); // Set attributes element_testcase->attribute("assertions",""); // not used element_testcase->attribute("classname",name()); element_testcase->attribute("name",testcase.name()); element_testcase->attribute("status",""); // not used element_testcase->attribute("time",str(testcase.duration())); // If a failure or error occured then append the message to the // XML element. if (!testcase.passed()) { // Create XML element for the test case problem GXmlElement* element_testcase_problem = new GXmlElement(); // Set attributes element_testcase_problem->attribute("message",testcase.message()); element_testcase_problem->attribute("type",testcase.type()); // Set tag name dependent on the type of problem if (testcase.kind() == GTestCase::ERROR_TEST) { element_testcase_problem->name("error"); } else { element_testcase_problem->name("failure"); } // Append problem to test case element element_testcase->append(element_testcase_problem); } // endif: failure or error occured // Append test case to testsuite element. element_testsuite->append(element_testcase); } // endfor: looped over all test cases // Append test suite to test suites element element_testsuites->append(element_testsuite); } // endfor: looped over all test suites // Append test suites to XML document xml.append(element_testsuites); // Return return; }
/***********************************************************************//** * @brief Test XML element access **************************************************************************/ void TestGXml::test_GXml_access(void) { // Test root document access GXml xml; xml.load(m_xml_file); test_value(xml.size(), 3, "Check number of child elements"); // Test node access for (int i = 0; i < xml.size(); ++i) { GXmlNode* ptr = xml[i]; test_assert(ptr != 0, "Check XML node access"); } test_value(xml.elements(), 1, "Check number of child elements"); // Test node access for (int i = 0; i < xml.elements(); ++i) { GXmlNode* ptr = xml.element(i); test_assert(ptr != 0, "Check XML element access"); } test_value(xml.elements("source_library"), 1, "Check number of child elements"); // Test element access for (int i = 0; i < xml.elements("source_library"); ++i) { GXmlElement* ptr = xml.element("source_library", i); test_value(ptr->name(), "source_library", "Check element name"); } // Test hierarchy access GXmlElement* ptr = NULL; ptr = xml.element("source_library"); test_value(ptr->name(), "source_library", "Check hierarchy level 1"); ptr = xml.element("source_library > source"); test_value(ptr->name(), "source", "Check hierarchy level 2"); ptr = xml.element("source_library > source > spectrum"); test_value(ptr->name(), "spectrum", "Check hierarchy level 3"); ptr = xml.element("source_library > source > spectrum > parameter[2]"); test_value(ptr->name(), "parameter", "Check hierarchy level 4"); test_value(ptr->attribute("name"), "PivotEnergy", "Check for attribute"); // Return return; }
/***********************************************************************//** * @brief Test XML constructors **************************************************************************/ void TestGXml::test_GXml_construct(void) { // Test void constructor test_try("Test void constructor"); try { GXml xml; test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test load constructor test_try("Test load constructor"); try { GXml xml(m_xml_file); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test copy constructor test_try("Test copy constructor"); try { GXml xml1(m_xml_file); GXml xml2 = xml1; test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Test XML file creation test_try("Test XML file creation"); try { GXml xml; xml.append(GXmlComment("This is a comment.")); xml.append(GXmlElement("source_library")); GXmlElement* lib = xml.element("source_library", 0); lib->append(GXmlElement("source name=\"LMC\" type=\"DiffuseSource\"")); GXmlNode* src = lib->element("source", 0); src->append(GXmlElement("spectrum type=\"PLSuperExpCutoff\"")); GXmlNode* spec = src->element("spectrum", 0); spec->append(GXmlElement("parameter free=\"1\" max=\"1000\" min=\"1e-07\"" " name=\"Prefactor\" scale=\"1e-07\"" " value=\"0.02754520844\"")); spec->append(GXmlElement("parameter free=\"1\" max=\"5\" min=\"-5\"" " name=\"Index1\" scale=\"1\" value=\"-2.0458781\"")); GXmlElement* par = spec->element("parameter", 0); par->attribute("value", "1.01"); par->attribute("error", "3.145"); par = spec->element("parameter", 1); par->attribute("value", "-2.100"); par->attribute("error", "9.876"); src->append(GXmlElement("spatialModel file=\"LMC.fits\" type=\"SpatialMap\"")); GXmlNode* spat = src->element("spatialModel", 0); spat->append(GXmlElement("parameter free=\"0\" max=\"1000\" min=\"0.001\"" " name=\"Prefactor\" scale=\"1\" value=\"1\"")); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Return return; }