Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Prog2
/
labor_peldak
/
lab_02
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
A prog2-höz tartozó friss repo anyagok itt elérhetőek:
https://git.iit.bme.hu/
Commit
9906d9c2
authored
Jul 01, 2025
by
András Bodor
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
friss gtest_lite
Új gtest_lite verzió.
parent
0d829d13
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
489 additions
and
125 deletions
+489
-125
string1/gtest_lite.h
+319
-79
string2_cpp/gtest_lite.h
+170
-46
No files found.
string1/gtest_lite.h
View file @
9906d9c2
#
ifndef
GTEST_LITE_H
#ifndef GTEST_LITE_H
#define GTEST_LITE_H
#define GTEST_LITE_H
/**
/**
* \file gtest_lite.h
* \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. 2019 singleton
* Sz.I. 2021 ASSERT.., STRCASE...
* 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.
*
*
* Szabadon felhasználható, bővíthető.
* Szabadon felhasználható, bővíthető.
*
*
* Használati példa:
* Használati példa:
...
@@ -22,6 +31,14 @@
...
@@ -22,6 +31,14 @@
* ...
* ...
* END
* END
* ...
* ...
* // Fatális hiba esetén a teszteset nem fut tovább. Ezek az ASSERT... makrók.
* // Nem lehet a kiírásukhoz további üzenetet fűzni. PL:
* TEST(TeszEsetNeve, TesztNeve)
* ASSERT_NO_THROW(f(0)); // itt nem lehet << "duma"
* EXPECT_EQ(4, f(2)) << "A függvény hibás eredményt adott" << std::endl;
* ...
* END
* ...
*
*
* A működés részleteinek megértése szorgalmi feladat.
* A működés részleteinek megértése szorgalmi feladat.
*/
*/
...
@@ -31,79 +48,151 @@
...
@@ -31,79 +48,151 @@
#include <cmath>
#include <cmath>
#include <cstring>
#include <cstring>
#include <limits>
#include <limits>
#include <cstdlib>
#include <string>
#include <string>
#include <fstream>
#include <fstream>
#if __cplusplus >= 201103L
# include <iterator>
# include <regex>
#endif
#ifdef MEMTRACE
#ifdef MEMTRACE
#include "memtrace.h"
#
include "memtrace.h"
#endif
#endif
// Két makró az egyes tesztek elé és mögé:
// Két makró az egyes tesztek elé és mögé:
// A két makró a kapcsos zárójelekkel egy új blokkot hoz létre, amiben
// A két makró a kapcsos zárójelekkel egy új blokkot hoz létre, amiben
// a nevek lokálisak, így elkerülhető a névütközés.
// a nevek lokálisak, így elkerülhető a névütközés.
/// Teszt kezdete. A makró paraméterezése hasonlít a gtest
/// Teszt kezdete. A makró paraméterezése hasonlít a gtest
/// paraméterezéséhez. Így az itt elkészített testek könnyen átemelhetők
/// paraméterezéséhez. Így az itt elkészített testek könnyen átemelhetők
/// a gtest keretrendszerbe.
/// a gtest keretrendszerbe.
/// @param C - teszteset neve (csak a gtest kompatibilitás miatt van külön neve az eseteknek)
/// @param C - teszteset neve (csak a gtest kompatibilitás miatt van külön neve az eseteknek)
/// @param N - teszt neve
/// @param N - teszt neve
#define TEST(C, N) { gtest_lite::test.begin(#C"."#N);
#define TEST(C, N)
do
{ gtest_lite::test.begin(#C"."#N);
/// Teszteset vége.
/// Teszteset vége.
#define END gtest_lite::test.end(); }
#define END gtest_lite::test.end(); } while (false);
/// Teszteset vége allokált blokkok számának összehasonlításával
/// Ez az ellenőrzés nem bomba biztos.
#define ENDM gtest_lite::test.end(true); } while (false);
/// Teszteset vége allokált blokkok számának összehasonlításával
/// Ez az ellenőrzés nem bomba biztos.
/// Ha hiba van kiírja az üzenetet.
#define ENDMsg(t) gtest_lite::test.end(true) << t << std::endl; } while (false);
// Eredmények vizsgálatát segítő makrók.
// Eredmények vizsgálatát segítő makrók.
// A paraméterek és a funkciók a gtest keretrendszerrel megegyeznek.
// A paraméterek és a funkciók a gtest keretrendszerrel megegyeznek.
/// Sikeres teszt makrója
/// Sikeres teszt makrója
#define SUCCEED() gtest_lite::test.tstatus(true, __FILE__, __LINE__)
#define SUCCEED() gtest_lite::test.expect(true, __FILE__, __LINE__, "SUCCEED()", true)
/// Sikertelen teszt fatális hiba makrója
#define FAIL() gtest_lite::test.expect(false, __FILE__, __LINE__, "FAIL()", true)
/// Sikertelen teszt makrója
/// Sikertelen teszt makrója
#define
FAIL() gtest_lite::test.tstatus(false, __FILE__, __LINE__
)
#define
ADD_FAILURE() gtest_lite::test.expect(false, __FILE__, __LINE__, "ADD_FAILURE()", true
)
/// Azonosságot elváró makró
/// Azonosságot elváró makró
#define EXPECT_EQ(expected, actual)
EXPECTCMP((expected) == (actual), expected, actual
)
#define EXPECT_EQ(expected, actual)
gtest_lite::EXPECT_(expected, actual, gtest_lite::eq, __FILE__, __LINE__, "EXPECT_EQ(" #expected ", " #actual ")"
)
/// Eltérést elváró makró
/// Eltérést elváró makró
#define EXPECT_NE(expected, actual) EXPECTNE((expected) != (actual), expected, actual)
#define EXPECT_NE(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::ne, __FILE__, __LINE__, "EXPECT_NE(" #expected ", " #actual ")", "etalon" )
/// Kisebb, vagy egyenlő relációt elváró makró
#define EXPECT_LE(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::le, __FILE__, __LINE__, "EXPECT_LE(" #expected ", " #actual ")", "etalon" )
/// Kisebb, mint relációt elváró makró
#define EXPECT_LT(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::lt, __FILE__, __LINE__, "EXPECT_LT(" #expected ", " #actual ")", "etalon" )
/// Nagyobb, vagy egyenlő relációt elváró makró
#define EXPECT_GE(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::ge, __FILE__, __LINE__, "EXPECT_GE(" #expected ", " #actual ")", "etalon" )
/// Nagyobb, mint relációt elváró makró
#define EXPECT_GT(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::gt, __FILE__, __LINE__, "EXPECT_GT(" #expected ", " #actual ")", "etalon" )
/// Igaz értéket elváró makró
/// Igaz értéket elváró makró
#define EXPECT_TRUE(actual)
EXPECTCMP(actual, "true", actual
)
#define EXPECT_TRUE(actual)
gtest_lite::EXPECT_(true, actual, gtest_lite::eq, __FILE__, __LINE__, "EXPECT_TRUE(" #actual ")"
)
/// Hamis értéket elváró makró
/// Hamis értéket elváró makró
#define EXPECT_FALSE(actual)
EXPECTCMP(!(actual), "false", actual
)
#define EXPECT_FALSE(actual)
gtest_lite::EXPECT_(false, actual, gtest_lite::eq, __FILE__, __LINE__, "EXPECT_FALSE(" #actual ")"
)
/// Valós számok azonosságát elváró makró
/// Valós számok azonosságát elváró makró
#define EXPECT_DOUBLE_EQ(expected, actual) EXPECTCMP(gtest_lite::almostEQ(expected, actual), expected, actual)
#define EXPECT_FLOAT_EQ(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::almostEQ, __FILE__, __LINE__, "EXPECT_FLOAT_EQ(" #expected ", " #actual ")" )
/// Valós számok azonosságát elváró makró
#define EXPECT_DOUBLE_EQ(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::almostEQ, __FILE__, __LINE__, "EXPECT_DOUBLE_EQ(" #expected ", " #actual ")" )
/// C stringek (const char *) azonosságát tesztelő makró
/// C stringek (const char *) azonosságát tesztelő makró
#define EXPECT_STREQ(expected, actual) ((actual != NULL) ? \
#define EXPECT_STREQ(expected, actual) gtest_lite::EXPECTSTR(expected, actual, gtest_lite::eqstr, __FILE__, __LINE__, "EXPECT_STREQ(" #expected ", " #actual ")" )
EXPECTCMP(strcmp(expected, actual) == 0, expected, actual) : \
EXPECT(false, "STR_EQ NULL pointert kapott!"))
/// C stringek (const char *) eltéréset tesztelő makró
/// C stringek (const char *) eltéréset tesztelő makró
#define EXPECT_STRNE(expected, actual) ((actual != NULL) ? \
#define EXPECT_STRNE(expected, actual) gtest_lite::EXPECTSTR(expected, actual, gtest_lite::nestr, __FILE__, __LINE__, "EXPECT_STRNE(" #expected ", " #actual ")", "etalon" )
EXPECTNE(strcmp(expected, actual) != 0, expected, actual) : \
EXPECT(false, "STR_EQ NULL pointert kapott!"))
/// C stringek (const char *) azonosságát tesztelő makró (kisbetű/nagybetű azonos)
#define EXPECT_STRCASEEQ(expected, actual) gtest_lite::EXPECTSTR(expected, actual, gtest_lite::eqstrcase, __FILE__, __LINE__, "EXPECT_STRCASEEQ(" #expected ", " #actual ")" )
/// C stringek (const char *) eltéréset tesztelő makró (kisbetű/nagybetű azonos)
#define EXPECT_STRCASENE(expected, actual) gtest_lite::EXPECTSTR(expected, actual, gtest_lite::nestrcase, __FILE__, __LINE__, "EXPECT_STRCASENE(" #expected ", " #actual ")", "etalon" )
/// 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.")
/// Kivételt várunk
#define EXPECT_ANY_THROW(statement) try { gtest_lite::test.tmp = false; statement; } \
catch (...) { gtest_lite::test.tmp = true; } \
EXPECTTHROW(statement, "kivetelt dob.", "nem dobott kivetelt.")
/// Nem várunk kivételt
#define EXPECT_NO_THROW(statement) try { gtest_lite::test.tmp = true; statement; } \
catch (...) { gtest_lite::test.tmp = false; }\
EXPECTTHROW(statement, "nem dob kivetelt.", "kivetelt dobott.")
/// Nem várunk kivételt
#define ASSERT_NO_THROW(statement) try { gtest_lite::test.tmp = true; statement; } \
catch (...) { gtest_lite::test.tmp = false; }\
ASSERTTHROW(statement, "nem dob kivetelt.", "kivetelt dobott.")
/// 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
#define EXPECT_ENVEQ(expected, actual) gtest_lite::EXPECTSTR(std::getenv(expected), actual, gtest_lite::eqstr, __FILE__, __LINE__, "EXPECT_ENVEQ(" #expected ", " #actual ")" )
/// Környezeti változóhoz hasonlít -- ilyen nincs a gtest-ben (kisbetű/nagybetű azonos)
#define EXPECT_ENVCASEEQ(expected, actual) gtest_lite::EXPECTSTR(std::getenv(expected), actual, gtest_lite::eqstrcase, __FILE__, __LINE__, "EXPECT_ENVCASEEQ(" #expected ", " #actual ")" )
#if __cplusplus >= 201103L
/// Reguláris kifejezés illesztése
# define EXPECT_REGEXP(expected, actual, match, err) gtest_lite::EXPECTREGEXP(expected, actual, match, err, __FILE__, __LINE__, "EXPECT_REGEXP(" #expected ", " #actual ", " #match ")" )
#endif
////--------------------------------------------------------------------------------------------
/// ASSERT típusú ellenőrzések. CSak 1-2 van megvalósítva. Nem ostream& -val térnek vissza !!!
/// Kivételt várunk
/// Azonosságot elváró makró
#define ASSERT_EQ(expected, actual) gtest_lite::ASSERT_(expected, actual, gtest_lite::eq, "ASSER_EQ")
/// Nem várunk kivételt
/// Nem várunk kivételt
#define
EXPEC
T_NO_THROW(statement) try { gtest_lite::test.tmp = true; statement; } \
#define
ASSER
T_NO_THROW(statement) try { gtest_lite::test.tmp = true; statement; } \
catch (...) { gtest_lite::test.tmp = false; }\
catch (...) { gtest_lite::test.tmp = false; }\
EXPECTTHROW(statement, "nem dob kivetelt.", "kivetelt dobott.")
ASSERTTHROW(statement, "nem dob kivetelt.", "kivetelt dobott.")
/// Segédmakró egy adattag, vagy tagfüggvény létezésének tesztelésére futási időben
/// Segédmakró egy adattag, vagy tagfüggvény létezésének tesztelésére futási időben
/// Ötlet:
/// Ötlet:
/// 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:
/// CREATE_Has_(size)
/// ... 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; }; \
struct Derived : T, Fallback {}; \
struct Derived : T, Fallback {}; \
template<typename C, C> struct ChT; \
template<typename C, C> struct ChT; \
...
@@ -112,37 +201,42 @@ template<typename T> struct Has_##X { \
...
@@ -112,37 +201,42 @@ template<typename T> struct Has_##X { \
static bool const member = sizeof(f<Derived>(0)) == 2; \
static bool const member = sizeof(f<Derived>(0)) == 2; \
};
};
/// Segédfüggvény egy publikus adattag, vagy tagfüggvény létezésének tesztelésére fordítási időben
#define CREATE_Has_fn_(X, S) \
void
hasMember
(...)
{}
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
/// fordítási időben
inline
void
hasMember
(...)
{}
/// Segédsablon típuskonverzió futás közbeni ellenőrzésere
template
<
typename
F
,
typename
T
>
struct
_Is_Types
{
template
<
typename
D
>
static
char
(
&
f
(
D
))[
1
];
template
<
typename
D
>
static
char
(
&
f
(...))[
2
];
static
bool
const
convertable
=
sizeof
(
f
<
T
>
(
F
()))
==
1
;
};
/// -----------------------------------
/// -----------------------------------
/// Belső megvalósításhoz tartozó makrók, és osztályok.
/// Belső megvalósításhoz tartozó makrók, és osztályok.
/// Nem célszerű közvetlenül használni, vagy módosítani
/// Nem célszerű közvetlenül használni, vagy módosítani
/// -----------------------------------
/// -----------------------------------
/// EXPECT: makró, hogy könnyen lecserélhető legyen
#define EXPECT(expr, msg) gtest_lite::test.expect(expr, __FILE__, __LINE__, #msg)
/// EXPECTEXP: általános kifejezés kiértékelése
#define EXPECTEXP(expr, exp, act) gtest_lite::test.expect(expr, __FILE__, __LINE__, #expr) \
<< "**A(z) '"#act << "'kifejezes\n** erteke: " << std::boolalpha << (act) \
<< "\n** elvart: " << (exp) << std::endl
/// EXPECTCMP: összehasonlítás
#define EXPECTCMP(expr, exp, act) gtest_lite::test.expect(expr, __FILE__, __LINE__, #act) \
<< "**A(z) '"#act << "'kifejezes\n** erteke: " << std::boolalpha << (act) \
<< "\n** elvart: " << (exp) << std::endl
/// EXPECTNE: összehasonlítás
#define EXPECTNE(expr, exp, act) gtest_lite::test.expect(expr, __FILE__, __LINE__, #act) \
<< "**A(z) '"#act << "'kifejezes\n** erteke: " << std::boolalpha << (act) \
<< "\n** elvart, hogy nem: " << (exp) << std::endl
/// EXPECTTHROW: kivételkezelés
/// EXPECTTHROW: kivételkezelés
#define EXPECTTHROW(statement, exp, act) gtest_lite::test.expect(gtest_lite::test.tmp, __FILE__, __LINE__, #statement) \
#define EXPECTTHROW(statement, exp, act) gtest_lite::test.expect(gtest_lite::test.tmp, __FILE__, __LINE__, #statement) \
<< "**Az utasitas " << (act) \
<< "** Az utasitas " << (act) \
<< "\n**Azt vartuk, hogy " << (exp) << std::endl
<< "\n** Azt vartuk, hogy " << (exp) << std::endl
#define ASSERTTHROW(statement, exp, act) gtest_lite::test.expect(gtest_lite::test.tmp, __FILE__, __LINE__, #statement) \
<< "** Az utasitas " << (act) \
<< "\n** Azt vartuk, hogy " << (exp) << std::endl; if (!gtest_lite::test.status) { gtest_lite::test.end(); break; }
#define ASSERT_(expected, actual, fn, op) EXPECT_(expected, actual, fn, __FILE__, __LINE__, #op "(" #expected ", " #actual ")" ); \
if (!gtest_lite::test.status) { gtest_lite::test.end(); break; }
#ifdef CPORTA
#ifdef CPORTA
#define GTINIT(is) \
#define GTINIT(is) \
...
@@ -168,88 +262,234 @@ namespace gtest_lite {
...
@@ -168,88 +262,234 @@ namespace gtest_lite {
struct
Test
{
struct
Test
{
int
sum
;
///< tesztek számlálója
int
sum
;
///< tesztek számlálója
int
failed
;
///< hibás tesztek
int
failed
;
///< hibás tesztek
int
ablocks
;
///< allokált blokkok száma
bool
status
;
///< éppen futó teszt státusza
bool
status
;
///< éppen futó teszt státusza
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
Test
()
:
sum
(
0
),
failed
(
0
),
status
(
false
),
null
(
"/dev/null"
)
{}
static
Test
&
getTest
()
{
static
Test
instance
;
///< egyedüli (singleton) példány
return
instance
;
}
private
:
/// singleton minta miatt
Test
()
:
sum
(
0
),
failed
(
0
),
status
(
false
),
null
(
"/dev/null"
),
os
(
std
::
cout
)
{}
Test
(
const
Test
&
);
void
operator
=
(
const
Test
&
);
public
:
/// Teszt kezdete
/// Teszt kezdete
void
begin
(
const
char
*
n
)
{
void
begin
(
const
char
*
n
)
{
name
=
n
;
status
=
true
;
name
=
n
;
status
=
true
;
#ifndef CPORTA
#ifdef MEMTRACE
std
::
cerr
<<
"
\n
---> "
<<
name
<<
std
::
endl
;
ablocks
=
memtrace
::
allocated_blocks
();
#endif // CPORTA
#endif
os
<<
"
\n
---> "
<<
name
<<
std
::
endl
;
++
sum
;
++
sum
;
}
}
/// Teszt vége
/// Teszt vége
void
end
()
{
std
::
ostream
&
end
(
bool
memchk
=
false
)
{
(
void
)
memchk
;
// Elkerülni az unused-variable warningot, ha nincs memtrace
#ifdef MEMTRACE
if
(
memchk
&&
ablocks
!=
memtrace
::
allocated_blocks
())
{
status
=
false
;
return
os
<<
"** Lehet, hogy nem szabaditott fel minden memoriat! **"
<<
std
::
endl
;
}
#endif
os
<<
(
status
?
" SIKERES"
:
"** HIBAS ****"
)
<<
"
\t
"
<<
name
<<
" <---"
<<
std
::
endl
;
#ifdef CPORTA
#ifdef CPORTA
if
(
!
status
)
if
(
!
status
)
std
::
cerr
<<
(
status
?
" SIKERES"
:
"** HIBAS ****"
)
<<
"
\t
"
<<
name
<<
" <---"
<<
std
::
endl
;
#endif // CPORTA
#endif // CPORTA
std
::
cerr
<<
(
status
?
" SIKERES"
:
"** HIBAS ****"
)
<<
"
\t
"
<<
name
<<
" <---"
<<
std
::
endl
;
if
(
!
status
)
return
os
;
else
return
null
;
}
}
bool
fail
()
{
return
failed
;
}
bool
fail
()
{
return
failed
;
}
bool
astatus
()
{
return
status
;
}
/// Eredményt adminisztráló tagfüggvény True a jó eset.
/// Eredményt adminisztráló tagfüggvény True a jó eset.
std
::
ostream
&
expect
(
bool
st
,
const
char
*
file
,
int
line
,
const
char
*
expr
)
{
std
::
ostream
&
expect
(
bool
st
,
const
char
*
file
,
int
line
,
const
char
*
expr
,
bool
pr
=
false
)
{
if
(
!
st
)
{
if
(
!
st
)
{
++
failed
;
++
failed
;
status
=
false
;
status
=
false
;
}
if
(
!
st
||
pr
)
{
std
::
string
str
(
file
);
std
::
string
str
(
file
);
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
**** HIBA:
"
<<
&
file
[
i
]
<<
"("
<<
line
<<
"): "
<<
expr
<<
" ****"
<<
std
::
endl
;
return
os
<<
"
\n
****
"
<<
&
file
[
i
]
<<
"("
<<
line
<<
"): "
<<
expr
<<
" ****"
<<
std
::
endl
;
}
}
return
null
;
return
null
;
}
}
/// Eredményt adminisztráló tagfüggvény True a jó eset, mindig ír
std
::
ostream
&
tstatus
(
bool
st
,
const
char
*
file
,
int
line
)
{
if
(
!
st
)
{
++
failed
;
status
=
false
;
}
std
::
string
str
(
file
);
size_t
i
=
str
.
rfind
(
"
\\
"
);
if
(
i
==
std
::
string
::
npos
)
i
=
str
.
rfind
(
"/"
);
if
(
i
==
std
::
string
::
npos
)
i
=
0
;
else
i
++
;
return
std
::
cerr
<<
(
status
?
"** SIKERES"
:
"** HIBAS"
)
<<
" TESZT "
<<
&
file
[
i
]
<<
"("
<<
line
<<
") **"
<<
std
::
endl
;
}
/// 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
;
}
}
}
};
};
/// Egytelen statikus példány
/// A statikus referencia minden fordítási egységben keletkezik, de
static
Test
test
;
/// mindegyik egyetlen példányra fog hivatkozni a singleton minta miatt
static
Test
&
test
=
Test
::
getTest
();
/// általános sablon a várt értékhez.
template
<
typename
T1
,
typename
T2
>
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"
)
{
return
test
.
expect
(
pred
(
exp
,
act
),
file
,
line
,
expr
)
<<
"** "
<<
lhs
<<
": "
<<
std
::
boolalpha
<<
exp
<<
"
\n
** "
<<
rhs
<<
": "
<<
std
::
boolalpha
<<
act
<<
std
::
endl
;
}
/// pointerre specializált sablon a várt értékhez.
template
<
typename
T1
,
typename
T2
>
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"
)
{
return
test
.
expect
(
pred
(
exp
,
act
),
file
,
line
,
expr
)
<<
"** "
<<
lhs
<<
": "
<<
(
void
*
)
exp
<<
"
\n
** "
<<
rhs
<<
": "
<<
(
void
*
)
act
<<
std
::
endl
;
}
#if __cplusplus >= 201103L
/// nullptr-re specializált sablon a várt értékhez.
template
<
typename
T
>
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"
)
{
return
test
.
expect
(
pred
(
exp
,
act
),
file
,
line
,
expr
)
<<
"** "
<<
lhs
<<
": "
<<
(
void
*
)
exp
<<
"
\n
** "
<<
rhs
<<
": "
<<
(
void
*
)
act
<<
std
::
endl
;
}
#endif
/// stringek összehasonlításához.
/// azért nem spec. mert a sima EQ-ra másként kell működnie.
inline
std
::
ostream
&
EXPECTSTR
(
const
char
*
exp
,
const
char
*
act
,
bool
(
*
pred
)(
const
char
*
,
const
char
*
),
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
<<
": "
<<
(
exp
==
NULL
?
"NULL pointer"
:
std
::
string
(
"
\"
"
)
+
exp
+
std
::
string
(
"
\"
"
))
<<
"
\n
** "
<<
rhs
<<
": "
<<
(
act
==
NULL
?
"NULL pointer"
:
std
::
string
(
"
\"
"
)
+
act
+
std
::
string
(
"
\"
"
))
<<
std
::
endl
;
}
/// Segédfüggvény valós számok összehasonlításához
#if __cplusplus >= 201103L
/// regexp összehasonlításhoz.
template
<
typename
E
,
typename
S
>
int
count_regexp
(
E
exp
,
S
str
)
{
std
::
regex
rexp
(
exp
);
auto
w_beg
=
std
::
sregex_iterator
(
str
.
begin
(),
str
.
end
(),
rexp
);
auto
w_end
=
std
::
sregex_iterator
();
return
std
::
distance
(
w_beg
,
w_end
);
}
template
<
typename
E
,
typename
S
>
std
::
ostream
&
EXPECTREGEXP
(
E
exp
,
S
str
,
int
match
,
const
char
*
err
,
const
char
*
file
,
int
line
,
const
char
*
expr
,
const
char
*
lhs
=
"regexp"
,
const
char
*
rhs
=
"string"
,
const
char
*
m
=
"elvart/illeszkedik"
)
{
int
cnt
=
count_regexp
(
exp
,
str
);
if
(
match
<
0
)
match
=
cnt
;
return
test
.
expect
(
cnt
==
match
,
file
,
line
,
expr
)
<<
"** "
<<
lhs
<<
": "
<<
std
::
string
(
"
\"
"
)
+
exp
+
std
::
string
(
"
\"
"
)
<<
"
\n
** "
<<
rhs
<<
": "
<<
(
err
==
NULL
?
std
::
string
(
"
\"
"
)
+
str
+
std
::
string
(
"
\"
"
)
:
err
)
<<
"
\n
** "
<<
m
<<
": "
<<
match
<<
"/"
<<
cnt
<<
std
::
endl
;
}
#endif
/// segéd sablonok a relációkhoz.
/// azért nem STL (algorithm), mert csak a függvény lehet, hogy menjen a deduckció
template
<
typename
T
>
bool
eq
(
T
a
,
T
b
)
{
return
a
==
b
;
}
inline
bool
eqstr
(
const
char
*
a
,
const
char
*
b
)
{
if
(
a
!=
NULL
&&
b
!=
NULL
)
return
strcmp
(
a
,
b
)
==
0
;
return
false
;
}
inline
bool
eqstrcase
(
const
char
*
a
,
const
char
*
b
)
{
if
(
a
!=
NULL
&&
b
!=
NULL
)
{
while
(
toupper
(
*
a
)
==
toupper
(
*
b
)
&&
*
a
!=
'\0'
)
{
a
++
;
b
++
;
}
return
*
a
==
*
b
;
}
return
false
;
}
template
<
typename
T
>
bool
ne
(
T
a
,
T
b
)
{
return
a
!=
b
;
}
inline
bool
nestr
(
const
char
*
a
,
const
char
*
b
)
{
if
(
a
!=
NULL
&&
b
!=
NULL
)
return
strcmp
(
a
,
b
)
!=
0
;
return
false
;
}
template
<
typename
T
>
bool
le
(
T
a
,
T
b
)
{
return
a
<=
b
;
}
template
<
typename
T
>
bool
lt
(
T
a
,
T
b
)
{
return
a
<
b
;
}
template
<
typename
T
>
bool
ge
(
T
a
,
T
b
)
{
return
a
>=
b
;
}
template
<
typename
T
>
bool
gt
(
T
a
,
T
b
)
{
return
a
>
b
;
}
/// 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
/// Elméleti hátér:
/// Elméleti hátér:
/// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
/// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
inline
bool
almostEQ
(
double
a
,
double
b
)
{
template
<
typename
T
>
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
double
eps
=
10
*
std
::
numeric_limits
<
double
>::
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
string2_cpp/gtest_lite.h
View file @
9906d9c2
...
@@ -2,12 +2,17 @@
...
@@ -2,12 +2,17 @@
#define GTEST_LITE_H
#define GTEST_LITE_H
/**
/**
* \file gtest_lite.h (v
3/2019
)
* \file gtest_lite.h (v
4/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 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.
...
@@ -26,6 +31,14 @@
...
@@ -26,6 +31,14 @@
* ...
* ...
* END
* END
* ...
* ...
* // Fatális hiba esetén a teszteset nem fut tovább. Ezek az ASSERT... makrók.
* // Nem lehet a kiírásukhoz további üzenetet fűzni. PL:
* TEST(TeszEsetNeve, TesztNeve)
* ASSERT_NO_THROW(f(0)); // itt nem lehet << "duma"
* EXPECT_EQ(4, f(2)) << "A függvény hibás eredményt adott" << std::endl;
* ...
* END
* ...
*
*
* A működés részleteinek megértése szorgalmi feladat.
* A működés részleteinek megértése szorgalmi feladat.
*/
*/
...
@@ -35,10 +48,15 @@
...
@@ -35,10 +48,15 @@
#include <cmath>
#include <cmath>
#include <cstring>
#include <cstring>
#include <limits>
#include <limits>
#include <cstdlib>
#include <string>
#include <string>
#include <fstream>
#include <fstream>
#if __cplusplus >= 201103L
# include <iterator>
# include <regex>
#endif
#ifdef MEMTRACE
#ifdef MEMTRACE
#include "memtrace.h"
#
include "memtrace.h"
#endif
#endif
// Két makró az egyes tesztek elé és mögé:
// Két makró az egyes tesztek elé és mögé:
...
@@ -50,19 +68,19 @@
...
@@ -50,19 +68,19 @@
/// a gtest keretrendszerbe.
/// a gtest keretrendszerbe.
/// @param C - teszteset neve (csak a gtest kompatibilitás miatt van külön neve az eseteknek)
/// @param C - teszteset neve (csak a gtest kompatibilitás miatt van külön neve az eseteknek)
/// @param N - teszt neve
/// @param N - teszt neve
#define TEST(C, N) { gtest_lite::test.begin(#C"."#N);
#define TEST(C, N)
do
{ gtest_lite::test.begin(#C"."#N);
/// Teszteset vége.
/// Teszteset vége.
#define END gtest_lite::test.end(); }
#define END gtest_lite::test.end(); }
while (false);
/// Teszteset vége allokált blokkok számának összehasonlításával
/// Teszteset vége allokált blokkok számának összehasonlításával
/// Ez az ellenőrzés nem bomba biztos.
/// Ez az ellenőrzés nem bomba biztos.
#define ENDM gtest_lite::test.end(true); }
#define ENDM gtest_lite::test.end(true); }
while (false);
/// Teszteset vége allokált blokkok számának összehasonlításával
/// Teszteset vége allokált blokkok számának összehasonlításával
/// Ez az ellenőrzés nem bomba biztos.
/// Ez az ellenőrzés nem bomba biztos.
/// Ha hiba van kiírja az üzenetet.
/// Ha hiba van kiírja az üzenetet.
#define ENDMsg(t) gtest_lite::test.end(true) << t << std::endl; }
#define ENDMsg(t) gtest_lite::test.end(true) << t << std::endl; }
while (false);
// Eredmények vizsgálatát segítő makrók.
// Eredmények vizsgálatát segítő makrók.
// A paraméterek és a funkciók a gtest keretrendszerrel megegyeznek.
// A paraméterek és a funkciók a gtest keretrendszerrel megegyeznek.
...
@@ -70,11 +88,13 @@
...
@@ -70,11 +88,13 @@
/// Sikeres teszt makrója
/// Sikeres teszt makrója
#define SUCCEED() gtest_lite::test.expect(true, __FILE__, __LINE__, "SUCCEED()", true)
#define SUCCEED() gtest_lite::test.expect(true, __FILE__, __LINE__, "SUCCEED()", true)
/// Sikertelen teszt makrója
/// Sikertelen teszt
fatális hiba
makrója
#define FAIL() gtest_lite::test.expect(false, __FILE__, __LINE__, "FAIL()", true)
#define FAIL() gtest_lite::test.expect(false, __FILE__, __LINE__, "FAIL()", true)
/// Azonosságot elváró makró
/// Sikertelen teszt makrója
#define ADD_FAILURE() gtest_lite::test.expect(false, __FILE__, __LINE__, "ADD_FAILURE()", true)
/// Azonosságot elváró makró
#define EXPECT_EQ(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::eq, __FILE__, __LINE__, "EXPECT_EQ(" #expected ", " #actual ")" )
#define EXPECT_EQ(expected, actual) gtest_lite::EXPECT_(expected, actual, gtest_lite::eq, __FILE__, __LINE__, "EXPECT_EQ(" #expected ", " #actual ")" )
/// Eltérést elváró makró
/// Eltérést elváró makró
...
@@ -110,9 +130,15 @@
...
@@ -110,9 +130,15 @@
/// C stringek (const char *) eltéréset tesztelő makró
/// C stringek (const char *) eltéréset tesztelő makró
#define EXPECT_STRNE(expected, actual) gtest_lite::EXPECTSTR(expected, actual, gtest_lite::nestr, __FILE__, __LINE__, "EXPECT_STRNE(" #expected ", " #actual ")", "etalon" )
#define EXPECT_STRNE(expected, actual) gtest_lite::EXPECTSTR(expected, actual, gtest_lite::nestr, __FILE__, __LINE__, "EXPECT_STRNE(" #expected ", " #actual ")", "etalon" )
/// C stringek (const char *) azonosságát tesztelő makró (kisbetű/nagybetű azonos)
#define EXPECT_STRCASEEQ(expected, actual) gtest_lite::EXPECTSTR(expected, actual, gtest_lite::eqstrcase, __FILE__, __LINE__, "EXPECT_STRCASEEQ(" #expected ", " #actual ")" )
/// C stringek (const char *) eltéréset tesztelő makró (kisbetű/nagybetű azonos)
#define EXPECT_STRCASENE(expected, actual) gtest_lite::EXPECTSTR(expected, actual, gtest_lite::nestrcase, __FILE__, __LINE__, "EXPECT_STRCASENE(" #expected ", " #actual ")", "etalon" )
/// 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.")
...
@@ -126,22 +152,45 @@
...
@@ -126,22 +152,45 @@
catch (...) { gtest_lite::test.tmp = false; }\
catch (...) { gtest_lite::test.tmp = false; }\
EXPECTTHROW(statement, "nem dob kivetelt.", "kivetelt dobott.")
EXPECTTHROW(statement, "nem dob kivetelt.", "kivetelt dobott.")
/// Nem várunk kivételt
gtest kompatibilitás miatt
/// Nem várunk kivételt
#define ASSERT_NO_THROW(statement) try { gtest_lite::test.tmp = true; statement; } \
#define ASSERT_NO_THROW(statement) try { gtest_lite::test.tmp = true; statement; } \
catch (...) { gtest_lite::test.tmp = false; }\
catch (...) { gtest_lite::test.tmp = false; }\
EXPEC
TTHROW(statement, "nem dob kivetelt.", "kivetelt dobott.")
ASSER
TTHROW(statement, "nem dob kivetelt.", "kivetelt dobott.")
/// 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
#define EXPECT_ENVEQ(expected, actual) gtest_lite::EXPECTSTR(std::getenv(expected), actual, gtest_lite::eqstr, __FILE__, __LINE__, "EXPECT_ENVEQ(" #expected ", " #actual ")" )
/// Környezeti változóhoz hasonlít -- ilyen nincs a gtest-ben (kisbetű/nagybetű azonos)
#define EXPECT_ENVCASEEQ(expected, actual) gtest_lite::EXPECTSTR(std::getenv(expected), actual, gtest_lite::eqstrcase, __FILE__, __LINE__, "EXPECT_ENVCASEEQ(" #expected ", " #actual ")" )
#if __cplusplus >= 201103L
/// Reguláris kifejezés illesztése
# define EXPECT_REGEXP(expected, actual, match, err) gtest_lite::EXPECTREGEXP(expected, actual, match, err, __FILE__, __LINE__, "EXPECT_REGEXP(" #expected ", " #actual ", " #match ")" )
#endif
////--------------------------------------------------------------------------------------------
/// ASSERT típusú ellenőrzések. CSak 1-2 van megvalósítva. Nem ostream& -val térnek vissza !!!
/// Kivételt várunk
/// Azonosságot elváró makró
#define ASSERT_EQ(expected, actual) gtest_lite::ASSERT_(expected, actual, gtest_lite::eq, "ASSER_EQ")
/// Nem várunk kivételt
#define ASSERT_NO_THROW(statement) try { gtest_lite::test.tmp = true; statement; } \
catch (...) { gtest_lite::test.tmp = false; }\
ASSERTTHROW(statement, "nem dob kivetelt.", "kivetelt dobott.")
/// Segédmakró egy adattag, vagy tagfüggvény létezésének tesztelésére futási időben
/// Segédmakró egy adattag, vagy tagfüggvény létezésének tesztelésére futási időben
/// Ötlet:
/// Ötlet:
/// 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; }; \
...
@@ -152,6 +201,14 @@ template<typename T> struct _Has_##X { \
...
@@ -152,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
(...)
{}
...
@@ -159,7 +216,7 @@ inline void hasMember(...) {}
...
@@ -159,7 +216,7 @@ inline void hasMember(...) {}
/// Segédsablon típuskonverzió futás közbeni ellenőrzésere
/// Segédsablon típuskonverzió futás közbeni ellenőrzésere
template
<
typename
F
,
typename
T
>
template
<
typename
F
,
typename
T
>
struct
_Is_Types
{
struct
_Is_Types
{
template
<
typename
D
>
static
char
(
&
f
(
D
*
))[
1
];
template
<
typename
D
>
static
char
(
&
f
(
D
))[
1
];
template
<
typename
D
>
static
char
(
&
f
(...))[
2
];
template
<
typename
D
>
static
char
(
&
f
(...))[
2
];
static
bool
const
convertable
=
sizeof
(
f
<
T
>
(
F
()))
==
1
;
static
bool
const
convertable
=
sizeof
(
f
<
T
>
(
F
()))
==
1
;
};
};
...
@@ -174,6 +231,13 @@ struct _Is_Types {
...
@@ -174,6 +231,13 @@ struct _Is_Types {
<< "** Az utasitas " << (act) \
<< "** Az utasitas " << (act) \
<< "\n** Azt vartuk, hogy " << (exp) << std::endl
<< "\n** Azt vartuk, hogy " << (exp) << std::endl
#define ASSERTTHROW(statement, exp, act) gtest_lite::test.expect(gtest_lite::test.tmp, __FILE__, __LINE__, #statement) \
<< "** Az utasitas " << (act) \
<< "\n** Azt vartuk, hogy " << (exp) << std::endl; if (!gtest_lite::test.status) { gtest_lite::test.end(); break; }
#define ASSERT_(expected, actual, fn, op) EXPECT_(expected, actual, fn, __FILE__, __LINE__, #op "(" #expected ", " #actual ")" ); \
if (!gtest_lite::test.status) { gtest_lite::test.end(); break; }
#ifdef CPORTA
#ifdef CPORTA
#define GTINIT(is) \
#define GTINIT(is) \
int magic; \
int magic; \
...
@@ -203,12 +267,13 @@ struct Test {
...
@@ -203,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
:
...
@@ -218,32 +283,33 @@ public:
...
@@ -218,32 +283,33 @@ 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
;
(
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
;
}
}
bool
fail
()
{
return
failed
;
}
bool
fail
()
{
return
failed
;
}
bool
astatus
()
{
return
status
;
}
/// Eredményt adminisztráló tagfüggvény True a jó eset.
/// Eredményt adminisztráló tagfüggvény True a jó eset.
std
::
ostream
&
expect
(
bool
st
,
const
char
*
file
,
int
line
,
const
char
*
expr
,
bool
pr
=
false
)
{
std
::
ostream
&
expect
(
bool
st
,
const
char
*
file
,
int
line
,
const
char
*
expr
,
bool
pr
=
false
)
{
if
(
!
st
)
{
if
(
!
st
)
{
...
@@ -255,17 +321,20 @@ public:
...
@@ -255,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
;
}
}
}
};
};
...
@@ -275,7 +344,7 @@ static Test& test = Test::getTest();
...
@@ -275,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
,
T
2
),
const
char
*
file
,
int
line
,
std
::
ostream
&
EXPECT_
(
T1
exp
,
T2
act
,
bool
(
*
pred
)(
T1
,
T
1
),
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
...
@@ -284,7 +353,7 @@ std::ostream& EXPECT_(T1 exp, T2 act, bool (*pred)(T1, T2), const char *file, in
...
@@ -284,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
*
,
T
2
*
),
const
char
*
file
,
int
line
,
std
::
ostream
&
EXPECT_
(
T1
*
exp
,
T2
*
act
,
bool
(
*
pred
)(
T1
*
,
T
1
*
),
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
...
@@ -293,8 +362,16 @@ std::ostream& EXPECT_(T1* exp, T2* act, bool (*pred)(T1*, T2*), const char *file
...
@@ -293,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
...
@@ -312,10 +389,33 @@ std::ostream& EXPECTSTR(const char *exp, const char *act, bool (*pred)(const cha
...
@@ -312,10 +389,33 @@ std::ostream& EXPECTSTR(const char *exp, const char *act, bool (*pred)(const cha
<<
"
\n
** "
<<
rhs
<<
": "
<<
(
act
==
NULL
?
"NULL pointer"
:
std
::
string
(
"
\"
"
)
+
act
+
std
::
string
(
"
\"
"
))
<<
std
::
endl
;
<<
"
\n
** "
<<
rhs
<<
": "
<<
(
act
==
NULL
?
"NULL pointer"
:
std
::
string
(
"
\"
"
)
+
act
+
std
::
string
(
"
\"
"
))
<<
std
::
endl
;
}
}
#if __cplusplus >= 201103L
/// regexp összehasonlításhoz.
template
<
typename
E
,
typename
S
>
int
count_regexp
(
E
exp
,
S
str
)
{
std
::
regex
rexp
(
exp
);
auto
w_beg
=
std
::
sregex_iterator
(
str
.
begin
(),
str
.
end
(),
rexp
);
auto
w_end
=
std
::
sregex_iterator
();
return
std
::
distance
(
w_beg
,
w_end
);
}
template
<
typename
E
,
typename
S
>
std
::
ostream
&
EXPECTREGEXP
(
E
exp
,
S
str
,
int
match
,
const
char
*
err
,
const
char
*
file
,
int
line
,
const
char
*
expr
,
const
char
*
lhs
=
"regexp"
,
const
char
*
rhs
=
"string"
,
const
char
*
m
=
"elvart/illeszkedik"
)
{
int
cnt
=
count_regexp
(
exp
,
str
);
if
(
match
<
0
)
match
=
cnt
;
return
test
.
expect
(
cnt
==
match
,
file
,
line
,
expr
)
<<
"** "
<<
lhs
<<
": "
<<
std
::
string
(
"
\"
"
)
+
exp
+
std
::
string
(
"
\"
"
)
<<
"
\n
** "
<<
rhs
<<
": "
<<
(
err
==
NULL
?
std
::
string
(
"
\"
"
)
+
str
+
std
::
string
(
"
\"
"
)
:
err
)
<<
"
\n
** "
<<
m
<<
": "
<<
match
<<
"/"
<<
cnt
<<
std
::
endl
;
}
#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
T
1
,
typename
T2
>
template
<
typename
T
>
bool
eq
(
T
1
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
)
{
...
@@ -324,8 +424,21 @@ bool eqstr(const char *a, const char *b) {
...
@@ -324,8 +424,21 @@ bool eqstr(const char *a, const char *b) {
return
false
;
return
false
;
}
}
template
<
typename
T1
,
typename
T2
>
inline
bool
ne
(
T1
a
,
T2
b
)
{
return
a
!=
b
;
}
bool
eqstrcase
(
const
char
*
a
,
const
char
*
b
)
{
if
(
a
!=
NULL
&&
b
!=
NULL
)
{
while
(
toupper
(
*
a
)
==
toupper
(
*
b
)
&&
*
a
!=
'\0'
)
{
a
++
;
b
++
;
}
return
*
a
==
*
b
;
}
return
false
;
}
template
<
typename
T
>
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
)
{
...
@@ -334,17 +447,17 @@ bool nestr(const char *a, const char *b) {
...
@@ -334,17 +447,17 @@ bool nestr(const char *a, const char *b) {
return
false
;
return
false
;
}
}
template
<
typename
T
1
,
typename
T2
>
template
<
typename
T
>
bool
le
(
T
1
a
,
T2
b
)
{
return
a
<=
b
;
}
bool
le
(
T
a
,
T
b
)
{
return
a
<=
b
;
}
template
<
typename
T
1
,
typename
T2
>
template
<
typename
T
>
bool
lt
(
T
1
a
,
T2
b
)
{
return
a
<
b
;
}
bool
lt
(
T
a
,
T
b
)
{
return
a
<
b
;
}
template
<
typename
T
1
,
typename
T2
>
template
<
typename
T
>
bool
ge
(
T
1
a
,
T2
b
)
{
return
a
>=
b
;
}
bool
ge
(
T
a
,
T
b
)
{
return
a
>=
b
;
}
template
<
typename
T
1
,
typename
T2
>
template
<
typename
T
>
bool
gt
(
T
1
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
...
@@ -354,18 +467,29 @@ template <typename T>
...
@@ -354,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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment