text: #ifndef OTUS_ALGO_DATA_STRUCTURES_TESTER_H
  #define OTUS_ALGO_DATA_STRUCTURES_TESTER_H
  
  #include <chrono>
  #include <filesystem>
  #include <fstream>
  #include <iostream>
  #include <string>
  #include <vector>
  
  namespace tester {
      namespace fs = std::filesystem;
      using test_args_t = std::vector<std::string>;
      using test_result_t = std::string;
      using clock = std::chrono::system_clock;
      using msec_t = std::chrono::duration<double, std::milli>;
  
      std::string &ltrim(std::string &str, const std::string &chars = "\t\n\v\f\r ") {
          str.erase(0, str.find_first_not_of(chars));
          return str;
      }
  
      std::string &rtrim(std::string &str, const std::string &chars = "\t\n\v\f\r ") {
          str.erase(str.find_last_not_of(chars) + 1);
          return str;
      }
  
      std::string &trim(std::string &str, const std::string &chars = "\t\n\v\f\r ") {
          return ltrim(rtrim(str, chars), chars);
      }
  
      template<typename T>
      void run_tests(const T &test, const std::string &test_dir) {
          auto test_index = 0;
          auto test_dir_(fs::absolute(test_dir));
          std::string in_path, out_path;
  
          auto next_in_path = [&]() { return test_dir_ / ("test." + std::to_string(test_index) + ".in"); };
          auto next_out_path = [&]() { return test_dir_ / ("test." + std::to_string(test_index) + ".out"); };
  
          while (fs::exists(in_path = next_in_path()) && fs::exists(out_path = next_out_path())) {
              std::string line;
              test_args_t input;
              std::ifstream in_file(in_path), out_file(out_path);
              while (std::getline(in_file, line)) {
                  input.push_back(std::move(trim(line)));
              }
  
              test_result_t expected((std::istreambuf_iterator<char>(out_file)), std::istreambuf_iterator<char>());
              test_result_t actual;
              msec_t duration = msec_t(0);
              try {
                  const auto start_time = clock::now();
                  actual = std::to_string(test(input));
                  duration = clock::now() - start_time;
              } catch (const std::exception &e) {
                  actual = e.what();
              }
  
              std::cout << "Test\t#" << test_index << "\t\t";
              std::cout << (std::to_string(duration.count()) + " ms") << "\t\t";
              std::cout << (actual == trim(expected) ? "OK" : "FAIL") << "\n";
              ++test_index;
          }
      }
  }
  
  #endif //OTUS_ALGO_DATA_STRUCTURES_TESTER_H
  