1 // Copyright 2014 The Kyua Authors. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // * Neither the name of Google Inc. nor the names of its contributors 14 // may be used to endorse or promote products derived from this software 15 // without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 #include "model/test_result.hpp" 30 31 #include "utils/format/macros.hpp" 32 #include "utils/sanity.hpp" 33 #include "utils/text/operations.ipp" 34 35 namespace text = utils::text; 36 37 38 const std::map<enum model::test_result_type, 39 const struct model::test_result_type_desc> 40 model::test_result_types = 41 { 42 { test_result_broken, 43 { .id = test_result_broken, 44 .name = "broken", 45 .is_run = true, 46 .is_good = false, } }, 47 48 { test_result_expected_failure, 49 { .id = test_result_expected_failure, 50 .name = "xfail", 51 .is_run = true, 52 .is_good = true, } }, 53 54 { test_result_failed, 55 { .id = test_result_failed, 56 .name = "failed", 57 .is_run = true, 58 .is_good = false, } }, 59 60 { test_result_passed, 61 { .id = test_result_passed, 62 .name = "passed", 63 .is_run = true, 64 .is_good = true, } }, 65 66 { test_result_skipped, 67 { .id = test_result_skipped, 68 .name = "skipped", 69 .is_run = false, 70 .is_good = true, } }, 71 }; 72 73 74 /// Constructs a base result. 75 /// 76 /// \param type_ The type of the result. 77 /// \param reason_ The reason explaining the result, if any. It is OK for this 78 /// to be empty, which is actually the default. 79 model::test_result::test_result(const test_result_type type_, 80 const std::string& reason_) : 81 _type(type_), 82 _reason(reason_) 83 { 84 } 85 86 87 /// Returns the type of the result. 88 /// 89 /// \return A result type. 90 model::test_result_type 91 model::test_result::type(void) const 92 { 93 return _type; 94 } 95 96 97 /// Returns the reason explaining the result. 98 /// 99 /// \return A textual reason, possibly empty. 100 const std::string& 101 model::test_result::reason(void) const 102 { 103 return _reason; 104 } 105 106 107 /// True if the test case result has a positive connotation. 108 /// 109 /// \return Whether the test case is good or not. 110 bool 111 model::test_result::good(void) const 112 { 113 return test_result_types.at(_type).is_good; 114 } 115 116 117 /// Equality comparator. 118 /// 119 /// \param other The test result to compare to. 120 /// 121 /// \return True if the other object is equal to this one, false otherwise. 122 bool 123 model::test_result::operator==(const test_result& other) const 124 { 125 return _type == other._type && _reason == other._reason; 126 } 127 128 129 /// Inequality comparator. 130 /// 131 /// \param other The test result to compare to. 132 /// 133 /// \return True if the other object is different from this one, false 134 /// otherwise. 135 bool 136 model::test_result::operator!=(const test_result& other) const 137 { 138 return !(*this == other); 139 } 140 141 142 /// Injects the object into a stream. 143 /// 144 /// \param output The stream into which to inject the object. 145 /// \param object The object to format. 146 /// 147 /// \return The output stream. 148 std::ostream& 149 model::operator<<(std::ostream& output, const test_result& object) 150 { 151 std::string result_name; 152 switch (object.type()) { 153 case test_result_broken: result_name = "broken"; break; 154 case test_result_expected_failure: result_name = "expected_failure"; break; 155 case test_result_failed: result_name = "failed"; break; 156 case test_result_passed: result_name = "passed"; break; 157 case test_result_skipped: result_name = "skipped"; break; 158 } 159 const std::string& reason = object.reason(); 160 if (reason.empty()) { 161 output << F("model::test_result{type=%s}") 162 % text::quote(result_name, '\''); 163 } else { 164 output << F("model::test_result{type=%s, reason=%s}") 165 % text::quote(result_name, '\'') % text::quote(reason, '\''); 166 } 167 return output; 168 } 169