Convenient method in GoogleTest for a double comparison of not equal? - c++

I'm looking for something similar to the ASSERT_EQ / ASSERT_NE for ASSERT_DOUBLE_EQ.
Maybe I'm missing an easy way of doing this without having a ASSERT_DOUBLE_NE?

You can use the companion mocking framework Google Mock. It has a powerful library of matchers (a la Hamcrest), which you can use with the EXPECT_THAT/ASSERT_THAT macros:
EXPECT_THAT(value, FloatEq(1));
EXPECT_THAT(another_value, Not(DoubleEq(3.14)));

It looks like you're out of luck. However, you could add one yourself. I built the following code using ASSERT_DOUBLE_EQ and ASSERT_NE as a pattern.
#define ASSERT_DOUBLE_NE(expected, actual)\
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointNE<double>, \
expected, actual)
// Helper template function for comparing floating-points.
//
// Template parameter:
//
// RawType: the raw floating-point type (either float or double)
//
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
template <typename RawType>
AssertionResult CmpHelperFloatingPointNE(const char* expected_expression,
const char* actual_expression,
RawType expected,
RawType actual) {
const FloatingPoint<RawType> lhs(expected), rhs(actual);
if ( ! lhs.AlmostEquals(rhs)) {
return AssertionSuccess();
}
StrStream expected_ss;
expected_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< expected;
StrStream actual_ss;
actual_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< actual;
Message msg;
msg << "Expected: (" << expected_expression << ") != (" << actual_expression
<< "), actual: (" << StrStreamToString(expected_ss) << ") == ("
<< StrStreamToString(actual_ss) << ")";
return AssertionFailure(msg);
}

instead of creating a new CmpHelperFloatingPointNE helper, you can just define the macro as the inverse of the existing helper:
#include "gtest/gtest.h"
#define ASSERT_FLOAT_NE(val1, val2) ASSERT_PRED_FORMAT2( \
!::testing::internal::CmpHelperFloatingPointEQ<float>, val1, val2 \
)
#define ASSERT_DOUBLE_NE(val1, val2) ASSERT_PRED_FORMAT2( \
!::testing::internal::CmpHelperFloatingPointEQ<double>, val1, val2 \
)
This is not as graceful as deft_code's solution because when the assertion fails, there are no specific details like "expected value" and "actual value", just the line number and file of the assertion. For my purposes, though, the line number was enough.

Related

