Skip to content
Snippets Groups Projects
Unverified Commit 61dc5e07 authored by Walter Van Herck's avatar Walter Van Herck Committed by GitHub
Browse files

Merge pull request #347 from gpospelov/develop

Test refactoring
parents 17b2ff7f ae3444c3
No related branches found
No related tags found
No related merge requests found
Showing
with 169 additions and 10924 deletions
......@@ -42,7 +42,7 @@ test_script:
- echo %PYTHONPATH%
- echo %PYTHONHOME%
- ps: >-
ctest -LE Examples --output-on-failure
ctest -LE Fullcheck --output-on-failure
if (-not $?) {
......
......@@ -20,7 +20,7 @@ include(PreventInSourceBuilds)
project(BornAgain)
include(CTest) # equivalent to "enable_testing() ???
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -LE Examples) # => 'make check' is an alias for 'ctest'
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -LE Fullcheck) # => 'make check' is an alias for 'ctest'
add_custom_target(fullcheck COMMAND ${CMAKE_CTEST_COMMAND}) # => 'make check' is an alias for 'ctest'
include(VERSION.cmake)
......
......@@ -22,5 +22,5 @@ foreach(example ${examples})
set(test_name PyExamples/${script_name})
add_test(${test_name} ${PYTHON_EXECUTABLE} ${test_script} ${script_path})
set_tests_properties(${test_name} PROPERTIES LABELS "Examples")
set_tests_properties(${test_name} PROPERTIES LABELS "Fullcheck")
endforeach()
......@@ -30,5 +30,5 @@ ADD_GTEST(Core "ExportToPython" ${libs} 0)
ADD_GTEST(Core "Parameters" ${libs} 0)
ADD_GTEST(Core "DataStructure" ${libs} 0)
ADD_GTEST(Core "Other" ${libs} 0)
ADD_GTEST(Core "Numeric0" ${libs} 1)
ADD_GTEST(Core "Numeric1" ${libs} 1)
ADD_GTEST(Core "Numeric0" ${libs} 2)
ADD_GTEST(Core "Numeric1" ${libs} 2)
#include "google_test.h"
#include "MathConstants.h"
#include "BornAgainNamespace.h"
#include "HardParticles.h"
#include "qLoopedTest.h"
#include "FormFactorTest.h"
class FFSpecializationTest : public QLoopedTest
class FFSpecializationTest : public FormFactorTest
{
public:
void test_ff_eq(IFormFactorBorn* p0, IFormFactorBorn* p1, double eps=1e-12) {
complex_t f0 = p0->evaluate_for_q(q);
complex_t f1 = p1->evaluate_for_q(q);
protected:
~FFSpecializationTest();
void run_test(IFormFactorBorn* p0, IFormFactorBorn* p1, double eps, double qmag1, double qmag2)
{
test_all(qmag1, qmag2, [&](){test_ff_eq(p0, p1, eps);});
}
void test_ff_eq(IFormFactorBorn* p0, IFormFactorBorn* p1, double eps) {
complex_t f0 = p0->evaluate_for_q(m_q);
complex_t f1 = p1->evaluate_for_q(m_q);
double avge = (std::abs(f0) + std::abs(f1))/2;
//std::cout<<"q="<<q<<" -> "<<std::setprecision(16)<<" f0="<<f0<<", f1="<<f1<<"\n";
EXPECT_NEAR( real(f0), real(f1), eps*avge );
EXPECT_NEAR( imag(f0), imag(f1), eps*avge );
}
~FFSpecializationTest();
static double eps_polyh;
};
FFSpecializationTest::~FFSpecializationTest() = default;
double FFSpecializationTest::eps_polyh = 7.5e-13;
INSTANTIATE_TEST_CASE_P(
FFSpecializationTests,
FFSpecializationTest,
qlist);
//*********** polyhedra ***************
double eps_polyh = 7.5e-13;
TEST_P(FFSpecializationTest, TruncatedCubeAsBox)
TEST_F(FFSpecializationTest, TruncatedCubeAsBox)
{
if (skip_q(1e-99, 5e2))
return;
double L = .5;
const double L = .5;
FormFactorTruncatedCube p0(L, 0);
FormFactorBox p1(L, L, L);
test_ff_eq(&p0, &p1, eps_polyh);
run_test(&p0, &p1, eps_polyh, 1e-99, 5e2);
}
TEST_P(FFSpecializationTest, AnisoPyramidAsPyramid)
TEST_F(FFSpecializationTest, AnisoPyramidAsPyramid)
{
if (skip_q(1e-99, 5e3))
return;
double L = 1.5, H = .24, alpha = .6;
const double L = 1.5, H = .24, alpha = .6;
FormFactorAnisoPyramid p0(L, L, H, alpha);
FormFactorPyramid p1(L, H, alpha);
test_ff_eq(&p0, &p1, eps_polyh);
run_test(&p0, &p1, eps_polyh, 1e-99, 5e3);
}
TEST_P(FFSpecializationTest, Pyramid3AsPrism)
TEST_F(FFSpecializationTest, Pyramid3AsPrism)
{
if (skip_q(1e-99, 5e3))
return;
double L = 1.8, H = .3;
const double L = 1.8, H = .3;
FormFactorTetrahedron p0(L, H, M_PI / 2);
FormFactorPrism3 p1(L, H);
test_ff_eq(&p0, &p1, eps_polyh);
run_test(&p0, &p1, eps_polyh, 1e-99, 5e3);
}
TEST_P(FFSpecializationTest, PyramidAsBox)
TEST_F(FFSpecializationTest, PyramidAsBox)
{
if (skip_q(1e-99, 5e2))
return;
double L = 1.8, H = .3;
const double L = 1.8, H = .3;
FormFactorPyramid p0(L, H, M_PI / 2);
FormFactorBox p1(L, L, H);
test_ff_eq(&p0, &p1, eps_polyh);
run_test(&p0, &p1, eps_polyh, 1e-99, 5e2);
}
TEST_P(FFSpecializationTest, Cone6AsPrism)
TEST_F(FFSpecializationTest, Cone6AsPrism)
{
if (skip_q(1e-99, 5e2))
return;
double L = .8, H = 1.13;
const double L = .8, H = 1.13;
FormFactorCone6 p0(L, H, M_PI / 2);
FormFactorPrism6 p1(L, H);
test_ff_eq(&p0, &p1, eps_polyh);
run_test(&p0, &p1, eps_polyh, 1e-99, 5e2);
}
//*********** spheroids ***************
TEST_P(FFSpecializationTest, HemiEllipsoidAsTruncatedSphere)
TEST_F(FFSpecializationTest, HemiEllipsoidAsTruncatedSphere)
{
if (skip_q(1e-99, 5e2))
return;
double R = 1.07;
const double R = 1.07;
FormFactorHemiEllipsoid p0(R, R, R);
FormFactorTruncatedSphere p1(R, R);
test_ff_eq(&p0, &p1, 1e-10);
run_test(&p0, &p1, 1e-10, 1e-99, 5e2);
}
TEST_P(FFSpecializationTest, EllipsoidalCylinderAsCylinder)
TEST_F(FFSpecializationTest, EllipsoidalCylinderAsCylinder)
{
if (skip_q(1e-99, 5e3))
return;
double R = .8, H = 1.2;
const double R = .8, H = 1.2;
FormFactorEllipsoidalCylinder p0(R, R, H);
FormFactorCylinder p1(R, H);
test_ff_eq(&p0, &p1, 1e-11);
run_test(&p0, &p1, 1e-11, 1e-99, 5e3);
}
TEST_P(FFSpecializationTest, TruncatedSphereAsSphere)
TEST_F(FFSpecializationTest, TruncatedSphereAsSphere)
{
if (skip_q(.02, 5e1)) // WAITING #1416 improve/replace numeric integration
return;
double R = 1.;
const double R = 1.;
FormFactorTruncatedSphere p0(R, 2 * R);
FormFactorFullSphere p1(R);
test_ff_eq(&p0, &p1);
run_test(&p0, &p1, 1e-12, .02, 5e1);
}
#include "google_test.h"
#include "FormFactorTest.h"
#include "MathConstants.h"
#include "BornAgainNamespace.h"
#include "HardParticles.h"
#include "qLoopedTest.h"
#include <functional>
class FFSymmetryTest : public QLoopedTest
class FFSymmetryTest : public FormFactorTest
{
public:
~FFSymmetryTest();
void test_qq_eq( IFormFactorBorn* p, cvector_t q0, cvector_t q1, double eps=1e-12 ) {
complex_t f0 = p->evaluate_for_q(q0);
complex_t f1 = p->evaluate_for_q(q1);
using transform_t = std::function<cvector_t(const cvector_t&)>;
void run_test(IFormFactorBorn* p, transform_t fun, double eps, double qmag1, double qmag2)
{
test_all(qmag1, qmag2, [&](){test_qq_eq(p, fun, eps);});
}
void test_qq_eq( IFormFactorBorn* p, transform_t fun, double eps=1e-12 ) {
complex_t f0 = p->evaluate_for_q(m_q);
complex_t f1 = p->evaluate_for_q(fun(m_q));
double avge = (std::abs(f0) + std::abs(f1))/2;
EXPECT_NEAR( real(f0), real(f1), eps*avge );
EXPECT_NEAR( imag(f0), imag(f1), eps*avge );
}
cvector_t qt;
};
FFSymmetryTest::~FFSymmetryTest() = default;
INSTANTIATE_TEST_CASE_P(
FFSymmetryTests,
FFSymmetryTest,
qlist);
//*********** polyhedra ***************
TEST_P(FFSymmetryTest, Prism3)
TEST_F(FFSymmetryTest, Prism3)
{
if (skip_q(1e-99, 2e2))
return;
FormFactorPrism3 p(.83, .45);
test_qq_eq(&p, q, q.rotatedZ(M_TWOPI / 3));
run_test(&p, [](const cvector_t& q)->cvector_t{return q.rotatedZ(M_TWOPI / 3);},
1e-12, 1e-99, 2e2);
}
TEST_P(FFSymmetryTest, Prism6)
TEST_F(FFSymmetryTest, Prism6)
{
if (skip_q(1e-99, 2e3))
return;
FormFactorPrism6 p(1.33, .42);
test_qq_eq(&p, q, q.rotatedZ(M_PI / 3), 1e-12);
test_qq_eq(&p, q, q.rotatedZ(-M_TWOPI / 3), 3.8e-12);
run_test(&p, [](const cvector_t& q)->cvector_t{return q.rotatedZ(M_PI / 3);},
1e-12, 1e-99, 2e3);
run_test(&p, [](const cvector_t& q)->cvector_t{return q.rotatedZ(-M_TWOPI / 3);},
3.8e-12, 1e-99, 2e3);
}
TEST_P(FFSymmetryTest, Tetrahedron)
TEST_F(FFSymmetryTest, Tetrahedron)
{
if (skip_q(1e-99, 2e2))
return;
FormFactorTetrahedron p(8.43, .25, .53);
test_qq_eq(&p, q, q.rotatedZ(M_TWOPI / 3), 6e-12);
run_test(&p, [](const cvector_t& q)->cvector_t{return q.rotatedZ(M_TWOPI / 3);},
6e-12, 1e-99, 2e2);
// Linux: 3e-12, relaxed for Mac
}
TEST_P(FFSymmetryTest, Cone6_flat)
TEST_F(FFSymmetryTest, Cone6_flat)
{
if (skip_q(1e-99, 2e2)) // TODO for larger q, imag(ff) is nan
return;
// TODO for larger q, imag(ff) is nan
FormFactorCone6 p(4.3, .09, .1);
test_qq_eq(&p, q, q.rotatedZ(-M_PI / 3), 3.8e-12);
run_test(&p, [](const cvector_t& q)->cvector_t{return q.rotatedZ(-M_PI / 3);},
3.8e-12, 1e-99, 2e2);
}
TEST_P(FFSymmetryTest, Cone6_steep)
TEST_F(FFSymmetryTest, Cone6_steep)
{
if (skip_q(1e-99, 2e2)) // TODO for larger q, imag(ff) is nan
return;
FormFactorCone6 p(.23, 3.5, .999 * M_PI / 2);
test_qq_eq(&p, q, q.rotatedZ(-M_PI / 3), 2.5e-12);
run_test(&p, [](const cvector_t& q)->cvector_t{return q.rotatedZ(-M_PI / 3);},
2.5e-12, 1e-99, 2e2);
}
//*********** spheroids ***************
TEST_P(FFSymmetryTest, HemiEllipsoid)
TEST_F(FFSymmetryTest, HemiEllipsoid)
{
if (skip_q(1e-99, 2e2))
return;
FormFactorHemiEllipsoid p(.53, .78, 1.3);
test_qq_eq(&p, q, cvector_t(-q.x(), q.y(), q.z()));
test_qq_eq(&p, q, cvector_t(q.x(), -q.y(), q.z()));
run_test(&p, [](const cvector_t& q)->cvector_t{return cvector_t(-q.x(), q.y(), q.z());},
1e-12, 1e-99, 2e2);
run_test(&p, [](const cvector_t& q)->cvector_t{return cvector_t(q.x(), -q.y(), q.z());},
1e-12, 1e-99, 2e2);
}
TEST_P(FFSymmetryTest, TruncatedSphere)
TEST_F(FFSymmetryTest, TruncatedSphere)
{
if (skip_q(1e-99, 2e2))
return;
FormFactorTruncatedSphere p(.79, .34);
test_qq_eq(&p, q, q.rotatedZ(M_PI / 3.13698), 1e-10);
run_test(&p, [](const cvector_t& q)->cvector_t{return q.rotatedZ(M_PI / 3.13698);},
1e-10, 1e-99, 2e2);
}
// ****** TODO: tests that do not pass for the full q range *********
// To renew this file, run /G/ba/dev-tools/code-tools/update-gtestlist.py <directory>
#include "FormFactorSymmetryTest.h"
#ifndef ERRORSTREAMREDIRECT_H
#define ERRORSTREAMREDIRECT_H
#include <iostream>
struct ErrorStreamRedirect {
ErrorStreamRedirect( std::streambuf* new_buffer )
: old( std::cerr.rdbuf(new_buffer) )
{}
~ErrorStreamRedirect() {
std::cerr.rdbuf(old);
}
private:
std::streambuf* old;
};
#endif // ERRORSTREAMREDIRECT_H
// ************************************************************************** //
//
// BornAgain: simulate and fit scattering at grazing incidence
//
//! @file Tests/UnitTests/utilities/qLoopedTest.h
//! @brief Auxiliary utility to loop over q vectors for tests.
//!
//! @homepage http://bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2016
//! @authors Scientific Computing Group at MLZ Garching
//! @authors M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke
//
// ************************************************************************** //
#include "google_test.h"
#include "Vectors3D.h"
#include "Complex.h"
#include "gtest/internal/gtest-param-util.h"
#include "HardParticles.h"
#ifndef QLOOPEDTEST_H
#define QLOOPEDTEST_H
using ::testing::Values;
using ::testing::internal::ParamGenerator;
using ::testing::Combine;
#include <tuple>
namespace TestData{
const complex_t I(0,1);
class QLoopedTest:
public ::testing::TestWithParam<std::tuple<cvector_t, cvector_t, double, complex_t>>
{
protected:
QLoopedTest() {}
virtual void SetUp()
{
cvector_t qdir = std::get<0>(GetParam());
cvector_t qdev = std::get<1>(GetParam());
double qmag = std::get<2>(GetParam());
complex_t qeps = std::get<3>(GetParam());
q = qmag * (qdir + qeps*qdev).unit();
}
cvector_t q;
bool skip_q( double qmag_begin=1e-99, double qmag_end=1e99 ) {
return q.mag()<=qmag_begin || q.mag()>=qmag_end;
}
};
auto qlist = testing::Combine(
testing::Values(
cvector_t({ 1, 0, 0 }),
......@@ -70,4 +42,36 @@ auto qlist = testing::Combine(
.9, -.99, .999, -.9999 )
);
#endif // QLOOPEDTEST_H
}
class FormFactorTest : public ::testing::Test
{
protected:
~FormFactorTest();
template<typename T>
void test_all(double qmag1, double qmag2, T fun) {
for (auto it : gen) {
cvector_t qdir = std::get<0>(it);
cvector_t qdev = std::get<1>(it);
double qmag = std::get<2>(it);
complex_t qeps = std::get<3>(it);
m_q = qmag * (qdir + qeps*qdev).unit();
if (skip_q(qmag1, qmag2))
continue;
fun();
}
}
bool skip_q( double qmag_begin=1e-99, double qmag_end=1e99 ) {
return m_q.mag()<=qmag_begin || m_q.mag()>=qmag_end;
}
cvector_t m_q;
static ParamGenerator<std::tuple<cvector_t, cvector_t, double, complex_t>> gen;
};
FormFactorTest::~FormFactorTest() = default;
ParamGenerator<std::tuple<cvector_t, cvector_t, double, complex_t>> FormFactorTest::gen = TestData::qlist;
#include "google_test.h"
#include "testlist.h"
#include "ErrorStreamRedirect.h"
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
// redirect std::cerr stream
std::stringstream oss;
ErrorStreamRedirect redirecter( oss.rdbuf() );
(void)redirecter;
// run all google tests
return RUN_ALL_TESTS();
}
This copy of gtest-1.8.0 is patched at the following places:
- src/gtest.cc (compare gtest.cc.orig)
......@@ -4,4 +4,3 @@ website https://github.com/google/googletest/releases
downloaded https://github.com/google/googletest/archive/release-1.8.0.tar.gz
unpacked -> googletest-release-1.8.0
moved subdirectory googletest -> ThirdParty/common/gtest/gtest-1.8.0
manually patched as described in file 00_PATCHES
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
......@@ -31,6 +31,10 @@ MACRO(ADD_GTEST project subdir libs stage)
elseif(${stage} EQUAL 1)
# Put test under control of CTest
add_test(${TEST_NAME} ${EXE})
elseif(${stage} EQUAL 2)
# Put test under control of CTest in "fullcheck" section
add_test(${TEST_NAME} ${EXE})
set_tests_properties(${TEST_NAME} PROPERTIES LABELS "Fullcheck")
else()
message(FATAL_ERROR "invalid parameter stage=${stage} in ADD_GTEST")
endif()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment