diff --git a/CMakeLists.txt b/CMakeLists.txt index e8d5345..1f44102 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,3 +69,10 @@ set(COMMON_LIBRARIES add_executable(password-analyzer ${COMMON_SOURCES} analyzer.cpp) target_link_libraries(password-analyzer PRIVATE ${COMMON_LIBRARIES}) + +add_executable(tests ${COMMON_SOURCES} tests.cpp) +target_link_libraries(tests PRIVATE Catch2::Catch2WithMain ${COMMON_LIBRARIES}) + +include(CTest) +include(Catch) +catch_discover_tests(tests) diff --git a/analyzer.cpp b/analyzer.cpp new file mode 100644 index 0000000..13b7c0a --- /dev/null +++ b/analyzer.cpp @@ -0,0 +1,14 @@ +#include "defs.hpp" + +int main() { + stat_length(DataSource::YAHOO); + stat_length(DataSource::CSDN); + + stat_struct(DataSource::YAHOO); + stat_struct(DataSource::CSDN); + + stat_keystroke(DataSource::YAHOO); + stat_keystroke(DataSource::CSDN); + + return 0; +} diff --git a/tests.cpp b/tests.cpp new file mode 100644 index 0000000..319fcbd --- /dev/null +++ b/tests.cpp @@ -0,0 +1,95 @@ +#include +#include +#include "defs.hpp" + +auto count_passwords(const DataSource &source) -> size_t { + auto cnt = 0; + for (auto const &_ : passwords(source)) cnt++; + return cnt; +} + +std::string get_struct(const std::string &password); +auto string_to_cord(const std::string &password) -> std::vector; +auto cord_to_string(const std::vector &cords) -> std::string; +auto is_neighbour(const Cord &a, const Cord &b) -> bool; + +TEST_CASE("number of CSDN is correct", "[passwords]") { REQUIRE(count_passwords(DataSource::CSDN) == 6428632); } + +TEST_CASE("number of YAHOO is correct", "[passwords]") { REQUIRE(count_passwords(DataSource::YAHOO) == 442836); } + +TEST_CASE("passwords(10) of CSDN is correct", "[passwords]") { + const std::string ans[] = {"12344321", "670203313747", "730413", "2535263", "KIC43dk6!", + "s12345", "apple", "lj7202", "12345", "hebeibdh"}; + + size_t i = 0; + for (auto const &p : passwords(DataSource::CSDN) | std::views::take(10)) { + REQUIRE(ans[i++] == p); + } +} + +TEST_CASE("passwords(10) of YAHOO is correct", "[passwords]") { + const std::string ans[] = {"@fl!pm0de@", "pass", "steveol", "chotzi", "lb2512", + "scotch", "passwerd", "flipmode", "flipmode", "alden2"}; + + size_t i = 0; + for (auto const &p : passwords(DataSource::YAHOO) | std::views::take(10)) { + REQUIRE(ans[i++] == p); + } +} + +TEST_CASE("get_struct works", "[stat_struct]") { + const std::string test_cases[][2] = {{"A", "L1"}, {"1", "D1"}, {"!", "S1"}, + {"AABBCC", "L6"}, {"A1@", "L1D1S1"}, {"AbCd@", "L4S1"}}; + + for (auto const &[password, expected] : test_cases) { + auto ans = get_struct(password); + REQUIRE(ans == expected); + } +} + +TEST_CASE("string_to_cord works", "[stat_keystroke]") { + const std::pair> test_cases[] = { + {"asdf", {{2, 1}, {2, 2}, {2, 3}, {2, 4}}}, + {"AwDr%", {{2, 1}, {1, 2}, {2, 3}, {1, 4}, {0, 5}}}, + {"p_[=}\\", {{1, 10}, {0, 11}, {1, 11}, {0, 12}, {1, 12}, {1, 13}}}, + {",L>;/\"", {{3, 8}, {2, 9}, {3, 9}, {2, 10}, {3, 10}, {2, 11}}}, + }; + + for (auto const &[password, expected] : test_cases) { + auto ans = string_to_cord(password); + REQUIRE(ans == expected); + } +} + +TEST_CASE("cord_to_string works", "[stat_keystroke]") { + const std::pair> test_cases[] = { + {"asdf", {{2, 1}, {2, 2}, {2, 3}, {2, 4}}}, + {"awdr5", {{2, 1}, {1, 2}, {2, 3}, {1, 4}, {0, 5}}}, + {"p-[=]\\", {{1, 10}, {0, 11}, {1, 11}, {0, 12}, {1, 12}, {1, 13}}}, + {",l.;/'", {{3, 8}, {2, 9}, {3, 9}, {2, 10}, {3, 10}, {2, 11}}}, + }; + + for (auto const &[expected, cords] : test_cases) { + auto ans = cord_to_string(cords); + REQUIRE(ans == expected); + } +} + +TEST_CASE("is_neighbour works", "[stat_keystroke]") { + const auto dict = string_to_cord("`1qwad;./"s); + + const std::pair, bool> test_cases[] = { + {{dict[0], dict[1]}, true}, // `1 + {{dict[0], dict[2]}, true}, // `q + {{dict[3], dict[4]}, true}, // wa + {{dict[3], dict[5]}, true}, // wd + {{dict[4], dict[5]}, false}, // ad + {{dict[6], dict[7]}, true}, // ;. + {{dict[6], dict[8]}, true}, // ;/ + }; + + for (auto const &[cords, expected] : test_cases) { + auto ans = is_neighbour(cords.first, cords.second); + REQUIRE(ans == expected); + } +}