foxygit / Torlinkc Log in
commits tags

/tests/test_sort.cpp · 4.74 KB

raw
#include <doctest/doctest.h>

#include "torlinkc/ui/sort.hpp"

using namespace torlinkc;
using namespace torlinkc::ui;

namespace {

TorrentResult r(std::string infoHash, std::int64_t sizeBytes = 0, int seeders = 0, std::string source = "yts",
                 std::optional<std::int64_t> added = std::nullopt) {
  TorrentResult t;
  t.infoHash = infoHash;
  t.name = infoHash;
  t.sizeBytes = sizeBytes;
  t.seeders = seeders;
  t.source = std::move(source);
  t.magnet = "magnet:?xt=urn:btih:" + infoHash;
  t.added = added;
  return t;
}

std::vector<std::string> ids(const std::vector<TorrentResult>& list) {
  std::vector<std::string> out;
  for (const auto& t : list) out.push_back(t.infoHash);
  return out;
}

}  // namespace

TEST_CASE("nextSort cycles through 9 states and back to none") {
  Sort s = std::nullopt;
  std::vector<Sort> seq;
  for (int i = 0; i < 9; ++i) {
    s = nextSort(s);
    seq.push_back(s);
  }
  REQUIRE(seq.size() == 9);
  CHECK(seq[0] == SortState{SortField::Size, SortDir::Asc});
  CHECK(seq[1] == SortState{SortField::Size, SortDir::Desc});
  CHECK(seq[2] == SortState{SortField::Seeders, SortDir::Asc});
  CHECK(seq[3] == SortState{SortField::Seeders, SortDir::Desc});
  CHECK(seq[4] == SortState{SortField::Source, SortDir::Asc});
  CHECK(seq[5] == SortState{SortField::Source, SortDir::Desc});
  CHECK(seq[6] == SortState{SortField::Added, SortDir::Asc});
  CHECK(seq[7] == SortState{SortField::Added, SortDir::Desc});
  CHECK_FALSE(seq[8].has_value());
}

TEST_CASE("sortCycle has exactly 9 states starting with none") {
  CHECK(sortCycle().size() == 9);
  CHECK_FALSE(sortCycle()[0].has_value());
}

TEST_CASE("sortArrow points up for asc and down for desc") {
  CHECK(sortArrow(SortDir::Asc) == "▴");
  CHECK(sortArrow(SortDir::Desc) == "▾");
}

TEST_CASE("sortResults none preserves the original arrival order") {
  std::vector<TorrentResult> list = {r("a", 1, 1), r("b", 9, 9), r("c", 5, 5)};
  CHECK(ids(sortResults(list, std::nullopt)) == std::vector<std::string>{"a", "b", "c"});
}

TEST_CASE("sortResults size asc: smallest first") {
  std::vector<TorrentResult> list = {r("a", 500), r("b", 100), r("c", 900)};
  CHECK(ids(sortResults(list, SortState{SortField::Size, SortDir::Asc})) == std::vector<std::string>{"b", "a", "c"});
}

TEST_CASE("sortResults size desc: largest first") {
  std::vector<TorrentResult> list = {r("a", 500), r("b", 100), r("c", 900)};
  CHECK(ids(sortResults(list, SortState{SortField::Size, SortDir::Desc})) == std::vector<std::string>{"c", "a", "b"});
}

TEST_CASE("sortResults seeders asc: fewest first") {
  std::vector<TorrentResult> list = {r("a", 0, 50), r("b", 0, 5), r("c", 0, 90)};
  CHECK(ids(sortResults(list, SortState{SortField::Seeders, SortDir::Asc})) ==
        std::vector<std::string>{"b", "a", "c"});
}

TEST_CASE("sortResults seeders desc: most first") {
  std::vector<TorrentResult> list = {r("a", 0, 50), r("b", 0, 5), r("c", 0, 90)};
  CHECK(ids(sortResults(list, SortState{SortField::Seeders, SortDir::Desc})) ==
        std::vector<std::string>{"c", "a", "b"});
}

TEST_CASE("sortResults source asc: A->Z by source id") {
  std::vector<TorrentResult> list = {r("a", 0, 0, "yts"), r("b", 0, 0, "eztv"), r("c", 0, 0, "nyaa")};
  CHECK(ids(sortResults(list, SortState{SortField::Source, SortDir::Asc})) ==
        std::vector<std::string>{"b", "c", "a"});
}

TEST_CASE("sortResults source desc: Z->A by source id") {
  std::vector<TorrentResult> list = {r("a", 0, 0, "eztv"), r("b", 0, 0, "yts"), r("c", 0, 0, "nyaa")};
  CHECK(ids(sortResults(list, SortState{SortField::Source, SortDir::Desc})) ==
        std::vector<std::string>{"b", "c", "a"});
}

TEST_CASE("sortResults added asc: oldest first") {
  std::vector<TorrentResult> list = {r("a", 0, 0, "yts", 300), r("b", 0, 0, "yts", 100), r("c", 0, 0, "yts", 200)};
  CHECK(ids(sortResults(list, SortState{SortField::Added, SortDir::Asc})) ==
        std::vector<std::string>{"b", "c", "a"});
}

TEST_CASE("sortResults added desc: newest first") {
  std::vector<TorrentResult> list = {r("a", 0, 0, "yts", 300), r("b", 0, 0, "yts", 100), r("c", 0, 0, "yts", 200)};
  CHECK(ids(sortResults(list, SortState{SortField::Added, SortDir::Desc})) ==
        std::vector<std::string>{"a", "c", "b"});
}

TEST_CASE("sortResults added treats missing timestamps as zero") {
  std::vector<TorrentResult> list = {r("a", 0, 0, "yts", 500), r("b", 0, 0, "yts", std::nullopt),
                                      r("c", 0, 0, "yts", 100)};
  CHECK(ids(sortResults(list, SortState{SortField::Added, SortDir::Asc})) ==
        std::vector<std::string>{"b", "c", "a"});
}

TEST_CASE("sortResults does not mutate the input") {
  std::vector<TorrentResult> list = {r("a", 1), r("b", 2)};
  const auto before = ids(list);
  sortResults(list, SortState{SortField::Size, SortDir::Asc});
  CHECK(ids(list) == before);
}