How to make the c ++ application work with the browser [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 11 months ago.
Improve this question
How to make the c ++ application work with the browser. I mean a program that retrieves data from a given page (let's assume that the page displays a string) and then performs some reaction on the page. For example, the page displays a random string, and the program enters the length of the string into the form.
I am a novice programmer, so I care about information and advice on where to start. Thanks in advance for any help.
As I already promised to OP in comments, posting Partial answer, which doesn't answer all questions, but only provides handy tool to wrap (call) any Python code inside C++ program.
In my code snippet I don't even do anything with browsers, but instead show only example of computing Greatest Common Divisor using Python's standard function math.gcd().
I decided to introduce this Python-in-C++ bridge only because there exist many beautiful Python modules that work with browsers or with parsing/composing HTML, hence it is much easier to write such tools in Python instead of C++.
But expert without knowledge of default Python C API, it is not that easy to implement even simple use case - compile text of Python code, pass to it any arguments from C++, receive response arguments, return arguments back to C++. Only these simple actions need usage of a dozen of different Python C API functions. That's why I decided to show how to do it, as I know.
I implemented from scratch (specifically for OP's question) handy class PyRunner which does all the magic, usage of this class is simple:
PyRunner pyrun;
std::string code = R"(
def gcd(a, b):
import math
return math.gcd(a, b)
res = gcd(*arg)
print('GCD of', arg[0], 'and', arg[1], 'is', res, flush = True)
)";
std::cout << pyrun.Run(code, "(2 * 3 * 5, 2 * 3 * 7)") << std::endl;
std::cout << pyrun.Run(code, "(5 * 7 * 11, 5 * 7 * 13)") << std::endl;
Basically you just pass any Python code snippet to PyRunner::Run() method and also any argument (represented as Python object converted to string). Result of this call is also a returned Python object converted to string. You can also use JSON to pass any large argument as string and parse returned argument, as any JSON string is also a valid stringized Python object.
Of course you need a knowledge of Python to be able to write complex code snippets inside C++.
One drawback of my PyRunner class is that for some reason (that I didn't yet understand), you can't import Python module inside global scope, as you can see I did import math within function scope. But this is not a big deal, I think, and maybe some experts will clarify the reason.
To compile and run code you need to have pre-installed Python, and pass Python's include folder and library file as compiler arguments. For example in Windows CLang you do following:
clang.exe -std=c++20 -O3 -Id:/bin/Python39/include/ d:/bin/Python39/libs/python39.lib prog.cpp
and in Linux:
clang -std=c++20 -O3 -I/usr/include/ -lpython3.9 prog.cpp
To run the program either you should provide environment variables PYTHONHOME or PYTHONPATH or run program from Python folder (like d:/bin/Python39/) or do sys.path.append("d:/bin/Python39/") on first lines of Python code snippet embedded in C++. Without these paths Python can't find location of its standard library.
PyRunner class is thread-safe, but only single-threaded always. It means that two calls to .Run() inside two threads will be exclusively blocked by mutex. I use std::mutex instead of Python's GIL to protect from multi-threading, because it is quite alright (and faster), if you don't use Python C API in any other threads simultaneously. Also it is not allowed right now to have two instances of PyRunner objects as it does Py_Initialize() and Py_FinalizeEx() in constructor and destructor, which should be done globally only once. Hence PyRunner should be a singleton.
Below is full C++ code with implementation of PyRunner class and its usage (usage is inside main()). See console output after code below. Click Try it online! link to see compile/run of this code on free GodBolt online Linux servers.
Try it online!
#include <iostream>
#include <functional>
#include <string>
#include <string_view>
#include <stdexcept>
#include <memory>
#include <mutex>
#include <Python.h>
#define ASSERT_MSG(cond, msg) { if (!(cond)) throw std::runtime_error("Assertion (" #cond ") failed at line " + std::to_string(__LINE__) + "! Msg: '" + std::string(msg) + "'."); }
#define ASSERT(cond) ASSERT_MSG(cond, "")
#define PY_ASSERT_MSG(cond, msg) { if (!(cond) || PyErr_Occurred()) { PyErr_Print(); ASSERT_MSG(false && #cond, msg); } }
#define PY_ASSERT(cond) PY_ASSERT_MSG(cond, "")
#define LN { std::cout << "LN " << __LINE__ << std::endl << std::flush; }
class PyRunner {
private:
class PyObj {
public:
PyObj(PyObject * pobj, bool inc_ref = false) : p_(pobj) {
if (inc_ref)
Py_XINCREF(p_);
PY_ASSERT_MSG(p_, "NULL PyObject* passed!");
}
PyObject * Get() { return p_; }
~PyObj() {
Py_XDECREF(p_);
p_ = nullptr;
}
private:
PyObject * p_ = nullptr;
};
public:
PyRunner() {
Py_SetProgramName(L"prog.py");
Py_Initialize();
}
~PyRunner() {
codes_.clear();
Py_FinalizeEx();
}
std::string Run(std::string code, std::string const & arg = "None") {
std::unique_lock<std::mutex> lock(mutex_);
code = StrUnIndent(code);
if (!codes_.count(code))
codes_.insert(std::pair{code, std::make_shared<PyObj>(Py_CompileString(code.c_str(), "script.py", Py_file_input))});
PyObj & compiled = *codes_.at(code);
PyObj globals_arg_mod = PyModule_New("arg"), globals_arg = PyModule_GetDict(globals_arg_mod.Get()), locals_arg = PyDict_New(),
globals_mod = PyModule_New("__main__"), globals = PyModule_GetDict(globals_mod.Get()), locals = PyDict_New();
// py_arg = PyUnicode_FromString(arg.c_str()),
PyObj py_arg = PyRun_String(arg.c_str(), Py_eval_input, globals_arg.Get(), locals_arg.Get());
PY_ASSERT(PyDict_SetItemString(locals.Get(), "arg", py_arg.Get()) == 0);
#if 0
PyObj result = PyEval_EvalCode(compiled.Get(), globals.Get(), locals.Get());
#else
PyObj builtins(PyEval_GetBuiltins(), true), exec(PyDict_GetItemString(builtins.Get(), "exec"), true);
PyObj exec_args = PyTuple_Pack(3, compiled.Get(), globals.Get(), locals.Get());
PyObj result = PyObject_CallObject(exec.Get(), exec_args.Get());
#endif
PyObj res(PyDict_GetItemString(locals.Get(), "res"), true), res_str = PyObject_Str(res.Get());
char const * cres = nullptr;
PY_ASSERT(cres = PyUnicode_AsUTF8(res_str.Get()));
return cres;
}
private:
static std::string StrUnIndent(std::string_view const & s) {
auto lines = StrSplit(s, "\n");
size_t min_off = size_t(-1);
for (auto const & line: lines) {
if (StrTrim(line).empty())
continue;
min_off = std::min<size_t>(min_off, line.find_first_not_of("\t\n\v\f\r "));
}
ASSERT(min_off < 10000ULL);
std::string res;
for (auto const & line: lines)
res += line.substr(std::min<size_t>(min_off, line.size())) + "\n";
return res;
}
static std::string StrTrim(std::string s) {
s.erase(0, s.find_first_not_of("\t\n\v\f\r ")); // left trim
s.erase(s.find_last_not_of("\t\n\v\f\r ") + 1); // right trim
return s;
}
static std::vector<std::string> StrSplit(std::string_view const & s, std::string_view const & delim) {
std::vector<std::string> res;
size_t start = 0;
while (true) {
size_t pos = s.find(delim, start);
if (pos == std::string::npos)
pos = s.size();
res.emplace_back(s.substr(start, pos - start));
if (pos >= s.size())
break;
start = pos + delim.size();
}
return res;
}
private:
std::unordered_map<std::string, std::shared_ptr<PyObj>> codes_;
std::mutex mutex_;
};
int main() {
try {
PyRunner pyrun;
std::string code = R"(
def gcd(a, b):
import math
return math.gcd(a, b)
res = gcd(*arg)
print('GCD of', arg[0], 'and', arg[1], 'is', res, flush = True)
)";
std::cout << pyrun.Run(code, "(2 * 3 * 5, 2 * 3 * 7)") << std::endl;
std::cout << pyrun.Run(code, "(5 * 7 * 11, 5 * 7 * 13)") << std::endl;
return 0;
} catch (std::exception const & ex) {
std::cout << "Exception: " << ex.what() << std::endl;
return -1;
}
}
Console output:
GCD of 30 and 42 is 6
6
GCD of 385 and 455 is 35
35

What's the equivalent of numpy.spacing(1) in libtorch?

It seems pytorch does have/expose the finfo link, but I can't find it in libtorch. Is it even made available in libtorch yet or not? Using the torch.finfo I could easily do:
esp = torch.finfo(torch.float).eps
which I believe is the counterpart/equivalent of np.spacing(1) but in libtorch I can't do the same thing as I can not find any trace of finfo class. What should I do?
There is a TypeInfo.cpp module (pytorch/torch/csrc/TypeInfo.cpp), unfortunately the method you mentioned (torch.finfo(torch.float).eps) seems to be private, as it's marked static within a translation unit:
static PyObject* THPFInfo_eps(THPFInfo* self, void*) {
return AT_DISPATCH_FLOATING_AND_COMPLEX_TYPES_AND2(at::kHalf, at::ScalarType::BFloat16,
self->type, "epsilon", [] {
return PyFloat_FromDouble(
std::numeric_limits<
at::scalar_value_type<scalar_t>::type>::epsilon());
});
}
But, within the corresponding header, there's an extern declaration:
extern PyTypeObject THPFInfoType;
THPFInfoType seems to be an instance which contains a pointer for the following function: THPFInfo_str. This function, on the other hand, prints the following:
PyObject* THPFInfo_str(THPFInfo* self) {
std::ostringstream oss;
oss << "finfo(resolution=" << PyFloat_AsDouble(THPFInfo_resolution(self, nullptr));
oss << ", min=" << PyFloat_AsDouble(THPFInfo_min(self, nullptr));
oss << ", max=" << PyFloat_AsDouble(THPFInfo_max(self, nullptr));
oss << ", eps=" << PyFloat_AsDouble(THPFInfo_eps(self, nullptr));
oss << ", tiny=" << PyFloat_AsDouble(THPFInfo_tiny(self, nullptr));
oss << ", dtype=" << PyUnicode_AsUTF8(THPFInfo_dtype(self, nullptr)) << ")";
return THPUtils_packString(oss.str().c_str());
}
Which apparently prints eps information. Maybe you could somehow link your target with TypeInfo.cpp and make use of above definitions?
It turns out, we can simply use std::nextafter just fine. And also torch::nextafter is recently added (#42580) and uses this under the hood!
So if you don't use nighlybuilds, and until 1.7 ships, you can simply use std::nextafter just fine! Concerning the THPFinfo:
THPFInfo and THPFInfo_eps exist to make this information available in
python
Source

Error handling design: Bind error messages to error codes

I have a simple structures to handle errors
enum class Error
{
None = 0,
FirstError,
SecondError,
ThirdError,
...
}
struct ErrorCategory
{
static const std::string& Message(Error aError)
{
static const std::string messages[] =
{
"first error message",
"second error message",
"third error message",
...
}
const auto index = static_cast<size_t>(aError);
assert(index < std::size(messages) && "Invalid error");
return messages[index];
}
};
Also, there are some class and methods to work with those structures.
Though it works, but the amount of errors is growing, so it becomes hard to navigate between error messages and error codes in enum. I want to declare error code and message for it in one place to make it easy to find error code. Is there a way to do it without making my code huge (such as enum + switch cases for messages) so it would be easy to maintain and without using macro?
You can use std::map<Error, std::string> like:
enum class Error : uint8_t {
None = 0,
FirstError = 1,
SecondError = 2,
ThirdError = 3
};
std::map<Error, std::string> error_messages = {
{ Error::None, "unknown error message" },
{ Error::FirstError, "first error message" },
{ Error::SecondError, "second error message" },
{ Error::ThirdError, "third error message" }
};
and then use it afterwards like:
std::cerr << error_messages[Error::None] << std::endl;
std::cerr << error_messages[Error::FirstError] << std::endl;
std::cerr << error_messages[Error::SecondError] << std::endl;
std::cerr << error_messages[Error::ThirdError] << std::endl;
Demo
This type of operation is exactly how most localized UIs work. You map some common structured ID to a user-facing string.
Because of this, there are a huge amount of platform-specific ways of doing this which aim to do exactly what you want. For example on Windows:
(Windows) FormatMessage and Message Compiler
(Windows / .NET) .resx files and ResourceManager

I want to be able to use 4 different variables in a select statement in c ++

First off I am new to C++ and I am trying to learn it to update one of my companies legacy apps. Which is on windows xp and visual c++ 6.0 which is not fun.. any ways I have this select statement that reads my database and searches for a ResourceID like what ever I set my m_operSet. I want to be able to use 4 specific variables in this like statement. problem is when I set it to a specific one it will not find any other resources besides what I set it to. here is my code this is my operations.Set.cpp and my bordDlg.cpp.
This is my list of variables I wish to use for the m_operSet
'COB'
'NIC'
'SIC'
'PRS'
Basically I want to use a if else statement.. say if COB use COB ifelse NIC use NIC ifelse SIC use SIC IFelse PRS use PRS
BordDlg.cpp
// BordDlg.cpp : implementation file
#include "operationSet.h"
#include "custSet.h"
// Initial filter is set in m_custSet Constuctor
m_custSet.setBaseID(baseID);
m_custSet.setLotID(lotID);
// Initial filter is set in m_operSet Constuctor
m_operSet.setBaseID(baseID);
m_operSet.setLotID(lotID);
m_operSet.setSubID(subID);
m_operSet.setSplitID(splitID);
// This is where I set this at and where I want to use either 'COB' 'NIC' 'SIC' 'PRS'
m_operSet.setResourceID("COB");
operationSet.cpp
// operationSet.cpp : implementation file
//
#include "stdafx.h"
#include "operationSet.h"
void operationSet::setBaseID(CString baseID)
{
m_strFilter += "and WORKORDER_BASE_ID LIKE '" + baseID + " ";
}
void operationSet::setLotID(CString lotID)
{
m_strFilter += "and WORKORDER_LOT_ID LIKE '" + lotID + "' ";
}
void operationSet::setSplitID(CString splitID)
{
m_strFilter += "and [WORKORDER_SPLIT_ID] LIKE '" + splitID + "' ";
}
void operationSet::setSubID(CString subID)
{
m_strFilter += "and [WORKORDER_SUB_ID] LIKE '" + subID + "' ";
}
void operationSet::setResourceID(CString resID)
{
m_strFilter += "and [RESOURCE_ID] LIKE '" + resID + "' ";
}
Those functions build a query string like this:
SELECT ..whatever.. FROM ..whatever.. WHERE ... \
... and [WORKORDER_SUB_ID] LIKE 'wid' and [RESOURCE_ID] LIKE 'rid' and ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~
^ build by setSubID ^ build by setResourceID ^ by other
you need to build this:
... and [WORKORDER_SUB_ID] LIKE 'wid' \
and ( [RESOURCE_ID] LIKE 'rid1' or [RESOURCE_ID] LIKE 'rid2' ) and ...
the quick fix (not recommended) is:
m_operSet.setResourceID("COB' or [RESOURCE_ID] LIKE 'NIC' or [RESOURCE_ID] "
"LIKE 'SIC' or [RESOURCE_ID] LIKE 'PRS");
and
m_strFilter += "and ( [RESOURCE_ID] LIKE '" + resID + "' ) ";
This way you end up with some kind of monster where apostrophes are added without consistency both on caller and on called function.
A better way:
void operationSet::setResourceID(std::vector<std::string> const &resIDs) {
m_strFilter += "and (";
for (auto it = resIDs.begin(); it != resIDs.end(); ++it) {
if (it != resIDs.begin())
m_strFilter += " or ";
m_strFilter += " [RESOURCE_ID] LIKE '" + *it + "' ";
}
m_strFilter += " ) ";
}
m_operSet.setResourceID({"COB", "NIC", "SIC", "PRS"});
things you need to check if your application framework:
CString and std::string. Most likely they didn't write an operator + for them. So you have 2 options: use .c_str() if they have an operator + for CString and c strings, or just use std::vector<CString>
The code is written in c++11. See if your compiler supports c++11. If not you need to replace auto with std::vector<std::string>::const_iterator
and the call with:
std::string res_id_arr[4] = {"COB", "NIC", "SIC", "PRS"};
std::vector<std::string> res_ids(res_id_arr, res_id_arr + 4);
m_operSet.setResourceID(res_ids);
Performance issues: A lot of copies will be passed around this way (but again that is true for CString also). So you really need to compile with c++11 and use move semantics. There are resources on the net for moving in c++11

BOOST_CHECK_EQUAL (and dervatives) Add custom message

We recently started using the Boost Test framework, and like it so far.
However, there are certain tests where it would be great if we could add custom messages to an existing helper.
For example, I can get the output in mytest and mytest2, but have found no way to get the output in mytest3:
#define BOOST_TEST_MODULE mytests
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_SUITE(myunit)
BOOST_AUTO_TEST_CASE(mytest)
{
// This give a nice output [2+2 != 5]
BOOST_CHECK_EQUAL(2+2, 5);
}
BOOST_AUTO_TEST_CASE(mytest2)
{
// This give only a custom output
BOOST_CHECK_MESSAGE(2+2 == 5, "comparison error");
}
BOOST_AUTO_TEST_CASE(mytest3)
{
// Ideally, it should output [2+2 != 5] comparison error
BOOST_CHECK_EQUAL_WITH_ADDITIONAL_MESSAGE(2+2, 5, "comparison error");
}
BOOST_AUTO_TEST_SUITE_END()
The reason I want this is because if I wish to have test cases like this:
BOOST_AUTO_TEST_CASE(mytest4)
{
for(int i = 0; i < 10; ++i)
{
BOOST_CHECK_EQUAL_WITH_ADDITIONAL_MESSAGE(i%3, 0, i);
}
}
In that case, there is no way to know for which i the test failed.
I have tried to "duplicate" the BOOST_CHECK_EQUAL macro as follows in hopes boost would append to the passed message as the original macro passes an empty literal:
#define BOOST_CHECK_EQUAL2( L, R ) \
BOOST_CHECK_WITH_ARGS_IMPL( ::boost::test_tools::tt_detail::equal_impl_frwd(), "hello world", CHECK, CHECK_EQUAL, (L)(R) )
However, "hello world: is overwritten somewhere in the test implementation with the failed condition.
Is there any (easy and clean) way to solve this?
UPDATE It appears as though the check_impl() implementation in test_tools.ipp doesn't utilize the check_descr parameter for the equality checks.
UPDATE 2020
BOOST_TEST_CONTEXT() and BOOST_TEST_INFO() , if you can use a reasonable recent boost version should now be the preferred method, as framework-provided operations are of course a lot cleaner.
Is there an elegant way to override/provide my own?
Ok, I would just like to post for reference in case someone else runs into this that I solved it like this:
//____________________________________________________________________________//
#define BOOST_TEST_REL_EQ_MESSAGE_EXTENSION(L, R, M, CMP, ICMP, CT) \
{ \
auto _1(L); \
auto _2(R); \
std::stringstream ss; \
ss << "check " << BOOST_TEST_STRINGIZE(L) << " " << BOOST_TEST_STRINGIZE(CMP) << " " << BOOST_TEST_STRINGIZE(R) << " failed [" << _1 << " " << BOOST_TEST_STRINGIZE(ICMP) << " " << _2 << "] : " << M;\
BOOST_CHECK_IMPL( (_1 CMP _2), ss.str(), CT, CHECK_MSG ); \
} \
/**/
#define BOOST_CHECK_EQUAL_MESSAGE(L, R, M) BOOST_TEST_REL_EQ_MESSAGE_EXTENSION(L, R, M, ==, !=, CHECK )
#define BOOST_WARN_EQUAL_MESSAGE(L, R, M) BOOST_TEST_REL_EQ_MESSAGE_EXTENSION(L, R, M, ==, !=, WARN )
#define BOOST_REQUIRE_EQUAL_MESSAGE(L, R, M) BOOST_TEST_REL_EQ_MESSAGE_EXTENSION(L, R, M, ==, !=, REQUIRE )
While this may not be optimal (mostly due to stringstream being used on every iteration in mytest4 above), it seems as through this provides a reasonably clean and non-intrusive solution for the few cases where the extra message might be required
UPDATE 2017-08
For newer boost test versions we can use BOOST_TEST_INFO() for outputting the message, which is much cleaner:
#define BOOST_CHECK_EQUAL_MESSAGE(L, R, M) { BOOST_TEST_INFO(M); BOOST_CHECK_EQUAL(L, R); }
#define BOOST_WARN_EQUAL_MESSAGE(L, R, M) { BOOST_TEST_INFO(M); BOOST_WARN_EQUAL(L, R); }
#define BOOST_REQUIRE_EQUAL_MESSAGE(L, R, M) { BOOST_TEST_INFO(M); BOOST_REQUIRE_EQUAL(L, R); }
For the need that you are describing, you should use the notion of context.
Otherwise, the assertion BOOST_TEST (and here) support a string as second argument that can be used for displaying a custom message.