Commit 81c4e8f70b5b114392a5513745631b44053a26d2

Authored by Jojo-1000
Committed by Moritz Wirger
1 parent 62d95333

Add tests for TimePattern, fix timestamp parsing.

include/hueplusplus/TimePattern.h
@@ -42,15 +42,16 @@ class AbsoluteTime @@ -42,15 +42,16 @@ class AbsoluteTime
42 public: 42 public:
43 explicit AbsoluteTime(clock::time_point baseTime, clock::duration variation = std::chrono::seconds(0)); 43 explicit AbsoluteTime(clock::time_point baseTime, clock::duration variation = std::chrono::seconds(0));
44 44
45 - clock::time_point getBaseTime();  
46 - clock::duration getRandomVariation(); 45 + clock::time_point getBaseTime() const;
  46 + clock::duration getRandomVariation() const;
47 47
48 - std::string toString(); 48 + std::string toString() const;
49 49
50 private: 50 private:
51 clock::time_point base; 51 clock::time_point base;
52 clock::duration variation; 52 clock::duration variation;
53 }; 53 };
  54 +
54 class Weekdays 55 class Weekdays
55 { 56 {
56 public: 57 public:
@@ -83,9 +84,14 @@ public: @@ -83,9 +84,14 @@ public:
83 static Weekdays sunday(); 84 static Weekdays sunday();
84 85
85 static Weekdays parse(const std::string& s); 86 static Weekdays parse(const std::string& s);
  87 +
  88 + bool operator==(const Weekdays& other) const { return bitmask == other.bitmask; }
  89 + bool operator!=(const Weekdays& other) const { return bitmask != other.bitmask; }
  90 +
86 private: 91 private:
87 int bitmask; 92 int bitmask;
88 }; 93 };
  94 +
89 class RecurringTime 95 class RecurringTime
90 { 96 {
91 using clock = std::chrono::system_clock; 97 using clock = std::chrono::system_clock;
@@ -104,6 +110,7 @@ private: @@ -104,6 +110,7 @@ private:
104 clock::duration variation; 110 clock::duration variation;
105 Weekdays days; 111 Weekdays days;
106 }; 112 };
  113 +
107 class TimeInterval 114 class TimeInterval
108 { 115 {
109 using clock = std::chrono::system_clock; 116 using clock = std::chrono::system_clock;
@@ -122,6 +129,7 @@ private: @@ -122,6 +129,7 @@ private:
122 clock::duration end; 129 clock::duration end;
123 Weekdays days; 130 Weekdays days;
124 }; 131 };
  132 +
