diff --git a/slsDetectorSoftware/tests/test-Result.cpp b/slsDetectorSoftware/tests/test-Result.cpp index 88fb762bc..352df0f68 100644 --- a/slsDetectorSoftware/tests/test-Result.cpp +++ b/slsDetectorSoftware/tests/test-Result.cpp @@ -1,18 +1,21 @@ #include "Result.h" +#include "TypeTraits.h" #include "catch.hpp" - -#include #include using sls::Result; -TEST_CASE("Default construction", "[detector][n2]") { +TEST_CASE("Result looks and behaves like a standard container") { + REQUIRE(sls::is_container>::value == true); +} + +TEST_CASE("Default construction is possible and gives an empty result") { Result res; REQUIRE(res.size() == 0); REQUIRE(res.empty() == true); } -TEST_CASE("Initializer list construction", "[n2]") { +TEST_CASE("Result can be constructed from std::initializer_list") { Result res{1, 2, 5}; REQUIRE(res.empty() == false); REQUIRE(res.size() == 3); @@ -21,7 +24,7 @@ TEST_CASE("Initializer list construction", "[n2]") { REQUIRE(res[2] == 5); } -TEST_CASE("Construct with value and number", "[n2]") { +TEST_CASE("Like vector it can be constructed from size and value") { Result res(5, 7); REQUIRE(res.size() == 5); REQUIRE(res[0] == 7); @@ -31,56 +34,103 @@ TEST_CASE("Construct with value and number", "[n2]") { REQUIRE(res[4] == 7); } -TEST_CASE("Squash empty", "[n2]") { - Result res; - REQUIRE(res.squash() == 0.); +TEST_CASE("Result can be iterated using modern syntax"){ + Result res{0,1,2,3,4,5}; + + int i = 0; + for (const auto& r:res) + REQUIRE(r == i++); + } -TEST_CASE("Squash gives either value or default constructed value", "[n2]") { +TEST_CASE("Calling squash on an empty Result produces default value") { + Result res; + REQUIRE(res.squash() == 0.); + + Result res2; + REQUIRE(res2.squash() == 0u); + + Result res3; + REQUIRE(res3.squash() == ""); +} + +TEST_CASE("When equal squash gives the front value") { Result res{3, 3, 3}; REQUIRE(res.squash() == 3); +} - res.push_back(5); +TEST_CASE("When elements are not equal squash gives default value") { + Result res{3, 3, 3, 5}; REQUIRE(res.squash() == 0); +} + +TEST_CASE("String compare with squash") { + Result res{"hej", "hej", "hej"}; + REQUIRE(res.squash() == "hej"); +} + +TEST_CASE("tsquash throws for different elements") { + Result res{1, 2, 3}; + REQUIRE_THROWS(res.tsquash("something is wrong")); +} + +TEST_CASE("tsquash returns front element when equal") { + Result res{"word", "word"}; + REQUIRE(res.tsquash("error") == "word"); +} + +TEST_CASE("When provided squash gives default value if elements differ") { + Result res{5, 5, 5}; + REQUIRE(res.squash(-1) == 5); + + res.push_back(7); // adding a different value REQUIRE(res.squash(-1) == -1); } -TEST_CASE("Updating an element", "[n2]") { - +TEST_CASE("It is possible to update elements by index access") { Result res{1, 2, 3}; - REQUIRE(res[0] == 1); - REQUIRE(res[1] == 2); - REQUIRE(res[2] == 3); - res[0] = 5; REQUIRE(res[0] == 5); REQUIRE(res[1] == 2); REQUIRE(res[2] == 3); } -TEST_CASE("equal", "[n2]"){ +TEST_CASE("Check if elements are equal") { Result res; + REQUIRE(res.equal() == false); // no elements to compare - // There are no elements to compare - REQUIRE(res.equal() == false); - - //all (the one) elements are equal - res.push_back(1.2); + res.push_back(1.2); // one element "all" equal REQUIRE(res.equal() == true); - res.push_back(1.2); + res.push_back(1.2); // two elements REQUIRE(res.equal() == true); - res.push_back(1.3); + res.push_back(1.3); // three elements 1.2, 1.2, 1.3 REQUIRE(res.equal() == false); } -TEST_CASE("throws for tsquash", "[n2]"){ - Result res{1,2,3}; - REQUIRE_THROWS(res.tsquash("something is wrong")); +TEST_CASE("Result can be converted to std::vector") { + Result res{1, 2, 3, 4, 5}; + std::vector vec{1, 2, 3, 4, 5}; + std::vector vec2 = res; + REQUIRE(vec2 == vec); } -TEST_CASE("", "[n2]"){ - Result res{"hej", "hej", "hej"}; - REQUIRE(res.squash() == "hej"); -} \ No newline at end of file +TEST_CASE("Result can be printed using <<") { + Result res{1, 2, 3}; + std::ostringstream os; + os << res; + REQUIRE(os.str() == "[1, 2, 3]"); +} + +TEST_CASE("Convert from Result to Result") { + // This function is used when the detector class + // returns time as integers + using ns = std::chrono::nanoseconds; + Result res{10, 50, 236}; + + Result res2 = res; + REQUIRE(res2[0] == ns(10)); + REQUIRE(res2[1] == ns(50)); + REQUIRE(res2[2] == ns(236)); +} diff --git a/slsSupportLib/CMakeLists.txt b/slsSupportLib/CMakeLists.txt index 21ebdfa71..20380e13c 100755 --- a/slsSupportLib/CMakeLists.txt +++ b/slsSupportLib/CMakeLists.txt @@ -7,7 +7,6 @@ set(SOURCES src/ServerSocket.cpp src/ServerInterface2.cpp src/network_utils.cpp - src/ToString.cpp ) set(HEADERS diff --git a/slsSupportLib/include/ToString.h b/slsSupportLib/include/ToString.h index 8acd31a29..b032151e5 100644 --- a/slsSupportLib/include/ToString.h +++ b/slsSupportLib/include/ToString.h @@ -19,8 +19,8 @@ namespace sls { -std::string ToString(const std::vector &vec, - const char delimiter = ' '); +// std::string ToString(const std::vector &vec, +// const char delimiter = ' '); /** Convert std::chrono::duration with specified output unit */ template diff --git a/slsSupportLib/include/TypeTraits.h b/slsSupportLib/include/TypeTraits.h index 2a5409e78..b7297389c 100644 --- a/slsSupportLib/include/TypeTraits.h +++ b/slsSupportLib/include/TypeTraits.h @@ -4,7 +4,7 @@ namespace sls { /** - * Type trait to check if atemplate parameter is a std::chrono::duration + * Type trait to check if a template parameter is a std::chrono::duration */ template @@ -22,6 +22,19 @@ struct is_duration().zero())>, void>::type> : public std::true_type {}; +/** + * Has str method + */ +template struct has_str : std::false_type {}; + +template struct has_str_helper {}; + +template +struct has_str().str())>, + void>::type> : public std::true_type {}; + /** * Type trait to evaluate if template parameter is * complying with a standard container diff --git a/slsSupportLib/src/ToString.cpp b/slsSupportLib/src/ToString.cpp deleted file mode 100644 index 541ce2829..000000000 --- a/slsSupportLib/src/ToString.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "ToString.h" - -namespace sls { - -std::string ToString(const std::vector &vec, - const char delimiter) { - std::ostringstream os; - if (vec.empty()) - return os.str(); - auto it = vec.cbegin(); - os << *it++; - if (vec.size() > 1) { - while (it != vec.cend()) - os << delimiter << *it++; - } - return os.str(); -} -} // namespace sls \ No newline at end of file diff --git a/slsSupportLib/tests/CMakeLists.txt b/slsSupportLib/tests/CMakeLists.txt index 4490ec18b..2d131a537 100755 --- a/slsSupportLib/tests/CMakeLists.txt +++ b/slsSupportLib/tests/CMakeLists.txt @@ -8,4 +8,5 @@ target_sources(tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/test-Sockets.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-FixedCapacityContainer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-ToString.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test-TypeTraits.cpp ) \ No newline at end of file diff --git a/slsSupportLib/tests/test-ToString.cpp b/slsSupportLib/tests/test-ToString.cpp index f080003b0..6ec8c3f4f 100644 --- a/slsSupportLib/tests/test-ToString.cpp +++ b/slsSupportLib/tests/test-ToString.cpp @@ -2,10 +2,16 @@ #include "ToString.h" #include "catch.hpp" #include -using namespace sls; +#include -TEST_CASE("Integer conversions", "[support][now]"){ +// using namespace sls; +using sls::ToString; +using sls::StringTo; +using namespace sls::time; + + +TEST_CASE("Integer conversions", "[support]"){ REQUIRE(ToString(0) == "0"); REQUIRE(ToString(1) == "1"); REQUIRE(ToString(-1) == "-1"); @@ -14,7 +20,8 @@ TEST_CASE("Integer conversions", "[support][now]"){ } -TEST_CASE("floating point conversions", "[support][now]"){ +TEST_CASE("floating point conversions", "[support]"){ + //Should strip trailing zeros REQUIRE(ToString(0.) == "0"); REQUIRE(ToString(1.) == "1"); REQUIRE(ToString(-1.) == "-1"); @@ -28,33 +35,33 @@ TEST_CASE("floating point conversions", "[support][now]"){ } -TEST_CASE("conversion from duration to string", "[support][now]") { - REQUIRE(ToString(time::ns(150)) == "150ns"); - REQUIRE(ToString(time::ms(783)) == "0.783s"); - REQUIRE(ToString(time::ms(783), "ms") == "783ms"); - REQUIRE(ToString(time::us(0)) == "0ns"); // Defaults to the lowest unit - REQUIRE(ToString(time::us(0), "s") == "0s"); - REQUIRE(ToString(time::s(-1)) == "-1s"); - REQUIRE(ToString(time::us(-100)) == "-100us"); +TEST_CASE("conversion from duration to string", "[support]") { + REQUIRE(ToString(ns(150)) == "150ns"); + REQUIRE(ToString(ms(783)) == "0.783s"); + REQUIRE(ToString(ms(783), "ms") == "783ms"); + REQUIRE(ToString(us(0)) == "0ns"); // Defaults to the lowest unit + REQUIRE(ToString(us(0), "s") == "0s"); + REQUIRE(ToString(s(-1)) == "-1s"); + REQUIRE(ToString(us(-100)) == "-100us"); } -TEST_CASE("string to std::chrono::duration", "[support][now]") { - REQUIRE(StringTo("150", "ns") == time::ns(150)); - REQUIRE(StringTo("150ns") == time::ns(150)); - REQUIRE(StringTo("150s") == time::s(150)); - REQUIRE(StringTo("3 s") == time::s(3)); +TEST_CASE("string to std::chrono::duration", "[support]") { + REQUIRE(StringTo("150", "ns") == ns(150)); + REQUIRE(StringTo("150ns") == ns(150)); + REQUIRE(StringTo("150s") == s(150)); + REQUIRE(StringTo("3 s") == s(3)); - REQUIRE_THROWS(StringTo("5xs")); - REQUIRE_THROWS(StringTo("asvn")); + REQUIRE_THROWS(StringTo("5xs")); + REQUIRE_THROWS(StringTo("asvn")); } -TEST_CASE("Convert vector of time", "[support][now]"){ - std::vector vec{time::ns(150), time::us(10), time::ns(600)}; +TEST_CASE("Convert vector of time", "[support]"){ + std::vector vec{ns(150), us(10), ns(600)}; REQUIRE(ToString(vec) == "[150ns, 10us, 600ns]"); REQUIRE(ToString(vec, "ns") == "[150ns, 10000ns, 600ns]"); } -TEST_CASE("Vector of int", "[support][now]"){ +TEST_CASE("Vector of int", "[support]"){ std::vector vec; REQUIRE(ToString(vec) == "[]"); @@ -69,7 +76,7 @@ TEST_CASE("Vector of int", "[support][now]"){ } -TEST_CASE("Vector of double", "[support][now]"){ +TEST_CASE("Vector of double", "[support]"){ std::vector vec; REQUIRE(ToString(vec) == "[]"); @@ -81,5 +88,10 @@ TEST_CASE("Vector of double", "[support][now]"){ vec.push_back(-5669.325005); REQUIRE(ToString(vec) == "[1.3, 5669.325, -5669.325005]"); +} + +TEST_CASE("Array"){ + std::array arr{1,2,3}; + REQUIRE(ToString(arr) == "[1, 2, 3]"); } \ No newline at end of file diff --git a/slsSupportLib/tests/test-TypeTraits.cpp b/slsSupportLib/tests/test-TypeTraits.cpp new file mode 100644 index 000000000..042eee3ac --- /dev/null +++ b/slsSupportLib/tests/test-TypeTraits.cpp @@ -0,0 +1,41 @@ +#include "TypeTraits.h" +#include "catch.hpp" +#include +#include +#include +#include + +//Dummy classes only used here for testing +class DummyWithStr { + public: + std::string str(); +}; + +class DummyNoStr { + public: + std::string somethingelse(); +}; + +TEST_CASE("sls::is_container") { + + CHECK(sls::is_container>::value == true); + CHECK(sls::is_container>::value == true); +} + +TEST_CASE("Check for str() method") { + REQUIRE(sls::has_str::value == true); + REQUIRE(sls::has_str::value == false); +} + +TEST_CASE("Check for str() on ostream") { + REQUIRE(sls::has_str::value == true); +} + +TEST_CASE("sls::is_duration"){ + REQUIRE(sls::is_duration::value == true); + REQUIRE(sls::is_duration::value == true); + REQUIRE(sls::is_duration::value == true); + + REQUIRE(sls::is_duration::value == false); + REQUIRE(sls::is_duration>::value == false); +} \ No newline at end of file