The Battle for Wesnoth  1.19.0-dev
test_formula_timespan.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2019 - 2024
3  by Iris Morelle <shadowm2006@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #include <boost/test/unit_test.hpp>
17 
18 #include "formula/string_utils.hpp"
19 #include "tstring.hpp"
20 
21 #include <algorithm>
22 
23 BOOST_AUTO_TEST_SUITE( formula_timespan )
24 
25 using std::time_t;
26 
27 namespace {
28 
29 enum TIME_FACTORS
30 {
31  YEAR = 31104000, /* 12 months */
32  MONTH = 2592000, /* 30 days */
33  WEEK = 604800,
34  DAY = 86400,
35  HOUR = 3600,
36  MIN = 60,
37  SEC = 1,
38 };
39 
40 inline std::string minifmt(time_t t, const std::string& singular, const std::string& plural)
41 {
42  return t ? std::to_string(t) + " " + (t > 1 ? plural : singular) : "";
43 }
44 
45 typedef std::tuple<
46  time_t /*sec*/,
47  time_t /*min*/,
48  time_t /*hr*/,
49  time_t /*day*/,
50  time_t /*wk*/,
51  time_t /*mo*/,
52  time_t /*yr*/> time_detailed;
53 
54 inline time_t gen_as_time_t(const time_detailed& params)
55 {
56  auto [sec, min, hr, day, wk, mo, yr] = params;
57 
58  return YEAR*yr + MONTH*mo + WEEK*wk + DAY*day + HOUR*hr + MIN*min + SEC*sec;
59 }
60 
61 inline std::string gen_as_str(const time_detailed& params)
62 {
63  auto [sec, min, hr, day, wk, mo, yr] = params;
64 
65  std::vector<t_string> bits;
66  std::string res;
67 
68  bits.emplace_back(minifmt(yr, "year", "years"));
69  bits.emplace_back(minifmt(mo, "month", "months"));
70  bits.emplace_back(minifmt(wk, "week", "weeks"));
71  bits.emplace_back(minifmt(day, "day", "days"));
72  bits.emplace_back(minifmt(hr, "hour", "hours"));
73  bits.emplace_back(minifmt(min, "minute", "minutes"));
74  bits.emplace_back(minifmt(sec, "second", "seconds"));
75 
76  // Drop zeroes
77  auto p = std::remove_if(bits.begin(), bits.end(), [](const t_string& t) { return t.empty(); });
78  if(p != bits.end()) {
79  bits.erase(p);
80  }
81 
82  return utils::format_conjunct_list("expired", bits);
83 }
84 
85 inline void test_format_timespan(const time_detailed& tcase, const std::string& detailed, const std::string& fuzzy="")
86 {
87  BOOST_CHECK_EQUAL(detailed, utils::format_timespan(gen_as_time_t(tcase), true));
88 
89  if(!fuzzy.empty()) {
90  BOOST_REQUIRE_NE(detailed, fuzzy); // ensure test case params are not borked
91  BOOST_CHECK_EQUAL(fuzzy, utils::format_timespan(gen_as_time_t(tcase)));
92  BOOST_CHECK_NE(utils::format_timespan(gen_as_time_t(tcase)), utils::format_timespan(gen_as_time_t(tcase), true));
93  }
94 }
95 
96 }
97 
98 BOOST_AUTO_TEST_CASE( test_formula_timespan )
99 {
100  test_format_timespan({ 1, 0, 0, 0, 0, 0, 0 }, "1 second");
101 
102  test_format_timespan({ 2, 0, 0, 0, 0, 0, 0 }, "2 seconds");
103 
104  test_format_timespan({ 0, 1, 0, 0, 0, 0, 0 }, "1 minute");
105 
106  test_format_timespan({ 0, 2, 0, 0, 0, 0, 0 }, "2 minutes");
107 
108  test_format_timespan({ 0, 0, 1, 0, 0, 0, 0 }, "1 hour");
109 
110  test_format_timespan({ 0, 0, 2, 0, 0, 0, 0 }, "2 hours");
111 
112  test_format_timespan({ 0, 0, 0, 1, 0, 0, 0 }, "1 day");
113 
114  test_format_timespan({ 0, 0, 0, 2, 0, 0, 0 }, "2 days");
115 
116  test_format_timespan({ 0, 0, 0, 0, 1, 0, 0 }, "1 week");
117 
118  test_format_timespan({ 0, 0, 0, 0, 2, 0, 0 }, "2 weeks");
119 
120  test_format_timespan({ 0, 0, 0, 0, 0, 1, 0 }, "1 month");
121 
122  test_format_timespan({ 0, 0, 0, 0, 0, 2, 0 }, "2 months");
123 
124  test_format_timespan({ 0, 0, 0, 0, 0, 0, 1 }, "1 year");
125 
126  test_format_timespan({ 0, 0, 0, 0, 0, 0, 2 }, "2 years");
127 
128  auto t = time_detailed{ 12, 1, 23, 3, 2, 5, 2 };
129  test_format_timespan(t, gen_as_str(t), "2 years");
130 
131  t = time_detailed{ 0, 0, 0, 0, 0, 0, 0 };
132  BOOST_CHECK_EQUAL(utils::format_timespan(gen_as_time_t(t)), utils::format_timespan(0));
133  BOOST_CHECK_EQUAL(utils::format_timespan(gen_as_time_t(t), true), utils::format_timespan(0));
134  BOOST_CHECK_EQUAL(utils::format_timespan(gen_as_time_t(t)), utils::format_timespan(-10000));
135  BOOST_CHECK_EQUAL(utils::format_timespan(gen_as_time_t(t), true), utils::format_timespan(-10000));
136 
137  test_format_timespan({ 4, 0, 49, 0, 0, 0, 0 }, "2 days, 1 hour, and 4 seconds", "2 days");
138 
139  test_format_timespan({ 0, 40, 0, 11, 1, 0, 4 }, "4 years, 2 weeks, 4 days, and 40 minutes", "4 years");
140 
141  test_format_timespan({ 0, 0, 1, 0, 0, 3, 4 }, "4 years, 3 months, and 1 hour", "4 years");
142 
143  test_format_timespan({ 10, 0, 0, 0, 0, 2, 0 }, "2 months and 10 seconds", "2 months");
144 }
145 
146 BOOST_AUTO_TEST_SUITE_END()
double t
Definition: astarsearch.cpp:63
std::string format_timespan(std::time_t time, bool detailed)
Formats a timespan into human-readable text for player authentication functions.
std::string format_conjunct_list(const t_string &empty, const std::vector< t_string > &elems)
Format a conjunctive list.
BOOST_AUTO_TEST_SUITE(filesystem)
mock_party p
BOOST_AUTO_TEST_CASE(test_formula_timespan)