Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F90917246
misc.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Nov 5, 23:35
Size
11 KB
Mime Type
text/x-c++
Expires
Thu, Nov 7, 23:35 (2 d)
Engine
blob
Format
Raw Data
Handle
22158462
Attached To
rSPECMICP SpecMiCP / ReactMiCP
misc.cpp
View Options
#include "catch.hpp"
#include "utils/log.hpp"
#include "utils/timer.hpp"
#include "physics/maths.hpp"
#include "utils/moving_average.hpp"
#include "utils/perfs_handler.hpp"
#include "utils/options_handler.hpp"
#include "utils/scope_guard.hpp"
#include "utils/pimpl_ptr.hpp"
#include "utils/cached_vector.hpp"
#include <sstream>
using
namespace
specmicp
;
// TOC
// =======================
//
// 1 - Logger
// 2 - Timer
// 3 - Average
// 4 - Moving Average
// 5 - Performance handler
// 6 - Options handler
// 7 - Scope guard
// 8 - Pimpl pointer
// 9 - Cached Vector
// 10 - Named Cached Vector
// Logger
// =======================
TEST_CASE
(
"Logger"
,
"[io],[log]"
)
{
SECTION
(
"Non init logging"
)
{
init_logger
(
nullptr
,
logger
::
LogLevel
::
Warning
);
// compilation test, and runtime test of not failling nullptr
SPAM
<<
"Spam"
;
DEBUG
<<
"Debug"
;
INFO
<<
"Info"
;
WARNING
<<
"Warning"
;
ERROR
<<
"Error"
;
CRITICAL
<<
"Critical"
;
}
SECTION
(
"Level test"
)
{
std
::
stringstream
stream_log
;
init_logger
(
&
stream_log
,
logger
::
LogLevel
::
Warning
);
SPAM
<<
"Spam"
;
REQUIRE
(
stream_log
.
str
().
size
()
==
0
);
DEBUG
<<
"Debug"
;
REQUIRE
(
stream_log
.
str
().
size
()
==
0
);
INFO
<<
"Info"
;
REQUIRE
(
stream_log
.
str
().
size
()
==
0
);
WARNING
<<
"Warning"
;
REQUIRE
(
stream_log
.
str
().
size
()
!=
0
);
stream_log
.
str
(
""
);
ERROR
<<
"Error"
;
REQUIRE
(
stream_log
.
str
().
size
()
!=
0
);
stream_log
.
str
(
""
);
CRITICAL
<<
"Critical"
;
REQUIRE
(
stream_log
.
str
().
size
()
!=
0
);
stream_log
.
str
(
""
);
init_logger
(
&
stream_log
,
logger
::
LogLevel
::
Debug
);
SPAM
<<
"Spam"
;
REQUIRE
(
stream_log
.
str
().
size
()
==
0
);
DEBUG
<<
"Debug"
;
#ifdef NDEBUG
REQUIRE
(
stream_log
.
str
().
size
()
==
0
);
#else
REQUIRE
(
stream_log
.
str
().
size
()
!=
0
);
#endif
stream_log
.
str
(
""
);
INFO
<<
"Info"
;
#ifdef NDEBUG
REQUIRE
(
stream_log
.
str
().
size
()
==
0
);
#else
REQUIRE
(
stream_log
.
str
().
size
()
!=
0
);
#endif
stream_log
.
str
(
""
);
WARNING
<<
"Warning"
;
REQUIRE
(
stream_log
.
str
().
size
()
!=
0
);
stream_log
.
str
(
""
);
ERROR
<<
"Error"
;
REQUIRE
(
stream_log
.
str
().
size
()
!=
0
);
stream_log
.
str
(
""
);
CRITICAL
<<
"Critical"
;
REQUIRE
(
stream_log
.
str
().
size
()
!=
0
);
stream_log
.
str
(
""
);
}
}
// Timer
// =======================
TEST_CASE
(
"Timer"
,
"[time],[CPU]"
)
{
SECTION
(
"Timer test"
)
{
Timer
timer
;
timer
.
stop
();
CHECK
(
timer
.
elapsed_time
()
>=
0.0
);
timer
.
start
();
timer
.
stop
();
CHECK
(
timer
.
elapsed_time
()
>=
0.0
);
CHECK
(
timer
.
get_stop
()
>=
timer
.
get_start
());
CHECK
(
timer
.
get_ctime_start
()
!=
nullptr
);
CHECK
(
timer
.
get_ctime_stop
()
!=
nullptr
);
}
}
// Average
// ====================
#define test_average(method, a, b, sol) \
CHECK(average<method>(a, b) == Approx(sol).epsilon(1e-10));
#define test_average_vector(method, vector, sol) \
CHECK(average<method>(vector) == Approx(sol).epsilon(1e-10));
TEST_CASE
(
"Average"
,
"[average],[maths]"
)
{
Vector
test_vector
(
4
);
test_vector
<<
1.0
,
2.0
,
3.0
,
4.0
;
SECTION
(
"Arithmetic average"
)
{
test_average
(
Average
::
arithmetic
,
1.0
,
1.0
,
1.0
);
test_average
(
Average
::
arithmetic
,
2.0
,
1.0
,
1.5
);
test_average
(
Average
::
arithmetic
,
-
1.0
,
1.0
,
0.0
);
test_average_vector
(
Average
::
arithmetic
,
test_vector
,
10.0
/
4
);
}
SECTION
(
"Harmonic average"
)
{
test_average
(
Average
::
harmonic
,
1.0
,
1.0
,
1.0
);
test_average
(
Average
::
harmonic
,
2.0
,
1.0
,
2.0
/
(
1
+
0.5
));
test_average_vector
(
Average
::
harmonic
,
test_vector
,
1.92
);
}
SECTION
(
"Geometric average"
)
{
test_average
(
Average
::
geometric
,
1.0
,
1.0
,
1.0
);
test_average
(
Average
::
geometric
,
1.0
,
2.0
,
std
::
sqrt
(
2.0
));
test_average_vector
(
Average
::
geometric
,
test_vector
,
std
::
pow
(
24.0
,
1.0
/
4.0
));
}
}
#undef test_average
#undef test_average_vector
// Moving Average
// =======================
TEST_CASE
(
"Moving average"
,
"[average],[timestep]"
)
{
SECTION
(
"Moving average test"
)
{
utils
::
ExponentialMovingAverage
moving_average
(
0.1
,
1.0
);
REQUIRE
(
moving_average
.
current_value
()
==
1.0
);
CHECK
(
moving_average
.
add_point
(
1.0
)
==
1.0
);
CHECK
(
moving_average
.
add_point
(
2.0
)
==
1.1
);
REQUIRE
(
moving_average
.
add_point
(
3.0
)
==
0.9
*
1.1
+
0.3
);
moving_average
.
reset
(
1.0
);
REQUIRE
(
moving_average
.
current_value
()
==
1.0
);
moving_average
.
set_alpha
(
0.2
);
REQUIRE
(
moving_average
.
add_point
(
2.0
)
==
Approx
(
0.8
+
0.4
));
}
}
// Performance handler
// =======================
struct
MockPerf
{
scalar_t
residuals
{
-
1
};
index_t
nb_iterations
{
-
1
};
};
class
MockSolverPerf
:
public
PerformanceHandler
<
MockPerf
>
{
public
:
MockSolverPerf
()
{}
void
do_stuff
()
{
get_perfs
().
residuals
=
1e-6
;
get_perfs
().
nb_iterations
=
10
;
}
void
reset_solver
()
{
reset_perfs
();
}
};
TEST_CASE
(
"PerformanceHandler"
,
"[performance],[base]"
)
{
SECTION
(
"Performance handler test"
)
{
auto
my_solver
=
MockSolverPerf
();
const
auto
&
perfs
=
my_solver
.
get_perfs
();
CHECK
(
perfs
.
nb_iterations
==
-
1
);
CHECK
(
perfs
.
residuals
==
-
1
);
my_solver
.
do_stuff
();
CHECK
(
perfs
.
nb_iterations
==
10
);
CHECK
(
perfs
.
residuals
==
1e-6
);
my_solver
.
reset_solver
();
CHECK
(
perfs
.
nb_iterations
==
-
1
);
CHECK
(
perfs
.
residuals
==
-
1
);
}
}
// Options handler
// =======================
struct
MockOptions
{
MockOptions
()
{}
MockOptions
(
scalar_t
res
,
index_t
max_iter
)
:
residuals
(
res
),
max_iterations
(
max_iter
)
{}
scalar_t
residuals
{
1e-6
};
index_t
max_iterations
{
100
};
};
class
MockSolverOptions
:
public
OptionsHandler
<
MockOptions
>
{
public
:
MockSolverOptions
()
{}
MockSolverOptions
(
scalar_t
res
,
index_t
max_iter
)
:
OptionsHandler
(
res
,
max_iter
)
{}
};
TEST_CASE
(
"Options handler"
,
"[options],[base]"
)
{
SECTION
(
"Options handler test"
)
{
auto
my_solver_default
=
MockSolverOptions
();
const
auto
&
ro_options
=
my_solver_default
.
get_options
();
CHECK
(
ro_options
.
max_iterations
==
100
);
CHECK
(
ro_options
.
residuals
==
1e-6
);
auto
&
rw_options
=
my_solver_default
.
get_options
();
rw_options
.
max_iterations
=
10
;
rw_options
.
residuals
=
1e-4
;
CHECK
(
ro_options
.
max_iterations
==
10
);
CHECK
(
ro_options
.
residuals
==
1e-4
);
}
SECTION
(
"Options handler - non default initialization"
)
{
auto
my_solver
=
MockSolverOptions
(
1e-4
,
10
);
const
auto
&
ro_options
=
my_solver
.
get_options
();
CHECK
(
ro_options
.
max_iterations
==
10
);
CHECK
(
ro_options
.
residuals
==
1e-4
);
}
}
// ScopeGuard
// ==========
static
void
will_fail
(
bool
&
hop
)
{
auto
guard
=
utils
::
make_scope_guard
([
&
hop
]{
hop
=
true
;});
throw
std
::
runtime_error
(
"fail on purpose"
);
guard
.
release
();
}
static
void
dont_fail
(
bool
&
hop
)
{
auto
guard
=
utils
::
make_scope_guard
([
&
hop
]{
hop
=
true
;});
hop
=
false
;
guard
.
release
();
}
TEST_CASE
(
"Scope guard"
,
"[utils]"
)
{
SECTION
(
"Catch error"
)
{
bool
hop
=
false
;
REQUIRE_THROWS_AS
(
will_fail
(
hop
),
std
::
runtime_error
);
CHECK
(
hop
==
true
);
dont_fail
(
hop
);
CHECK
(
hop
==
false
);
}
}
// pimpl_ptr
// =========
// simple Interface + Implementation to test pimpl_ptr
class
MockImplementation
{
public
:
MockImplementation
(
double
a
)
:
m_a
(
a
)
{}
double
add
(
double
b
)
const
{
return
m_a
+
b
;}
// Compilation should failed if this one is activated
//double add(double b) {return m_a + b;}
void
set
(
double
new_a
)
{
m_a
=
new_a
;}
private
:
double
m_a
;
};
class
MockInterface
{
public
:
MockInterface
(
double
a
)
:
m_impl
(
utils
::
make_pimpl
<
MockImplementation
>
(
a
))
{}
double
add
(
double
b
)
const
{
return
m_impl
->
add
(
b
);}
void
set
(
double
new_a
)
{
return
m_impl
->
set
(
new_a
);}
private
:
utils
::
pimpl_ptr
<
MockImplementation
>
m_impl
;
};
TEST_CASE
(
"pimpl_ptr"
,
"[utils],[pointer],[const]"
)
{
SECTION
(
"Test mock"
)
{
auto
hop
=
MockImplementation
(
1.0
);
CHECK
(
hop
.
add
(
2.0
)
==
Approx
(
3.0
));
hop
.
set
(
2.0
);
CHECK
(
hop
.
add
(
2.0
)
==
Approx
(
4.0
));
}
//SECTION("compilation fail") {
// const MockInterface fail1(2.0);
// fail1.set(3.0);
//}
}
// Cached Vector
//
TEST_CASE
(
"Cached vector"
,
"[utils],[container],[cache]"
)
{
SECTION
(
"Default"
)
{
utils
::
CachedVector
<
std
::
string
>
cached
;
cached
.
push_back
(
"value0"
);
cached
.
push_back
(
0
);
CHECK
(
cached
.
size
()
==
2
);
CHECK
(
cached
.
size_cache
()
==
1
);
CHECK
(
cached
[
0
]
==
"value0"
);
CHECK
(
cached
[
1
]
==
"value0"
);
for
(
auto
&
it:
cached
)
{
CHECK
(
it
==
"value0"
);
}
cached
.
emplace_back
(
"truc"
);
CHECK
(
cached
[
2
]
==
"truc"
);
cached
.
emplace_back
(
"other"
);
CHECK
(
cached
[
3
]
==
"other"
);
cached
.
push_back
(
2
);
CHECK
(
cached
.
at
(
4
)
==
"other"
);
CHECK
(
cached
.
size
()
==
5
);
CHECK
(
cached
.
size_cache
()
==
3
);
auto
&
new_val
=
cached
.
fork
(
1
);
new_val
=
"plop"
;
CHECK
(
cached
[
1
]
==
"plop"
);
for
(
auto
it
=
cached
.
begin_index
();
it
!=
cached
.
cend_index
();
++
it
)
{
CHECK
(
*
it
<
cached
.
size
());
CHECK
(
*
it
>=
0
);
}
//! it's possible, absolutely not a good idea
for
(
auto
&
value:
cached
)
{
value
=
"reinit"
;
}
CHECK
(
cached
[
2
]
==
"reinit"
);
}
SECTION
(
"Default constructor"
)
{
static_assert
(
std
::
is_default_constructible
<
std
::
string
>::
value
,
"String is default constructible"
);
utils
::
CachedVector
<
std
::
string
>
cached
(
5
);
CHECK
(
cached
[
4
]
==
""
);
}
}
// Named Cached Vector
TEST_CASE
(
"NamedCachedVector"
,
"[utils],[container],[cache]"
)
{
SECTION
(
"Default"
)
{
utils
::
NameCachedVector
<
std
::
string
>
cached
(
5
,
"default_name"
,
"default_value"
);
CHECK
(
cached
.
size_cache
()
==
1
);
CHECK
(
cached
.
size
()
==
5
);
CHECK
(
cached
.
get
(
"default_name"
)
==
"default_value"
);
auto
&
forked
=
cached
.
fork
(
2
,
"new name"
);
forked
=
"new value"
;
CHECK
(
cached
.
size_cache
()
==
2
);
CHECK
(
cached
.
size
()
==
5
);
CHECK
(
cached
[
2
]
==
"new value"
);
CHECK
(
cached
.
get
(
"new name"
)
==
"new value"
);
CHECK
(
cached
.
has_value
(
"new name"
));
CHECK
(
not
cached
.
has_value
(
"not a name"
));
cached
.
push_back_cache
(
"another name"
,
"another value"
);
CHECK
(
cached
.
get
(
"another name"
)
==
"another value"
);
CHECK
(
cached
.
size_cache
()
==
3
);
CHECK
(
cached
.
size
()
==
5
);
for
(
auto
&
value:
cached
)
{
CHECK
(
value
!=
"another value"
);
}
}
SECTION
(
"Default constructor"
)
{
static_assert
(
std
::
is_default_constructible
<
std
::
string
>::
value
,
"String is default constructible"
);
utils
::
NameCachedVector
<
std
::
string
>
cached
(
5
,
"default"
);
CHECK
(
cached
[
4
]
==
""
);
}
}
Event Timeline
Log In to Comment