Skip to content

Commit bec8f9d

Browse files
committed
Updates as listed in CHANGES.md
1 parent 4da49e0 commit bec8f9d

6 files changed

Lines changed: 111 additions & 119 deletions

File tree

CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## New Features
44

5+
- Add `Signal::HandlerScope` to restore the default handler when the object goes out of scope
6+
- Add `Test::TimedScope` class to check for testing durations
7+
- Add enum class `chrono::Date::Month` for a list of months
58
- Add class `Thread::Mq` to support posix mqueue
69
- Add optional stack size parameter when constructing `Thread::Attributes`
710
- If `Thread::Attributes` changes policy or priority, policy inherit is disabled

libraries/ChronoAPI/include/chrono/DateTime.hpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,26 @@ class Date {
9292
int minute() const { return m_tm.tm_min; }
9393
int hour() const { return m_tm.tm_hour; }
9494

95+
enum class Month {
96+
null,
97+
january,
98+
february,
99+
march,
100+
april,
101+
may,
102+
june,
103+
july,
104+
august,
105+
september,
106+
october,
107+
november,
108+
december
109+
};
110+
95111
int day() const { return m_tm.tm_mday; }
96112
int weekday() const { return m_tm.tm_wday; }
97113
int yearday() const { return m_tm.tm_yday; }
98-
int month() const { return m_tm.tm_mon + 1; }
114+
Month month() const { return Month(m_tm.tm_mon + 1); }
99115
int year() const { return m_tm.tm_year + 1900; }
100116

101117
const struct tm &get_tm() const { return m_tm; }

libraries/TestAPI/include/test/Test.hpp

Lines changed: 40 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -70,70 +70,18 @@ class Test : public api::ExecutionContext, public TestFlags {
7070
API_AF(Initialize, printer::Printer *, printer, nullptr);
7171
};
7272

73-
/*! \details Initializes the test report.
74-
*
75-
* This must be called before any tests are even
76-
* constructed.
77-
*
78-
*/
7973
static void initialize(const Initialize &options);
80-
81-
/*! \details Finalizes the test report.
82-
*
83-
* This should be called after the last test
84-
* has been deconstructed.
85-
*
86-
*/
8774
static void finalize();
8875

89-
/*! \details Parse command line options for running test types.
90-
*
91-
* This method searches for the following options and returns
92-
* a value that has which tests to execute.
93-
*
94-
* - -execute_all
95-
* - -api
96-
* - -performance
97-
* - -stress
98-
* - -additional
99-
*
100-
* \code
101-
* #include <test.hpp>
102-
* #include <sys.hpp>
103-
*
104-
* int main(int argc, char * argv[]){
105-
* Cli cli(argc, argv);
106-
* u32 o_execute_flags = Test::parse_options(cli);
107-
*
108-
* Test::initialize(cli.name(), cli.version());
109-
*
110-
* if( o_execute_flags ){
111-
* Test test("do nothing");
112-
* test.execute(o_execute_flags);
113-
* }
114-
*
115-
* Test::finalize();
116-
*
117-
* return 0;
118-
* }
119-
*
120-
* \endcode
121-
*
122-
*/
12376
static ExecuteFlags parse_execution_flags(const sys::Cli &cli);
124-
static u32
125-
parse_test(const sys::Cli &cli, var::StringView name, u32 test_flag);
77+
static u32 parse_test(const sys::Cli &cli, var::StringView name,
78+
u32 test_flag);
12679

12780
Test(var::StringView name);
12881
~Test();
12982

13083
void execute(const sys::Cli &cli);
13184

132-
/*! \details Executes the tests specified by \a o_flags.
133-
*
134-
* @param o_flags Bitmask of the tests to execute (e.g., Test::EXECUTE_API)
135-
*
136-
*/
13785
void execute(ExecuteFlags execute_flags = ExecuteFlags::all) {
13886
if (execute_flags & ExecuteFlags::api) {
13987
execute_api_case();
@@ -146,59 +94,17 @@ class Test : public api::ExecutionContext, public TestFlags {
14694
}
14795
}
14896

149-
/*! \details Executes the API test case. */
15097
void execute_api_case();
151-
/*! \details Executes the performance test case. */
15298
void execute_performance_case();
153-
/*! \details Executes the stress test case. */
15499
void execute_stress_case();
155100

156-
/*! \details Executes the class api test.
157-
*
158-
* This method should be overridden by the inheriting
159-
* class.
160-
*
161-
*/
162101
virtual bool execute_class_api_case();
163-
164-
/*! \details Executes the class performance test.
165-
*
166-
* This method should be overridden by the inheriting
167-
* class.
168-
*
169-
*/
170102
virtual bool execute_class_performance_case();
171-
172-
/*! \details Executes the class stress test.
173-
*
174-
* This method should be overridden by the inheriting
175-
* class.
176-
*
177-
*/
178103
virtual bool execute_class_stress_case();
179104

180-
/*! \details Returns the results of the test.
181-
*
182-
* If any single test case has a false result,
183-
* the result of the test is false. Otherwise,
184-
* the result is true.
185-
*
186-
*/
187105
bool result() const { return m_test_result; }
188-
189-
/*! \details Returns the current value of the case result.
190-
*
191-
* When a case is opened, the case result is set to true (passing).
192-
*
193-
* Calling set_case_failed() or print_case_failed() will set
194-
* the case result value to false.
195-
*
196-
* case_result() is the default return value of close_case().
197-
*
198-
*/
199106
bool case_result() const { return m_case_result; }
200107

201-
/*! \details Sets the current case result to failed. */
202108
void set_case_failed() {
203109
m_case_result = false;
204110
m_test_result = false;
@@ -210,9 +116,8 @@ class Test : public api::ExecutionContext, public TestFlags {
210116
return true;
211117
}
212118

213-
printer().key(
214-
var::String().format("expect%d", line),
215-
var::String().format("%s failed", function));
119+
printer().key(var::String().format("expect%d", line),
120+
var::String().format("%s failed", function));
216121

217122
if (is_error()) {
218123
printer().object("errorContext", api::ExecutionContext::error());
@@ -225,6 +130,42 @@ class Test : public api::ExecutionContext, public TestFlags {
225130

226131
static bool final_result() { return m_final_result; }
227132

133+
class TimedScope {
134+
public:
135+
TimedScope(Test &test, const var::StringView name,
136+
const chrono::MicroTime &minimum,
137+
const chrono::MicroTime &maximum)
138+
: m_test(test), m_name(name), m_start(test.case_timer().milliseconds()),
139+
m_minimum(minimum.milliseconds()), m_maximum(maximum.milliseconds()) {
140+
m_test.printer().open_object(name);
141+
API_ASSERT(m_minimum < m_maximum);
142+
}
143+
144+
~TimedScope() {
145+
const auto stop = m_test.case_timer().milliseconds();
146+
const auto duration = stop - m_start;
147+
m_test.printer()
148+
.key("minimum (ms)", var::NumberString(m_minimum))
149+
.key("maximum (ms)", var::NumberString(m_maximum))
150+
.key("duration (ms)", var::NumberString(duration));
151+
if (duration < m_minimum) {
152+
m_test.printer().error("duration below minimum");
153+
m_test.set_case_failed();
154+
} else if( duration > m_maximum ){
155+
m_test.printer().error("duration above maximum");
156+
m_test.set_case_failed();
157+
}
158+
m_test.printer().close_object();
159+
}
160+
161+
private:
162+
Test &m_test;
163+
var::StringView m_name;
164+
u32 m_start;
165+
u32 m_minimum;
166+
u32 m_maximum;
167+
};
168+
228169
protected:
229170
const chrono::ClockTimer &case_timer() const { return m_case_timer; }
230171
chrono::ClockTimer &case_timer() { return m_case_timer; }

libraries/ThreadAPI/include/thread/Signal.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,18 @@ class Signal : public SignalFlags {
248248
API_NO_DISCARD int sigvalue() const { return m_sigvalue.sival_int; }
249249
API_NO_DISCARD void *sigptr() const { return m_sigvalue.sival_ptr; }
250250

251+
class HandlerScope {
252+
public:
253+
HandlerScope(Signal & signal, const SignalHandler & handler) : m_signo(signal.number()){
254+
signal.set_handler(handler);
255+
}
256+
~HandlerScope(){
257+
Signal(m_signo).set_handler(SignalHandler::default_());
258+
}
259+
private:
260+
Number m_signo;
261+
};
262+
251263
private:
252264
int m_signo;
253265
union sigval m_sigvalue;

libraries/ThreadAPI/include/thread/Timer.hpp

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,45 +5,38 @@
55

66
#include <signal.h>
77

8-
#include "chrono/ClockTime.hpp"
98
#include "Signal.hpp"
9+
#include "chrono/ClockTime.hpp"
1010

1111
namespace thread {
1212

1313
class Timer : public api::ExecutionContext {
1414
public:
1515
using ClockId = chrono::ClockTime::ClockId;
16-
Timer(Signal::Event& signal_event, ClockId clock_id = ClockId::realtime);
16+
Timer(Signal::Event &signal_event, ClockId clock_id = ClockId::realtime);
1717
~Timer();
1818

19-
Timer(const Timer & a) = delete;
20-
Timer& operator=(const Timer &a) = delete;
19+
Timer(const Timer &a) = delete;
20+
Timer &operator=(const Timer &a) = delete;
2121

22-
Timer(Timer && a){
23-
std::swap(m_timer, a.m_timer);
24-
}
22+
Timer(Timer &&a) { std::swap(m_timer, a.m_timer); }
2523

26-
Timer& operator=(Timer &&a){
24+
Timer &operator=(Timer &&a) {
2725
std::swap(m_timer, a.m_timer);
2826
return *this;
2927
}
3028

31-
bool is_valid() const {
32-
return m_timer != timer_t(-1);
33-
}
29+
bool is_valid() const { return m_timer != timer_t(-1); }
3430

35-
enum class Flags {
36-
null = 0,
37-
absolute_time = TIMER_ABSTIME
38-
};
31+
enum class Flags { null = 0, absolute_time = TIMER_ABSTIME };
3932

4033
class SetTime {
4134
API_AC(SetTime, chrono::ClockTime, interval);
4235
API_AC(SetTime, chrono::ClockTime, value);
4336
API_AF(SetTime, Flags, flags, Flags::null);
4437
};
4538

46-
Timer & set_time(const SetTime & options);
39+
Timer &set_time(const SetTime &options);
4740

4841
class Info {
4942
API_RAC(Info, chrono::ClockTime, interval);
@@ -53,9 +46,21 @@ class Timer : public api::ExecutionContext {
5346

5447
Info get_info() const;
5548

49+
class Alarm {
50+
public:
51+
enum class Type { seconds, useconds };
52+
53+
private:
54+
API_AC(Alarm, chrono::ClockTime, value);
55+
API_AC(Alarm, chrono::ClockTime, interval);
56+
API_AF(Alarm, Type, type, Type::seconds);
57+
};
58+
59+
static chrono::ClockTime alarm(const Alarm &options);
60+
static void cancel_alarm() { alarm(Alarm()); }
61+
5662
private:
5763
timer_t m_timer = timer_t(-1);
58-
5964
};
6065

6166
} // namespace thread

libraries/ThreadAPI/src/Timer.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
#include <unistd.h>
2+
13
#include "thread/Timer.hpp"
24

5+
extern "C" useconds_t ualarm(useconds_t useconds, useconds_t interval);
6+
37
using namespace thread;
48

59
Timer::Timer(Signal::Event &signal_event, ClockId clock_id) {
@@ -21,11 +25,11 @@ Timer &Timer::set_time(const SetTime &options) {
2125
struct itimerspec value = {.it_interval = *options.interval().timespec(),
2226
.it_value = *options.value().timespec()};
2327

24-
API_SYSTEM_CALL("", timer_settime(m_timer, int(options.flags()), &value, nullptr));
28+
API_SYSTEM_CALL(
29+
"", timer_settime(m_timer, int(options.flags()), &value, nullptr));
2530
return *this;
2631
}
2732

28-
2933
Timer::Info Timer::get_info() const {
3034
API_RETURN_VALUE_IF_ERROR(Info());
3135

@@ -37,3 +41,14 @@ Timer::Info Timer::get_info() const {
3741
return result;
3842
}
3943

44+
chrono::ClockTime Timer::alarm(const Alarm &options) {
45+
API_RETURN_VALUE_IF_ERROR(chrono::ClockTime());
46+
if (options.type() == Alarm::Type::seconds) {
47+
API_SYSTEM_CALL("", ::alarm(options.value().seconds()));
48+
return chrono::ClockTime(return_value() * 1_seconds);
49+
}
50+
51+
API_SYSTEM_CALL("", ::ualarm(options.value().nanoseconds() / 1000UL,
52+
options.interval().nanoseconds() / 1000UL));
53+
return chrono::ClockTime(return_value() * 1_microseconds);
54+
}

0 commit comments

Comments
 (0)