Commit b4a5b734 by András Bodor

memtrace/gtest_lite frissítés

parent 3c4fc9f2
...@@ -2,14 +2,17 @@ ...@@ -2,14 +2,17 @@
#define GTEST_LITE_H #define GTEST_LITE_H
/** /**
* \file gtest_lite.h (v3/2019) * \file gtest_lite.h (v4/2022)
* *
* Google gtest keretrendszerhez hasonló rendszer. * Google gtest keretrendszerhez hasonló rendszer.
* Sz.I. 2015., 2016., 2017. (_Has_X) * Sz.I. 2015., 2016., 2017. (_Has_X)
* Sz.I. 2018 (template), ENDM, ENDMsg, nullptr_t * Sz.I. 2018 (template), ENDM, ENDMsg, nullptr_t
* Sz.I. 2019 singleton * Sz.I. 2019 singleton
* Sz.I. 2021 ASSERT.., STRCASE... * Sz.I. 2021 ASSERT.., STRCASE...
* Sz.I. 2021 EXPEXT_REGEXP * Sz.I. 2021 EXPEXT_REGEXP, CREATE_Has_fn_, cmp w. NULL, EXPECT_ param fix
* V.B., Sz.I. 2022 almostEQ fix,
* Sz.I. 2022. EXPECT_THROW fix
* B.A. 2025. unused-variable fixek (memtrace nélkül, EXPECT_THROW)
* *
* A tesztelés legalapvetőbb funkcióit támogató függvények és makrók. * A tesztelés legalapvetőbb funkcióit támogató függvények és makrók.
* Nem szálbiztos megvalósítás. * Nem szálbiztos megvalósítás.
...@@ -135,7 +138,7 @@ ...@@ -135,7 +138,7 @@
/// Kivételt várunk /// Kivételt várunk
#define EXPECT_THROW(statement, exception_type) try { gtest_lite::test.tmp = false; statement; } \ #define EXPECT_THROW(statement, exception_type) try { gtest_lite::test.tmp = false; statement; } \
catch (exception_type) { gtest_lite::test.tmp = true; } \ catch (exception_type &) { gtest_lite::test.tmp = true; } \
catch (...) { } \ catch (...) { } \
EXPECTTHROW(statement, "kivetelt dob.", "nem dobott '"#exception_type"' kivetelt.") EXPECTTHROW(statement, "kivetelt dob.", "nem dobott '"#exception_type"' kivetelt.")
...@@ -156,7 +159,7 @@ ...@@ -156,7 +159,7 @@
/// Kivételt várunk és továbbdobjuk -- ilyen nincs a gtest-ben /// Kivételt várunk és továbbdobjuk -- ilyen nincs a gtest-ben
#define EXPECT_THROW_THROW(statement, exception_type) try { gtest_lite::test.tmp = false; statement; } \ #define EXPECT_THROW_THROW(statement, exception_type) try { gtest_lite::test.tmp = false; statement; } \
catch (exception_type) { gtest_lite::test.tmp = true; throw; } \ catch (exception_type &) { gtest_lite::test.tmp = true; throw; } \
EXPECTTHROW(statement, "kivetelt dob.", "nem dobott '"#exception_type"' kivetelt.") EXPECTTHROW(statement, "kivetelt dob.", "nem dobott '"#exception_type"' kivetelt.")
/// Környezeti változóhoz hasonlít -- ilyen nincs a gtest-ben /// Környezeti változóhoz hasonlít -- ilyen nincs a gtest-ben
...@@ -187,7 +190,7 @@ ...@@ -187,7 +190,7 @@
/// https://cpptalk.wordpress.com/2009/09/12/substitution-failure-is-not-an-error-2 /// https://cpptalk.wordpress.com/2009/09/12/substitution-failure-is-not-an-error-2
/// Használat: /// Használat:
/// CREATE_Has_(size) /// CREATE_Has_(size)
/// ... if (Has_size<std::string>::member)... /// ... if (_Has_size<std::string>::member)...
#define CREATE_Has_(X) \ #define CREATE_Has_(X) \
template<typename T> struct _Has_##X { \ template<typename T> struct _Has_##X { \
struct Fallback { int X; }; \ struct Fallback { int X; }; \
...@@ -198,6 +201,14 @@ template<typename T> struct _Has_##X { \ ...@@ -198,6 +201,14 @@ template<typename T> struct _Has_##X { \
static bool const member = sizeof(f<Derived>(0)) == 2; \ static bool const member = sizeof(f<Derived>(0)) == 2; \
}; };
#define CREATE_Has_fn_(X, S) \
template<typename R, typename T> struct _Has_fn_##X##_##S { \
template<typename C, R (C::*f)() S> struct ChT; \
template<typename D> static char (&f(ChT<D, &D::X>*))[1]; \
template<typename D> static char (&f(...))[2]; \
static bool const fn = sizeof(f<T>(0)) == 1; \
};
/// Segédfüggvény egy publikus adattag, vagy tagfüggvény létezésének tesztelésére /// Segédfüggvény egy publikus adattag, vagy tagfüggvény létezésének tesztelésére
/// fordítási időben /// fordítási időben
inline void hasMember(...) {} inline void hasMember(...) {}
...@@ -256,12 +267,13 @@ struct Test { ...@@ -256,12 +267,13 @@ struct Test {
bool tmp; ///< temp a kivételkezeléshez; bool tmp; ///< temp a kivételkezeléshez;
std::string name; ///< éppen futó teszt neve std::string name; ///< éppen futó teszt neve
std::fstream null; ///< nyelő, ha nem kell kiírni semmit std::fstream null; ///< nyelő, ha nem kell kiírni semmit
std::ostream& os; ///< ide írunk
static Test& getTest() { static Test& getTest() {
static Test instance;///< egyedüli (singleton) példány static Test instance;///< egyedüli (singleton) példány
return instance; return instance;
} }
private: /// singleton minta miatt private: /// singleton minta miatt
Test() :sum(0), failed(0), status(false), null("/dev/null") {} Test() :sum(0), failed(0), status(false), null("/dev/null"), os(std::cout) {}
Test(const Test&); Test(const Test&);
void operator=(const Test&); void operator=(const Test&);
public: public:
...@@ -271,25 +283,25 @@ public: ...@@ -271,25 +283,25 @@ public:
#ifdef MEMTRACE #ifdef MEMTRACE
ablocks = memtrace::allocated_blocks(); ablocks = memtrace::allocated_blocks();
#endif #endif
#ifndef CPORTA os << "\n---> " << name << std::endl;
std::cerr << "\n---> " << name << std::endl;
#endif // CPORTA
++sum; ++sum;
} }
/// Teszt vége /// Teszt vége
std::ostream& end(bool memchk = false) { std::ostream& end(bool memchk = false) {
(void) memchk; // Elkerülni az unused-variable warningot, ha nincs memtrace
#ifdef MEMTRACE #ifdef MEMTRACE
if (memchk && ablocks != memtrace::allocated_blocks()) { if (memchk && ablocks != memtrace::allocated_blocks()) {
status = false; status = false;
return std::cerr << "** Lehet, hogy nem szabaditott fel minden memoriat! **" << std::endl; return os << "** Lehet, hogy nem szabaditott fel minden memoriat! **" << std::endl;
} }
#endif #endif
os << (status ? " SIKERES" : "** HIBAS ****") << "\t" << name << " <---" << std::endl;
#ifdef CPORTA #ifdef CPORTA
if (!status) if (!status)
#endif // CPORTA
std::cerr << (status ? " SIKERES" : "** HIBAS ****") << "\t" << name << " <---" << std::endl; std::cerr << (status ? " SIKERES" : "** HIBAS ****") << "\t" << name << " <---" << std::endl;
#endif // CPORTA
if (!status) if (!status)
return std::cerr; return os;
else else
return null; return null;
} }
...@@ -309,17 +321,20 @@ public: ...@@ -309,17 +321,20 @@ public:
size_t i = str.rfind("\\"); size_t i = str.rfind("\\");
if (i == std::string::npos) i = str.rfind("/"); if (i == std::string::npos) i = str.rfind("/");
if (i == std::string::npos) i = 0; else i++; if (i == std::string::npos) i = 0; else i++;
return std::cerr << "\n**** " << &file[i] << "(" << line << "): " << expr << " ****" << std::endl; return os << "\n**** " << &file[i] << "(" << line << "): " << expr << " ****" << std::endl;
} }
return null; return null;
} }
/// Destruktor /// Destruktor
~Test() { ~Test() {
if (sum != 0) {
os << "\n==== TESZT VEGE ==== HIBAS/OSSZES: " << failed << "/" << sum << std::endl;
#ifdef CPORTA #ifdef CPORTA
if (failed) if (failed)
std::cerr << "\n==== TESZT VEGE ==== HIBAS/OSSZES: " << failed << "/" << sum << std::endl;
#endif // CPORTA #endif // CPORTA
std::cerr << "\n==== TESZT VEGE ==== HIBAS/OSSZES: " << failed << "/" << sum << std::endl; }
} }
}; };
...@@ -329,7 +344,7 @@ static Test& test = Test::getTest(); ...@@ -329,7 +344,7 @@ static Test& test = Test::getTest();
/// általános sablon a várt értékhez. /// általános sablon a várt értékhez.
template <typename T1, typename T2> template <typename T1, typename T2>
std::ostream& EXPECT_(T1 exp, T2 act, bool (*pred)(T1, T2), const char *file, int line, std::ostream& EXPECT_(T1 exp, T2 act, bool (*pred)(T1, T1), const char *file, int line,
const char *expr, const char *lhs = "elvart", const char *rhs = "aktual") { const char *expr, const char *lhs = "elvart", const char *rhs = "aktual") {
return test.expect(pred(exp, act), file, line, expr) return test.expect(pred(exp, act), file, line, expr)
<< "** " << lhs << ": " << std::boolalpha << exp << "** " << lhs << ": " << std::boolalpha << exp
...@@ -338,7 +353,7 @@ std::ostream& EXPECT_(T1 exp, T2 act, bool (*pred)(T1, T2), const char *file, in ...@@ -338,7 +353,7 @@ std::ostream& EXPECT_(T1 exp, T2 act, bool (*pred)(T1, T2), const char *file, in
/// pointerre specializált sablon a várt értékhez. /// pointerre specializált sablon a várt értékhez.
template <typename T1, typename T2> template <typename T1, typename T2>
std::ostream& EXPECT_(T1* exp, T2* act, bool (*pred)(T1*, T2*), const char *file, int line, std::ostream& EXPECT_(T1* exp, T2* act, bool (*pred)(T1*, T1*), const char *file, int line,
const char *expr, const char *lhs = "elvart", const char *rhs = "aktual") { const char *expr, const char *lhs = "elvart", const char *rhs = "aktual") {
return test.expect(pred(exp, act), file, line, expr) return test.expect(pred(exp, act), file, line, expr)
<< "** " << lhs << ": " << (void*) exp << "** " << lhs << ": " << (void*) exp
...@@ -347,8 +362,16 @@ std::ostream& EXPECT_(T1* exp, T2* act, bool (*pred)(T1*, T2*), const char *file ...@@ -347,8 +362,16 @@ std::ostream& EXPECT_(T1* exp, T2* act, bool (*pred)(T1*, T2*), const char *file
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
/// nullptr-re specializált sablon a várt értékhez. /// nullptr-re specializált sablon a várt értékhez.
template <typename T1> template <typename T>
std::ostream& EXPECT_(T1* exp, std::nullptr_t act, bool (*pred)(T1*, std::nullptr_t), const char *file, int line, std::ostream& EXPECT_(std::nullptr_t exp, T* act, bool (*pred)(T*, T*), const char *file, int line,
const char *expr, const char *lhs = "elvart", const char *rhs = "aktual") {
return test.expect(pred(exp, act), file, line, expr)
<< "** " << lhs << ": " << (void*) exp
<< "\n** " << rhs << ": " << (void*) act << std::endl;
}
template <typename T>
std::ostream& EXPECT_(T* exp, std::nullptr_t act, bool (*pred)(T*, T*), const char *file, int line,
const char *expr, const char *lhs = "elvart", const char *rhs = "aktual") { const char *expr, const char *lhs = "elvart", const char *rhs = "aktual") {
return test.expect(pred(exp, act), file, line, expr) return test.expect(pred(exp, act), file, line, expr)
<< "** " << lhs << ": " << (void*) exp << "** " << lhs << ": " << (void*) exp
...@@ -387,14 +410,12 @@ std::ostream& EXPECTREGEXP(E exp, S str, int match, const char *err, const char ...@@ -387,14 +410,12 @@ std::ostream& EXPECTREGEXP(E exp, S str, int match, const char *err, const char
<< "\n** " << rhs << ": " << (err == NULL ? std::string("\"") + str + std::string("\"") : err) << "\n** " << rhs << ": " << (err == NULL ? std::string("\"") + str + std::string("\"") : err)
<< "\n** " << m << ": " << match << "/" << cnt << std::endl; << "\n** " << m << ": " << match << "/" << cnt << std::endl;
} }
#else
#error "EXPEXTREGEXP requires compiler and library support for the ISO C++ 2011 standard."
#endif #endif
/// segéd sablonok a relációkhoz. /// segéd sablonok a relációkhoz.
/// azért nem STL (algorithm), mert csak a függvény lehet, hogy menjen a deduckció /// azért nem STL (algorithm), mert csak a függvény lehet, hogy menjen a deduckció
template <typename T1, typename T2> template <typename T>
bool eq(T1 a, T2 b) { return a == b; } bool eq(T a, T b) { return a == b; }
inline inline
bool eqstr(const char *a, const char *b) { bool eqstr(const char *a, const char *b) {
...@@ -416,8 +437,8 @@ bool eqstrcase(const char *a, const char *b) { ...@@ -416,8 +437,8 @@ bool eqstrcase(const char *a, const char *b) {
} }
template <typename T1, typename T2> template <typename T>
bool ne(T1 a, T2 b) { return a != b; } bool ne(T a, T b) { return a != b; }
inline inline
bool nestr(const char *a, const char *b) { bool nestr(const char *a, const char *b) {
...@@ -426,17 +447,17 @@ bool nestr(const char *a, const char *b) { ...@@ -426,17 +447,17 @@ bool nestr(const char *a, const char *b) {
return false; return false;
} }
template <typename T1, typename T2> template <typename T>
bool le(T1 a, T2 b) { return a <= b; } bool le(T a, T b) { return a <= b; }
template <typename T1, typename T2> template <typename T>
bool lt(T1 a, T2 b) { return a < b; } bool lt(T a, T b) { return a < b; }
template <typename T1, typename T2> template <typename T>
bool ge(T1 a, T2 b) { return a >= b; } bool ge(T a, T b) { return a >= b; }
template <typename T1, typename T2> template <typename T>
bool gt(T1 a, T2 b) { return a > b; } bool gt(T a, T b) { return a > b; }
/// Segédsablon valós számok összehasonlításához /// Segédsablon valós számok összehasonlításához
/// Nem bombabiztos, de nekünk most jó lesz /// Nem bombabiztos, de nekünk most jó lesz
...@@ -446,18 +467,29 @@ template <typename T> ...@@ -446,18 +467,29 @@ template <typename T>
bool almostEQ(T a, T b) { bool almostEQ(T a, T b) {
// eps: ha a relatív, vagy abszolút hiba ettől kisebb, akkor elfogadjuk // eps: ha a relatív, vagy abszolút hiba ettől kisebb, akkor elfogadjuk
T eps = 10 * std::numeric_limits<T>::epsilon(); // 10-szer a legkisebb érték T eps = 10 * std::numeric_limits<T>::epsilon(); // 10-szer a legkisebb érték
if (a == b) return true; T diff = fabs(a - b);
if (fabs(a - b) < eps) if (diff < eps)
return true; return true;
double aa = fabs(a); T aa = fabs(a);
double ba = fabs(b); T ba = fabs(b);
if (aa < ba) { if (aa < ba) {
aa = ba; aa = ba;
ba = fabs(a); ba = fabs(a);
} }
return (aa - ba) < aa * eps; return diff < aa * eps;
} }
/// Segédsablon ostream átirányításához
/// A destruktor visszaállít
class ostreamRedir {
std::ostream& src;
std::streambuf *const save;
public:
ostreamRedir(std::ostream& src, std::ostream& dst)
: src(src), save(src.rdbuf(dst.rdbuf())) {}
~ostreamRedir() { src.rdbuf(save); }
};
} // namespace gtest_lite } // namespace gtest_lite
#endif // GTEST_LITE_H #endif // GTEST_LITE_H
...@@ -5,8 +5,9 @@ Keszitette: Peregi Tamas, BME IIT, 2011 ...@@ -5,8 +5,9 @@ Keszitette: Peregi Tamas, BME IIT, 2011
Kanari: Szeberenyi Imre, 2013. Kanari: Szeberenyi Imre, 2013.
VS 2012: Szeberényi Imre, 2015., VS 2012: Szeberényi Imre, 2015.,
mem_dump: 2016. mem_dump: 2016.
meset felszabaditaskor: 2018. memset felszabaditaskor: 2018.
typo: 2019. typo: 2019.
poi_check: 2021.
*********************************/ *********************************/
/*definialni kell, ha nem paracssorbol allitjuk be (-DMEMTRACE) */ /*definialni kell, ha nem paracssorbol allitjuk be (-DMEMTRACE) */
...@@ -178,7 +179,6 @@ START_NAMESPACE ...@@ -178,7 +179,6 @@ START_NAMESPACE
dying = TRUE; dying = TRUE;
exit(120); exit(120);
} }
static void initialize(); static void initialize();
END_NAMESPACE END_NAMESPACE
...@@ -188,6 +188,7 @@ END_NAMESPACE ...@@ -188,6 +188,7 @@ END_NAMESPACE
#ifdef MEMTRACE_TO_MEMORY #ifdef MEMTRACE_TO_MEMORY
START_NAMESPACE START_NAMESPACE
typedef struct _registry_item { typedef struct _registry_item {
void * p; /* mem pointer*/ void * p; /* mem pointer*/
size_t size; /* size*/ size_t size; /* size*/
...@@ -197,6 +198,12 @@ START_NAMESPACE ...@@ -197,6 +198,12 @@ START_NAMESPACE
static registry_item registry; /*sentinel*/ static registry_item registry; /*sentinel*/
static registry_item *find_registry_item(void * p) {
registry_item *n = &registry;
for(; n->next && n->next->p != p ; n=n->next);
return n;
}
static void print_registry_item(registry_item * p) { static void print_registry_item(registry_item * p) {
if (p) { if (p) {
print_registry_item(p->next); print_registry_item(p->next);
...@@ -225,6 +232,13 @@ START_NAMESPACE ...@@ -225,6 +232,13 @@ START_NAMESPACE
} }
return 0; return 0;
} }
/* Ellenorzi, hogy a pointer regisztralt-e. Ha nem, akkor 0-val tér vissza */
int poi_check(void *pu) {
if (pu == NULL) return 1;
initialize();
return find_registry_item(P(pu))->next != NULL;
}
END_NAMESPACE END_NAMESPACE
#endif/*MEMTRACE_TO_MEMORY*/ #endif/*MEMTRACE_TO_MEMORY*/
...@@ -271,14 +285,6 @@ START_NAMESPACE ...@@ -271,14 +285,6 @@ START_NAMESPACE
return TRUE; return TRUE;
} }
#ifdef MEMTRACE_TO_MEMORY
static registry_item *find_registry_item(void * p) {
registry_item *n = &registry;
for(; n->next && n->next->p != p ; n=n->next);
return n;
}
#endif
static void unregister_memory(void * p, call_t call) { static void unregister_memory(void * p, call_t call) {
initialize(); initialize();
#ifdef MEMTRACE_TO_FILE #ifdef MEMTRACE_TO_FILE
......
...@@ -5,7 +5,8 @@ Keszitette: Peregi Tamas, BME IIT, 2011 ...@@ -5,7 +5,8 @@ Keszitette: Peregi Tamas, BME IIT, 2011
Kanari: Szeberenyi Imre, 2013., Kanari: Szeberenyi Imre, 2013.,
VS 2012: Szeberényi Imre, 2015., VS 2012: Szeberényi Imre, 2015.,
mem_dump: 2016. mem_dump: 2016.
inclue-ok: 2017., 2018., 2019., 2021. inclue-ok: 2017., 2018., 2019., 2021., 2022.
clang-mágia:Bodor András, 2025
*********************************/ *********************************/
#ifndef MEMTRACE_H #ifndef MEMTRACE_H
...@@ -101,7 +102,8 @@ END_NAMESPACE ...@@ -101,7 +102,8 @@ END_NAMESPACE
#if defined(MEMTRACE_TO_MEMORY) #if defined(MEMTRACE_TO_MEMORY)
START_NAMESPACE START_NAMESPACE
int mem_check(void); int mem_check(void);
int poi_check(void*);
END_NAMESPACE END_NAMESPACE
#endif #endif
...@@ -160,6 +162,11 @@ END_NAMESPACE ...@@ -160,6 +162,11 @@ END_NAMESPACE
#include <ostream> #include <ostream>
#include <stdexcept> #include <stdexcept>
#include <ctime> #include <ctime>
#include <random>
#if __cplusplus >= 201103L
#include <iterator>
#include <regex>
#endif
#endif #endif
#ifdef MEMTRACE_CPP #ifdef MEMTRACE_CPP
namespace std { namespace std {
...@@ -187,7 +194,6 @@ START_NAMESPACE ...@@ -187,7 +194,6 @@ START_NAMESPACE
void mem_dump(void const *mem, size_t size, FILE* fp = stdout); void mem_dump(void const *mem, size_t size, FILE* fp = stdout);
END_NAMESPACE END_NAMESPACE
#endif/*MEMTRACE_C*/ #endif/*MEMTRACE_C*/
...@@ -217,6 +223,16 @@ void operator delete[](void * p, size_t) THROW_NOTHING; ...@@ -217,6 +223,16 @@ void operator delete[](void * p, size_t) THROW_NOTHING;
void operator delete(void *p, int, const char *) THROW_NOTHING; void operator delete(void *p, int, const char *) THROW_NOTHING;
void operator delete[](void *p, int, const char *) THROW_NOTHING; void operator delete[](void *p, int, const char *) THROW_NOTHING;
// clang >= 3.1 esetén vannak warningok, amiket zavar, hogy redefiniálva van a new/delete
#if defined(__clang__) && (__clang_major__ > 3 || \
(__clang_major__ == 3 && __clang_minor__ > 0))
// Csak nagyon drasztikus warning szint mellet jön elő, amikor van rekurzívnak tűnő makró.
// Ilyenek a new és delete alább, hiszen olyan, mintha magukat hívnák, pedig nincs (ilyen)
// rekurzió makró szinten.
# pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
// Bármilyen kulcsszó újradefiniálása esetén pánikol.
# pragma clang diagnostic ignored "-Wkeyword-macro"
#endif
#define new new(__LINE__, __FILE__) #define new new(__LINE__, __FILE__)
#define delete memtrace::set_delete_call(__LINE__, __FILE__),delete #define delete memtrace::set_delete_call(__LINE__, __FILE__),delete
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment