CppUnit
-
At $work, we use CppUnit. We also have some tests for thread abstraction that either test things that are not guaranteed, contain race-conditions of their own, or both. Today, colleague got this¹ output:
4) test: SomethingThreadTest::TestWithReallyReallyLongName (F) line: 211 c:\tfs\project\very\long\component\name\somethingthreadtest.cpp equality assertion failed - Expected: 1 - Actual : 1
You may guess what happened (we actually have a theory).
-
You may guess what happened (we actually have a theory).
My money is on pointers.
-
@Tsaukpaetra said in CppUnit:
You may guess what happened (we actually have a theory).
My money is on pointers.
I'm guessing one of them is
"1 "
and the other is"1"
-
You may guess what happened (we actually have a theory).
The values were not equal when the comparison was done due to a synchronization issue, but equal when the framework printed them.
-
Concurrent modification by another thread?! Butbut the assert parameters are by value no?
-
Concurrent modification by another thread?! Butbut the assert parameters are by value no?
If they're template functions, someone could easily pass an int& by accident.
-
@ben_lubar said in CppUnit:
If they're template functions, someone could easily pass an int& by accident.
oooh that's how you get red shoes
-
@Tsaukpaetra said in CppUnit:
You may guess what happened (we actually have a theory).
My money is on pointers.
Frankly, my money is on idiots.
-
@Tsaukpaetra said in CppUnit:
My money is on pointers.
Warm.
The condition looks like:
CPPUNIT_ASSERT_EQUAL(1u, someObject->counter);
@ben_lubar said in CppUnit:
I'm guessing one of them is "1 " and the other is "1"
Cold. They are unsingned ints.
The values were not equal when the comparison was done due to a synchronization issue, but equal when the framework printed them.
Yes, that's what we think too.
Concurrent modification by another thread?! Butbut the assert parameters are by value no?
Well, apparently they are not. The
CPPUNIT_ASSERT_EQUALS
macro evaluates them only once, but the signature of the function it calls is:template <class T> void assertEquals( const T& expected, const T& actual, SourceLine sourceLine, const std::string &message )
And, well, if another thread writes the variable, it can still change.
@ben_lubar said in CppUnit:
If they're template functions, someone could easily pass an int& by accident.
It's not by accident.
@Steve_The_Cynic said in CppUnit:
Frankly, my money is on idiots.
Lots of those involved, for sure. From the authors of CppUnit, over those who decided equality can only work on arguments that deduce to the same argument on both sides, over those who decided the kind of test makes sense at all to the one who wrote it without regard to synchronization.
-
Yes, that's what we think too.
So… the test framework isn't doing exactly one read (of each of
expected
andactual
because test authors are TRWTF) and then comparing those?
-
Yes, that's what we think too.
So… the test framework isn't doing exactly one read (of each of
expected
andactual
because test authors are TRWTF) and then comparing those?It probably is doing one read of each to compare them. And another read to display them.
Because, frankly, what's being done is somewhere far, far outside any reasonable design centre of a unit test framework. (Concurrency in a unit test? ...)
It could be mitigated for types for which that is suitable by passing the arguments by value, but that causes problems if the type T (why is the template not using
typename T
, by the way?) doesn't have an accessible copy constructor.EDIT: but of course that makes the test results be just non-deterministic, rather than non-deterministic with gibberish messages.
-
the test framework isn't doing exactly one read [..] and then comparing those?
Difficult/impossible to guarantee for arbitrary types (since they can have custom operator== and the like). Besides, requiring the types to be copyable would impose a somewhat weird restriction.
I think the problem lies with the test authors. Multithreading requires synchronization (explicit or implicit), and that's what's missing here.
Edit: 'd once again.
-
Difficult/impossible to guarantee for arbitrary types (since they can have custom operator== and the like).
It'd be even more fun with a
volatile
memory location…
-
My first guess is floating point arithmetic. Next guess is race condition.
-
It'd be even more fun with a volatile memory location…
Agreed. For instance, surprisingly few people write custom operators that accept
volatile
-qualified instances of their objects.
-
@Steve_The_Cynic said in CppUnit:
Concurrency in a unit test? ...
Well, it is a test of the thread pool library, so it does need concurrency.
TR is that it tests things that are simply not guaranteed. One of the tests in that suite (not sure its that one, but I think it is) tests that when scheduling 6 tasks that simply sleep 40 ms to pool of 2 threads, after 50 ms two of them will be complete and after another 50 ms another 2 will be.
@Steve_The_Cynic said in CppUnit:
but of course that makes the test results be just non-deterministic, rather than non-deterministic with gibberish messages.
Well, since the test would still invoke Undefined Behaviour™, the compiler would still be free to generate gibberish messages. I don't know how it would achieve that, but I have full trust in gcc that it would be capable of such feat.
@Steve_The_Cynic said in CppUnit:
why is the template not using typename T, by the way?
Because it is Ancient™. Quite possibly from last millennium.
-
One of the tests in that suite (not sure its that one, but I think it is) tests that when scheduling 6 tasks that simply sleep 40 ms to pool of 2 threads, after 50 ms two of them will be complete and after another 50 ms another 2 will be.
-
@Bulb So TRWTF is templates.
C++ could be so good, but so many WTF. All I wanted is C with classes and strings. Mostly strings.
Edit: and minus the C WTFs that are plenty. Nevermind both these languages are beyond salvation.
-
@wharrgarbl said in CppUnit:
All I wanted is C with classes and strings.
Why would anyone want that?
-
@Steve_The_Cynic said in CppUnit:
why is the template not using
typename T,
by the way?What would be the advantage of it using
typename T
? Last time I checked, the two meant exactly the same thing, andclass
isfourfive letters,typename
is eight.
-
@ixvedeusi Yes, to the compiler mean the same. In older code,
class
was usually used, but since the parameter is rarely actually a class, in modern codetypename
is preferred.
-
Why would anyone want that?
I miss strings and destructors, and these stupid embedded devices with no file system can't C#.
-
@ixvedeusi said in CppUnit:
@Steve_The_Cynic said in CppUnit:
why is the template not using
typename T,
by the way?What would be the advantage of it using
typename T
? Last time I checked, the two meant exactly the same thing, andclass
is four letters,typename
is eight.And you can't count... ;) ;) ;) Sorry. I make
class
to be five letters.I looked it up. In this context, there's no actual difference between them. The "mandatory"
typename
use applies when using a nested type within a template parameter T, that is,T::bar
, if that is supposed to be a type, must be qualified astypename T::bar
otherwise it will be treated during syntax/etc. analysis as if it is a value / variable, and might cause ... hilarity.However, the human semantics of
typename
in a template parameter declaration are clearer than if it isclass
, sinceclass T
in a template declaration will accept things that aren't classes. I've seen claims that some people useclass T
to document that T must be a class.
-
@wharrgarbl said in CppUnit:
Why would anyone want that?
I miss strings and destructors, and these stupid embedded devices with no file system can't C#.
How about exception handling? A safer alternative to Macros? Namespaces? A standard library containing a bit more than basically nothing?
Oh, wait…
-
@Steve_The_Cynic said in CppUnit:
why is the template not using typename T, by the way?
Because it is Ancient™. Quite possibly from last millennium.
Steve.isConvinced() returns
false
. In the last millennium I wrote C++ that usedtypename
in preference toclass
for template parameter declarations. It's part of C++98.
-
in modern code typename is preferred.
I got that that was what was being asserted, but what I wondered was why.
@Steve_The_Cynic said in CppUnit:
I looked it up. In this context, there's no actual difference between them. The "mandatory" typename use applies when using a nested type within a template parameter T, that is, T::bar, if that is supposed to be a type, must be qualified as typename T::bar otherwise it will be treated during syntax/etc. analysis as if it is a value / variable, and might cause ... hilarity.
Yes, there's places where
typename
is required, which is an entirely different context and is extremely annoying because it adds up to a shit-ton of clutter obliterating the actual code.@Steve_The_Cynic said in CppUnit:
I make class to be five letters.
Ok, ok, very large values of four maybe ; I'll let you borrow my for a while.
@Steve_The_Cynic said in CppUnit:
However, the human semantics of typename in a template parameter declaration are clearer
IMHO, if you try to apply human semantics and intuition to C++ template code, you've already lost; better to not start getting used to doing so. And also IMHO, given the number of times you have to write that in all but the most utterly trivial cases, the excessive length of
typename
does quickly add up to being an actual code readability problem.
-
How about exception handling? A safer alternative to Macros? Namespaces? A standard library containing a bit more than basically nothing?
Exceptions in C++ are useless because most libraries don't use them. And libraries in C++ are incompatible between compilers, so
-
How about exception handling? A safer alternative to Macros? Namespaces? A standard library containing a bit more than basically nothing?
If you really want C, you don't really want those things. Especially the standard library (and exceptions are surprisingly chunky too…)
-
If you really want C, you don't really want those things.
But then you don't want OOP/RAII either.
-
If you really want C, you don't really want those things.
But then you don't want OOP/RAII either.
You leap to conclusions very nicely there.
-
@wharrgarbl said in CppUnit:
Exceptions in C++ are useless because most libraries don't use them.
TDEMSYR
And libraries in C++ are incompatible between compilers, so
Not true anymore, also: why not just compile them yourself?
-
You leap to conclusions very nicely there.
What's the point of RAII if there are no exceptions anyway?
-
What's the point of RAII if there are no exceptions anyway?
Not having to manually remember to deallocate the resource? That's actually got significant value, even if not quite as much as it would have in the presence of exceptions…
-
@wharrgarbl said in CppUnit:
All I wanted is C with classes and strings.
Why would anyone want that?
Because sometimes, believe it or not, the C philosophy of "keep the language simple" can have advantages.
Also, believe it or not, keeping a language similar to another language that millions of programmers already know can be an advantage too (crazy right?)
C with some syntactic sugar (like classes) to make things easier and some stupid shit removed would be a better C. Meaning anywhere C is found, you could use that instead.
C++ on the other hand adds so much stuff with so many implications that it's no longer C. It might be a better language for most purposes, but there will still be cases where it's not.
-
@anonymous234 said in CppUnit:
C with some syntactic sugar (like classes) to make things easier and some stupid shit removed would be a better C.
That's how C++ started. Problem is, it didn't know when to stop.
-
@RaceProUK said in CppUnit:
Problem is, it didn't know when to stop.
The right time to stop has come when people finally stop using C for anything else than extremely low-level stuff like device drivers.
Filed under: Finally another C vs C++ flamewar
-
Finally another C vs C++ flamewar
Oh... Um... Well, this is embarrassing... I only have a C# cannon...
-
@RaceProUK said in CppUnit:
I only have a C# cannon...
I have a reply to that, but I think fbmac and me already derailed this thread enough.
-
@Steve_The_Cynic said in CppUnit:
Frankly, my money is on idiots.
Well, we already know they're using C++...
-
@anonymous234 said in CppUnit:
C with some syntactic sugar (like classes) to make things easier and some stupid shit removed would be a better C. Meaning anywhere C is found, you could use that instead.
My 20 year old unsupported compiler disagrees with your second statement.
-
@masonwheeler said in CppUnit:
they're using C++
The fact they are using C++ is not the main problem. The main problem is they are using C++ as if it was Java and in fact most of the code was initially converted from Java, apparently mostly using some tool.
Before you ask why convert from Java to C++: portability reasons. When it comes to mobile platforms, Java is actually useless.
-
When it comes to mobile platforms, Java is actually useless.
There are literally millions of Android users who would disagree...
-
@masonwheeler said in CppUnit:
When it comes to mobile platforms, Java is actually useless.
There are literally millions of Android users who would disagree...
And that flavour of Java isn't portable. If you want a portable language for mobile, I only know of one practical choice: C#.
-
@RaceProUK said in CppUnit:
If you want a portable language for mobile, I only know of one practical choice: C#.
C++ gets you pretty far. Android has the NDK, iOS has (used to have?) ObjectiveC++ (while an abomination, it allows you to mix C++ with ObjectiveC code), and according to a quick google+MSDN, you can use native C++ for mobile development.
So, if you're writing a game engine or something performance sensitive, I'd say that C++ is your best bet.
-
@cvi And now I know of two practical choices
-
@wharrgarbl You can always make a language that compiles to C ;-).
-
@anonymous234 I wanted to find one ready-made, but they always want to implement some kind of garbage collection and put dependencies that are hard to port.
-
@RaceProUK said in CppUnit:
And that flavour of Java isn't portable.
You're there. The size of the big mobile platforms (iOS, Android) is such that they don't care about portability. Working on a single platform can be enough for a product to be viable.
-
@dkf Wasn't the discussion about code portability?
-
@anonymous234 said in CppUnit:
@wharrgarbl You can always make a language that compiles to C ;-).
I've heard ugly rumours about that with respect to C++, actually.
(In fact, it once came up on a job interview, and that day I learned that cfront put the vtable pointer at the end of the object, not at the beginning, meaning it would be in the middle of the derived-class object...)