125 class Timer 133 class Timer
126 { 134 {
127 using clock = std::chrono::system_clock; 135 using clock = std::chrono::system_clock;
@@ -176,6 +184,8 @@ public: @@ -176,6 +184,8 @@ public:
176 184
177 Timer asTimer() const; 185 Timer asTimer() const;
178 186
  187 + std::string toString() const;
  188 +
179 static TimePattern parse(const std::string& s); 189 static TimePattern parse(const std::string& s);
180 190
181 private: 191 private:
src/TimePattern.cpp
@@ -48,9 +48,9 @@ std::string timepointToTimestamp(clock::time_point time) @@ -48,9 +48,9 @@ std::string timepointToTimestamp(clock::time_point time)
48 48
49 clock::time_point parseTimestamp(const std::string& timestamp) 49 clock::time_point parseTimestamp(const std::string& timestamp)
50 { 50 {
51 - std::tm tm;  
52 - tm.tm_year = std::stoi(timestamp.substr(0, 4));  
53 - tm.tm_mon = std::stoi(timestamp.substr(5, 2)); 51 + std::tm tm {};
  52 + tm.tm_year = std::stoi(timestamp.substr(0, 4)) - 1900;
  53 + tm.tm_mon = std::stoi(timestamp.substr(5, 2)) - 1;
54 tm.tm_mday = std::stoi(timestamp.substr(8, 2)); 54 tm.tm_mday = std::stoi(timestamp.substr(8, 2));
55 tm.tm_hour = std::stoi(timestamp.substr(11, 2)); 55 tm.tm_hour = std::stoi(timestamp.substr(11, 2));
56 tm.tm_min = std::stoi(timestamp.substr(14, 2)); 56 tm.tm_min = std::stoi(timestamp.substr(14, 2));
@@ -82,21 +82,24 @@ std::string durationTo_hh_mm_ss(clock::duration duration) @@ -82,21 +82,24 @@ std::string durationTo_hh_mm_ss(clock::duration duration)
82 clock::duration parseDuration(const std::string& s) 82 clock::duration parseDuration(const std::string& s)
83 { 83 {
84 using namespace std::chrono; 84 using namespace std::chrono;
85 - return hours(std::stoi(s.substr(0, 2))) + minutes(std::stoi(s.substr(3, 2))) + seconds(std::stoi(s.substr(7, 2))); 85 + const hours hour(std::stoi(s.substr(0, 2)));
  86 + const minutes min(std::stoi(s.substr(3, 2)));
  87 + const seconds sec(std::stoi(s.substr(6, 2)));
  88 + return hour + min + sec;
86 } 89 }
87 90
88 AbsoluteTime::AbsoluteTime(clock::time_point baseTime, clock::duration variation) : base(baseTime), variation(variation) 91 AbsoluteTime::AbsoluteTime(clock::time_point baseTime, clock::duration variation) : base(baseTime), variation(variation)
89 {} 92 {}
90 93
91 -clock::time_point AbsoluteTime::getBaseTime() 94 +clock::time_point AbsoluteTime::getBaseTime() const
92 { 95 {
93 return base; 96 return base;
94 } 97 }
95 -clock::duration AbsoluteTime::getRandomVariation() 98 +clock::duration AbsoluteTime::getRandomVariation() const
96 { 99 {
97 return variation; 100 return variation;
98 } 101 }
99 -std::string AbsoluteTime::toString() 102 +std::string AbsoluteTime::toString() const
100 { 103 {
101 std::string result = timepointToTimestamp(base); 104 std::string result = timepointToTimestamp(base);
102 if (variation.count() != 0) 105 if (variation.count() != 0)
@@ -246,14 +249,14 @@ std::string RecurringTime::toString() const @@ -246,14 +249,14 @@ std::string RecurringTime::toString() const
246 { 249 {
247 std::string result = "W"; 250 std::string result = "W";
248 result.append(days.toString()); 251 result.append(days.toString());
249 - result.append("/"); 252 + result.append("/T");
250 result.append(durationTo_hh_mm_ss(time)); 253 result.append(durationTo_hh_mm_ss(time));
251 if (variation.count() != 0) 254 if (variation.count() != 0)
252 { 255 {
253 result.push_back('A'); 256 result.push_back('A');
254 result.append(durationTo_hh_mm_ss(variation)); 257 result.append(durationTo_hh_mm_ss(variation));
255 } 258 }
256 - return std::string(); 259 + return result;
257 } 260 }
258 261
259 TimeInterval::TimeInterval(clock::duration start, clock::duration end, Weekdays days) 262 TimeInterval::TimeInterval(clock::duration start, clock::duration end, Weekdays days)
@@ -355,25 +358,13 @@ TimePattern::~TimePattern() @@ -355,25 +358,13 @@ TimePattern::~TimePattern()
355 destroy(); 358 destroy();
356 } 359 }
357 360
358 -TimePattern::TimePattern(const AbsoluteTime& absolute) : type(Type::absolute)  
359 -{  
360 - new (&this->absolute) AbsoluteTime(absolute);  
361 -} 361 +TimePattern::TimePattern(const AbsoluteTime& absolute) : type(Type::absolute), absolute(absolute) {}
362 362
363 -TimePattern::TimePattern(const RecurringTime& recurring) : type(Type::recurring)  
364 -{  
365 - new (&this->recurring) RecurringTime(recurring);  
366 -} 363 +TimePattern::TimePattern(const RecurringTime& recurring) : type(Type::recurring), recurring(recurring) {}
367 364
368 -TimePattern::TimePattern(const TimeInterval& interval) : type(Type::interval)  
369 -{  
370 - new (&this->interval) TimeInterval(interval);  
371 -} 365 +TimePattern::TimePattern(const TimeInterval& interval) : type(Type::interval), interval(interval) {}
372 366
373 -TimePattern::TimePattern(const Timer& timer) : type(Type::timer)  
374 -{  
375 - new (&this->timer) Timer(timer);  
376 -} 367 +TimePattern::TimePattern(const Timer& timer) : type(Type::timer), timer(timer) {}
377 368
378 TimePattern::TimePattern(const TimePattern& other) : type(Type::undefined), undefined(nullptr) 369 TimePattern::TimePattern(const TimePattern& other) : type(Type::undefined), undefined(nullptr)
379 { 370 {
@@ -444,6 +435,25 @@ Timer TimePattern::asTimer() const @@ -444,6 +435,25 @@ Timer TimePattern::asTimer() const
444 return timer; 435 return timer;
445 } 436 }
446 437
  438 +std::string TimePattern::toString() const
  439 +{
  440 + switch (type)
  441 + {
  442 + case Type::undefined:
  443 + return std::string();
  444 + case Type::absolute:
  445 + return absolute.toString();
  446 + case Type::recurring:
  447 + return recurring.toString();
  448 + case Type::interval:
  449 + return interval.toString();
  450 + case Type::timer:
  451 + return timer.toString();
  452 + default:
  453 + throw HueException(CURRENT_FILE_INFO, "TimePattern has wrong type");
  454 + }
  455 +}
  456 +
447 TimePattern TimePattern::parse(const std::string& s) 457 TimePattern TimePattern::parse(const std::string& s)
448 { 458 {
449 if (s.empty() || s == "none") 459 if (s.empty() || s == "none")
@@ -471,7 +481,7 @@ TimePattern TimePattern::parse(const std::string& s) @@ -471,7 +481,7 @@ TimePattern TimePattern::parse(const std::string& s)
471 if (s.at(1) == '/') 481 if (s.at(1) == '/')
472 { 482 {
473 // Infinite 483 // Infinite
474 - numRepetitions = -1; 484 + numRepetitions = 0;
475 } 485 }
476 else 486 else
477 { 487 {
@@ -484,7 +494,7 @@ TimePattern TimePattern::parse(const std::string& s) @@ -484,7 +494,7 @@ TimePattern TimePattern::parse(const std::string& s)
484 clock::duration variance = std::chrono::seconds(0); 494 clock::duration variance = std::chrono::seconds(0);
485 if (randomStart != std::string::npos) 495 if (randomStart != std::string::npos)
486 { 496 {
487 - variance = parseDuration(s.substr(randomStart)); 497 + variance = parseDuration(s.substr(randomStart+1));
488 } 498 }
489 return TimePattern(Timer(expires, numRepetitions, variance)); 499 return TimePattern(Timer(expires, numRepetitions, variance));
490 } 500 }
@@ -535,6 +545,8 @@ void TimePattern::destroy() @@ -535,6 +545,8 @@ void TimePattern::destroy()
535 timer.~Timer(); 545 timer.~Timer();
536 break; 546 break;
537 default: 547 default:
  548 + // Do not throw exception, because it is called in destructor
  549 + // just ignore
538 break; 550 break;
539 } 551 }
540 type = Type::undefined; 552 type = Type::undefined;
test/test_TimePattern.cpp
@@ -26,6 +26,56 @@ using namespace hueplusplus::time; @@ -26,6 +26,56 @@ using namespace hueplusplus::time;
26 using std::chrono::system_clock; 26 using std::chrono::system_clock;
27 using namespace std::chrono_literals; 27 using namespace std::chrono_literals;
28 28
  29 +TEST(Time, parseTimestamp)
  30 +{
  31 + std::tm tm {};
  32 + tm.tm_year = 2020 - 1900;
  33 + tm.tm_mon = 3 - 1;
  34 + tm.tm_mday = 24;
  35 + tm.tm_hour = 12;
  36 + tm.tm_min = 45;
  37 + tm.tm_sec = 0;
  38 + // Auto detect daylight savings time
  39 + tm.tm_isdst = -1;
  40 + const std::time_t ctime = std::mktime(&tm);
  41 + const auto timePoint = system_clock::from_time_t(ctime);
  42 + EXPECT_EQ(timePoint, parseTimestamp("2020-03-24T12:45:00"));
  43 +}
  44 +
  45 +TEST(Time, timepointToTimestamp)
  46 +{
  47 + std::tm tm {};
  48 + tm.tm_year = 2020 - 1900;
  49 + tm.tm_mon = 3 - 1;
  50 + tm.tm_mday = 24;
  51 + tm.tm_hour = 12;
  52 + tm.tm_min = 45;
  53 + tm.tm_sec = 0;
  54 + // Auto detect daylight savings time
  55 + tm.tm_isdst = -1;
  56 + const std::time_t ctime = std::mktime(&tm);
  57 + const auto timePoint = system_clock::from_time_t(ctime);
  58 + EXPECT_EQ("2020-03-24T12:45:00", timepointToTimestamp(timePoint));
  59 +
  60 + EXPECT_EQ(timePoint, parseTimestamp(timepointToTimestamp(timePoint)));
  61 +}
  62 +
  63 +TEST(Time, parseDuration)
  64 +{
  65 + EXPECT_EQ(1h + 24min + 1s, parseDuration("01:24:01"));
  66 + EXPECT_EQ(22h + 59min + 49s, parseDuration("22:59:49"));
  67 + EXPECT_EQ(0s, parseDuration("00:00:00"));
  68 +}
  69 +
  70 +TEST(Time, durationTo_hh_mm_ss)
  71 +{
  72 + EXPECT_EQ("00:00:00", durationTo_hh_mm_ss(0s));
  73 + EXPECT_EQ("01:32:05", durationTo_hh_mm_ss(1h + 32min + 5s));
  74 + EXPECT_EQ("20:45:13", durationTo_hh_mm_ss(20h + 45min + 13s));
  75 + const auto duration = 20h + 45min + 13s;
  76 + EXPECT_EQ(duration, parseDuration(durationTo_hh_mm_ss(duration)));
  77 +}
  78 +
29 TEST(AbsoluteTime, Constructor) 79 TEST(AbsoluteTime, Constructor)
30 { 80 {
31 system_clock::time_point now = system_clock::now(); 81 system_clock::time_point now = system_clock::now();
@@ -44,15 +94,7 @@ TEST(AbsoluteTime, Constructor) @@ -44,15 +94,7 @@ TEST(AbsoluteTime, Constructor)
44 94
45 TEST(AbsoluteTime, toString) 95 TEST(AbsoluteTime, toString)
46 { 96 {
47 - std::tm time {};  
48 - time.tm_year = 2020 - 1900;  
49 - time.tm_mon = 2;  
50 - time.tm_mday = 3;  
51 - time.tm_hour = 20;  
52 - time.tm_min = 53;  
53 - time.tm_sec = 3;  
54 - std::time_t ctime = std::mktime(&time);  
55 - const system_clock::time_point timePoint = system_clock::from_time_t(ctime); 97 + const system_clock::time_point timePoint = parseTimestamp("2020-03-03T20:53:03");
56 98
57 EXPECT_EQ("2020-03-03T20:53:03", AbsoluteTime(timePoint).toString()); 99 EXPECT_EQ("2020-03-03T20:53:03", AbsoluteTime(timePoint).toString());
58 100
@@ -122,9 +164,320 @@ TEST(Weekdays, unionWith) @@ -122,9 +164,320 @@ TEST(Weekdays, unionWith)
122 EXPECT_TRUE(day.isAll()); 164 EXPECT_TRUE(day.isAll());
123 } 165 }
124 166
  167 +TEST(Weekdays, equals)
  168 +{
  169 + EXPECT_EQ(Weekdays::monday(), Weekdays(0));
  170 + EXPECT_EQ(Weekdays::none(), Weekdays());
  171 + EXPECT_EQ(Weekdays::monday() | Weekdays::tuesday(), Weekdays::monday().unionWith(Weekdays::tuesday()));
  172 +
  173 + EXPECT_NE(Weekdays::none(), Weekdays(0));
  174 + EXPECT_NE(Weekdays::all(), Weekdays::monday());
  175 +}
  176 +
125 TEST(Weekdays, toString) 177 TEST(Weekdays, toString)
126 { 178 {
127 EXPECT_EQ("001", Weekdays(0).toString()); 179 EXPECT_EQ("001", Weekdays(0).toString());
128 EXPECT_EQ("064", Weekdays(6).toString()); 180 EXPECT_EQ("064", Weekdays(6).toString());
129 EXPECT_EQ("112", (Weekdays(6) | Weekdays(5) | Weekdays(4)).toString()); 181 EXPECT_EQ("112", (Weekdays(6) | Weekdays(5) | Weekdays(4)).toString());
130 } 182 }
  183 +
  184 +TEST(RecurringTime, Constructor)
  185 +{
  186 + {
  187 + const auto time = 6h + 4min;
  188 + const Weekdays days = Weekdays::all();
  189 + const RecurringTime recurring(time, days);
  190 +
  191 + EXPECT_EQ(time, recurring.getDaytime());
  192 + EXPECT_EQ(0s, recurring.getRandomVariation());
  193 + EXPECT_EQ(days, recurring.getWeekdays());
  194 + }
  195 + {
  196 + const auto time = 2h + 3min + 2s;
  197 + const Weekdays days = Weekdays::monday() | Weekdays::friday();
  198 + const auto variation = 40min;
  199 + const RecurringTime recurring(time, days, variation);
  200 +
  201 + EXPECT_EQ(time, recurring.getDaytime());
  202 + EXPECT_EQ(variation, recurring.getRandomVariation());
  203 + EXPECT_EQ(days, recurring.getWeekdays());
  204 + }
  205 +}
  206 +
  207 +TEST(RecurringTime, toString)
  208 +{
  209 + const auto time = 0h + 4min;
  210 + const RecurringTime recurring(time, Weekdays::monday());
  211 + EXPECT_EQ("W001/T00:04:00", recurring.toString());
  212 +
  213 + const RecurringTime variation(time, Weekdays::monday(), 1s);
  214 + EXPECT_EQ("W001/T00:04:00A00:00:01", variation.toString());
  215 +}
  216 +
  217 +TEST(TimeInterval, Constructor)
  218 +{
  219 + {
  220 + const auto start = 1h + 40min;
  221 + const auto end = 11h + 25s;
  222 + const TimeInterval interval(start, end);
  223 +
  224 + EXPECT_EQ(start, interval.getStartTime());
  225 + EXPECT_EQ(end, interval.getEndTime());
  226 + EXPECT_EQ(Weekdays::all(), interval.getWeekdays());
  227 + }
  228 + {
  229 + const auto start = 0s;
  230 + const auto end = 20h;
  231 + const Weekdays days = Weekdays::friday() | Weekdays::saturday();
  232 + const TimeInterval interval(start, end, days);
  233 + EXPECT_EQ(start, interval.getStartTime());
  234 + EXPECT_EQ(end, interval.getEndTime());
  235 + EXPECT_EQ(days, interval.getWeekdays());
  236 + }
  237 +}
  238 +
  239 +TEST(TimeInterval, toString)
  240 +{
  241 + {
  242 + const TimeInterval interval(1h + 40min, 11h + 25s);
  243 + EXPECT_EQ("T01:40:00/T11:00:25", interval.toString());
  244 + }
  245 + {
  246 + const TimeInterval interval(0h, 20h + 1s, Weekdays::monday());
  247 + EXPECT_EQ("W001/T00:00:00/T20:00:01", interval.toString());
  248 + }
  249 +}
  250 +
  251 +TEST(Timer, Constructor)
  252 +{
  253 + {
  254 + const auto duration = 1min + 20s;
  255 + const Timer timer(duration);
  256 + EXPECT_FALSE(timer.isRecurring());
  257 + EXPECT_EQ(1, timer.getNumberOfExecutions());
  258 + EXPECT_EQ(duration, timer.getExpiryTime());
  259 + EXPECT_EQ(0s, timer.getRandomVariation());
  260 + }
  261 + {
  262 + const auto duration = 1min + 20s;
  263 + const auto variation = 1h;
  264 + const Timer timer(duration, variation);
  265 + EXPECT_FALSE(timer.isRecurring());
  266 + EXPECT_EQ(1, timer.getNumberOfExecutions());
  267 + EXPECT_EQ(duration, timer.getExpiryTime());
  268 + EXPECT_EQ(variation, timer.getRandomVariation());
  269 + }
  270 + {
  271 + const auto duration = 1min + 20s;
  272 + const int num = 0;
  273 + const Timer timer(duration, num);
  274 + EXPECT_TRUE(timer.isRecurring());
  275 + EXPECT_EQ(num, timer.getNumberOfExecutions());
  276 + EXPECT_EQ(duration, timer.getExpiryTime());
  277 + EXPECT_EQ(0s, timer.getRandomVariation());
  278 + }
  279 + {
  280 + const auto duration = 1min + 20s;
  281 + const int num = 10;
  282 + const auto variation = 20min;
  283 + const Timer timer(duration, num, variation);
  284 + EXPECT_TRUE(timer.isRecurring());
  285 + EXPECT_EQ(num, timer.getNumberOfExecutions());
  286 + EXPECT_EQ(duration, timer.getExpiryTime());
  287 + EXPECT_EQ(variation, timer.getRandomVariation());
  288 + }
  289 +}
  290 +
  291 +TEST(Timer, toString)
  292 +{
  293 + {
  294 + const Timer timer(1min + 20s);
  295 + EXPECT_EQ("PT00:01:20", timer.toString());
  296 + }
  297 + {
  298 + const Timer timer(1min + 20s, 1h);
  299 + EXPECT_EQ("PT00:01:20A01:00:00", timer.toString());
  300 + }
  301 + {
  302 + const Timer timer(1min + 20s, 0);
  303 + EXPECT_EQ("R/PT00:01:20", timer.toString());
  304 + }
  305 + {
  306 + const Timer timer(1min + 20s, 1);
  307 + EXPECT_EQ("PT00:01:20", timer.toString());
  308 + }
  309 + {
  310 + const Timer timer(1min + 20s, 15);
  311 + EXPECT_EQ("R15/PT00:01:20", timer.toString());
  312 + }
  313 + {
  314 + const Timer timer(1min + 20s, 5, 1h);
  315 + EXPECT_EQ("R05/PT00:01:20A01:00:00", timer.toString());
  316 + }
  317 + {
  318 + const Timer timer(1min + 20s, 0, 1h);
  319 + EXPECT_EQ("R/PT00:01:20A01:00:00", timer.toString());
  320 + }
  321 +}
  322 +
  323 +TEST(TimePattern, Undefined)
  324 +{
  325 + {
  326 + TimePattern pattern;
  327 + EXPECT_EQ(TimePattern::Type::undefined, pattern.getType());
  328 + }
  329 + {
  330 + TimePattern pattern = TimePattern::parse("");
  331 + EXPECT_EQ(TimePattern::Type::undefined, pattern.getType());
  332 + }
  333 + {
  334 + TimePattern pattern = TimePattern::parse("none");
  335 + EXPECT_EQ(TimePattern::Type::undefined, pattern.getType());
  336 + }
  337 +}
  338 +
  339 +TEST(TimePattern, Absolute)
  340 +{
  341 + {
  342 + const AbsoluteTime abs(system_clock::now(), 20s);
  343 + const TimePattern pattern(abs);
  344 + ASSERT_EQ(TimePattern::Type::absolute, pattern.getType());
  345 + EXPECT_EQ(abs.getBaseTime(), pattern.asAbsolute().getBaseTime());
  346 + EXPECT_EQ(abs.getRandomVariation(), pattern.asAbsolute().getRandomVariation());
  347 + }
  348 +
  349 + const system_clock::time_point timePoint = parseTimestamp("2020-03-03T20:53:03");
  350 + {
  351 + const TimePattern pattern = TimePattern::parse("2020-03-03T20:53:03");
  352 + const AbsoluteTime expected(timePoint);
  353 + ASSERT_EQ(TimePattern::Type::absolute, pattern.getType());
  354 + EXPECT_EQ(expected.getBaseTime(), pattern.asAbsolute().getBaseTime());
  355 + EXPECT_EQ(expected.getRandomVariation(), pattern.asAbsolute().getRandomVariation());
  356 + }
  357 + {
  358 + const system_clock::duration variation = 1h + 2min + 1s;
  359 + const TimePattern pattern = TimePattern::parse("2020-03-03T20:53:03A01:02:01");
  360 + const AbsoluteTime expected(timePoint, variation);
  361 + ASSERT_EQ(TimePattern::Type::absolute, pattern.getType());
  362 + EXPECT_EQ(expected.getBaseTime(), pattern.asAbsolute().getBaseTime());
  363 + EXPECT_EQ(expected.getRandomVariation(), pattern.asAbsolute().getRandomVariation());
  364 + }
  365 +}
  366 +
  367 +TEST(TimePattern, Recurring)
  368 +{
  369 + {
  370 + const RecurringTime rec(12h + 30min, Weekdays::monday(), 1h);
  371 + const TimePattern pattern(rec);
  372 + ASSERT_EQ(TimePattern::Type::recurring, pattern.getType());
  373 + EXPECT_EQ(rec.getDaytime(), pattern.asRecurring().getDaytime());
  374 + EXPECT_EQ(rec.getWeekdays(), pattern.asRecurring().getWeekdays());
  375 + EXPECT_EQ(rec.getRandomVariation(), pattern.asRecurring().getRandomVariation());
  376 + }
  377 + {
  378 + const TimePattern pattern = TimePattern::parse("W001/T12:30:00");
  379 + const RecurringTime expected(12h + 30min, Weekdays::monday());
  380 +
  381 + ASSERT_EQ(TimePattern::Type::recurring, pattern.getType());
  382 + EXPECT_EQ(expected.getDaytime(), pattern.asRecurring().getDaytime());
  383 + EXPECT_EQ(expected.getWeekdays(), pattern.asRecurring().getWeekdays());
  384 + EXPECT_EQ(expected.getRandomVariation(), pattern.asRecurring().getRandomVariation());
  385 + }
  386 + {
  387 + const TimePattern pattern = TimePattern::parse("W001/T12:30:00A01:00:00");
  388 + const RecurringTime expected(12h + 30min, Weekdays::monday(), 1h);
  389 +
  390 + ASSERT_EQ(TimePattern::Type::recurring, pattern.getType());
  391 + EXPECT_EQ(expected.getDaytime(), pattern.asRecurring().getDaytime());
  392 + EXPECT_EQ(expected.getWeekdays(), pattern.asRecurring().getWeekdays());
  393 + EXPECT_EQ(expected.getRandomVariation(), pattern.asRecurring().getRandomVariation());
  394 + }
  395 +}
  396 +
  397 +TEST(TimePattern, Interval)
  398 +{
  399 + {
  400 + const TimeInterval interval(12h + 30min, 13h + 20min, Weekdays::friday());
  401 + const TimePattern pattern(interval);
  402 + ASSERT_EQ(TimePattern::Type::interval, pattern.getType());
  403 + EXPECT_EQ(interval.getStartTime(), pattern.asInterval().getStartTime());
  404 + EXPECT_EQ(interval.getEndTime(), pattern.asInterval().getEndTime());
  405 + EXPECT_EQ(interval.getWeekdays(), pattern.asInterval().getWeekdays());
  406 + }
  407 + {
  408 + const TimeInterval expected(12h + 30min, 13h + 20min + 12s);
  409 + const TimePattern pattern = TimePattern::parse("T12:30:00/T13:20:12");
  410 + ASSERT_EQ(TimePattern::Type::interval, pattern.getType());
  411 + EXPECT_EQ(expected.getStartTime(), pattern.asInterval().getStartTime());
  412 + EXPECT_EQ(expected.getEndTime(), pattern.asInterval().getEndTime());
  413 + EXPECT_EQ(expected.getWeekdays(), pattern.asInterval().getWeekdays());
  414 + }
  415 + {
  416 + const TimeInterval expected(12h + 30min, 13h + 20min + 12s, Weekdays::monday());
  417 + const TimePattern pattern = TimePattern::parse("W001/T12:30:00/T13:20:12");
  418 + ASSERT_EQ(TimePattern::Type::interval, pattern.getType());
  419 + EXPECT_EQ(expected.getStartTime(), pattern.asInterval().getStartTime());
  420 + EXPECT_EQ(expected.getEndTime(), pattern.asInterval().getEndTime());
  421 + EXPECT_EQ(expected.getWeekdays(), pattern.asInterval().getWeekdays());
  422 + }
  423 +}
  424 +
  425 +TEST(TimePattern, Timer)
  426 +{
  427 + {
  428 + const Timer timer(1h + 30min, 5, 20s);
  429 + const TimePattern pattern(timer);
  430 + ASSERT_EQ(TimePattern::Type::timer, pattern.getType());
  431 + EXPECT_EQ(timer.getExpiryTime(), pattern.asTimer().getExpiryTime());
  432 + EXPECT_EQ(timer.getRandomVariation(), pattern.asTimer().getRandomVariation());
  433 + EXPECT_EQ(timer.getNumberOfExecutions(), pattern.asTimer().getNumberOfExecutions());
  434 + }
  435 + {
  436 + const Timer expected(1h + 30min + 20s);
  437 + const TimePattern pattern = TimePattern::parse("PT01:30:20");
  438 + ASSERT_EQ(TimePattern::Type::timer, pattern.getType());
  439 + EXPECT_EQ(expected.getExpiryTime(), pattern.asTimer().getExpiryTime());
  440 + EXPECT_EQ(expected.getRandomVariation(), pattern.asTimer().getRandomVariation());
  441 + EXPECT_EQ(expected.getNumberOfExecutions(), pattern.asTimer().getNumberOfExecutions());
  442 + }
  443 + {
  444 + const Timer expected(1h + 30min + 20s, 20s);
  445 + const TimePattern pattern = TimePattern::parse("PT01:30:20A00:00:20");
  446 + ASSERT_EQ(TimePattern::Type::timer, pattern.getType());
  447 + EXPECT_EQ(expected.getExpiryTime(), pattern.asTimer().getExpiryTime());
  448 + EXPECT_EQ(expected.getRandomVariation(), pattern.asTimer().getRandomVariation());
  449 + EXPECT_EQ(expected.getNumberOfExecutions(), pattern.asTimer().getNumberOfExecutions());
  450 + }
  451 + {
  452 + const Timer expected(1h + 30min + 20s, 0);
  453 + const TimePattern pattern = TimePattern::parse("R/PT01:30:20");
  454 + ASSERT_EQ(TimePattern::Type::timer, pattern.getType());
  455 + EXPECT_EQ(expected.getExpiryTime(), pattern.asTimer().getExpiryTime());
  456 + EXPECT_EQ(expected.getRandomVariation(), pattern.asTimer().getRandomVariation());
  457 + EXPECT_EQ(expected.getNumberOfExecutions(), pattern.asTimer().getNumberOfExecutions());
  458 + }
  459 + {
  460 + const Timer expected(1h + 30min + 20s, 0, 20s);
  461 + const TimePattern pattern = TimePattern::parse("R/PT01:30:20A00:00:20");
  462 + ASSERT_EQ(TimePattern::Type::timer, pattern.getType());
  463 + EXPECT_EQ(expected.getExpiryTime(), pattern.asTimer().getExpiryTime());
  464 + EXPECT_EQ(expected.getRandomVariation(), pattern.asTimer().getRandomVariation());
  465 + EXPECT_EQ(expected.getNumberOfExecutions(), pattern.asTimer().getNumberOfExecutions());
  466 + }
  467 + {
  468 + const Timer expected(1h + 30min + 20s, 5);
  469 + const TimePattern pattern = TimePattern::parse("R05/PT01:30:20");
  470 + ASSERT_EQ(TimePattern::Type::timer, pattern.getType());
  471 + EXPECT_EQ(expected.getExpiryTime(), pattern.asTimer().getExpiryTime());
  472 + EXPECT_EQ(expected.getRandomVariation(), pattern.asTimer().getRandomVariation());
  473 + EXPECT_EQ(expected.getNumberOfExecutions(), pattern.asTimer().getNumberOfExecutions());
  474 + }
  475 + {
  476 + const Timer expected(1h + 30min + 20s, 5, 20s);
  477 + const TimePattern pattern = TimePattern::parse("R05/PT01:30:20A00:00:20");
  478 + ASSERT_EQ(TimePattern::Type::timer, pattern.getType());
  479 + EXPECT_EQ(expected.getExpiryTime(), pattern.asTimer().getExpiryTime());
  480 + EXPECT_EQ(expected.getRandomVariation(), pattern.asTimer().getRandomVariation());
  481 + EXPECT_EQ(expected.getNumberOfExecutions(), pattern.asTimer().getNumberOfExecutions());
  482 + }
  483 +}
131 \ No newline at end of file 484 \ No newline at end of file