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).


  • Impossible Mission Players - A

    @Bulb said in CppUnit:

    You may guess what happened (we actually have a theory).

    My money is on pointers.



  • @Tsaukpaetra said in CppUnit:

    @Bulb 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"


  • Winner of the 2016 Presidential Election

    @Bulb said in CppUnit:

    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?



  • @gleemonk said in CppUnit:

    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:

    @Bulb 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.

    @asdf said in CppUnit:

    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.

    @gleemonk said in CppUnit:

    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.


  • Discourse touched me in a no-no place

    @Bulb said in CppUnit:

    Yes, that's what we think too.

    So… the test framework isn't doing exactly one read (of each of expected and actual because test authors are TRWTF) and then comparing those?



  • @dkf said in CppUnit:

    @Bulb said in CppUnit:

    Yes, that's what we think too.

    So… the test framework isn't doing exactly one read (of each of expected and actual 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? :wtf: :wtf: :wtf:...)

    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.



  • @dkf said in CppUnit:

    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: :hanzo:'d once again.


  • Discourse touched me in a no-no place

    @cvi said in CppUnit:

    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.



  • @dkf said in CppUnit:

    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? :wtf: :wtf: :wtf: ...

    Well, it is a test of the thread pool library, so it does need concurrency.

    TR:wtf: 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.


  • Discourse touched me in a no-no place

    @Bulb said in CppUnit:

    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.

    :headdesk:



  • @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.


  • Winner of the 2016 Presidential Election

    @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, and class is four five 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 code typename is preferred.



  • @asdf 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#.



  • @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, and class 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 as typename 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 is class, since class T in a template declaration will accept things that aren't classes. I've seen claims that some people use class T to document that T must be a class.


  • Winner of the 2016 Presidential Election

    @wharrgarbl said in CppUnit:

    @asdf 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…



  • @Bulb said in CppUnit:

    @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 used typename in preference to class for template parameter declarations. It's part of C++98.



  • @Bulb said in CppUnit:

    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 :blush:; I'll let you borrow my :pendant: 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.



  • @asdf said in CppUnit:

    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 :man_shrugging:


  • Discourse touched me in a no-no place

    @asdf said in CppUnit:

    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…)


  • Winner of the 2016 Presidential Election

    @dkf said in CppUnit:

    If you really want C, you don't really want those things.

    But then you don't want OOP/RAII either.


  • Discourse touched me in a no-no place

    @asdf said in CppUnit:

    @dkf said in CppUnit:

    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.


  • Winner of the 2016 Presidential Election

    @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?


  • Winner of the 2016 Presidential Election

    @dkf said in CppUnit:

    You leap to conclusions very nicely there.

    What's the point of RAII if there are no exceptions anyway?


  • Discourse touched me in a no-no place

    @asdf said in CppUnit:

    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…



  • @asdf said in CppUnit:

    @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.


  • SockDev

    @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.


  • Winner of the 2016 Presidential Election

    @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. :trolleybus:


    Filed under: Finally another C vs C++ flamewar

  • SockDev

    @asdf said in CppUnit:

    Finally another C vs C++ flamewar

    Oh... Um... Well, this is embarrassing... I only have a C# cannon...


  • Winner of the 2016 Presidential Election

    @RaceProUK said in CppUnit:

    I only have a C# cannon...

    I have a :trolleybus: reply to that, but I think fbmac and me already derailed this thread enough.


  • Impossible Mission - B

    @Steve_The_Cynic said in CppUnit:

    Frankly, my money is on idiots.

    Well, we already know they're using C++... :trolleybus:



  • @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.


  • Impossible Mission - B

    @Bulb said in CppUnit:

    When it comes to mobile platforms, Java is actually useless.

    There are literally millions of Android users who would disagree...


  • SockDev

    @masonwheeler said in CppUnit:

    @Bulb 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.


  • SockDev

    @cvi And now I know of two practical choices :slight_smile:



  • @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.


  • Discourse touched me in a no-no place

    @RaceProUK said in CppUnit:

    And that flavour of Java isn't portable.

    You're :moving_goal_post: 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.


  • SockDev

    @dkf Wasn't the discussion about code portability? :confused:



  • @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...)



Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.