Unittest for C++ running on an AtMega32a - Page 1
Forum section: electronics / general

author: cedric!
author_rank: Contributor
timestamp: May 28, 2020, 02:08:05 pm
content: Hi All,I've made a workflow to unit test C code for an AtMega32a. I've used a combination of the C test framework "unity" and the AVR simulator "simavr". After I write the C code, I push it to a Gitlab server. The Gitlab server downloads and runs a docker container, installs gccavr, simavr to it, compiles the C code, and then runs the code in Simavr. Simavr pipes the messages from unity from the serial port to the console. When the tests are complete, the gitlab server sends me an e-mail with the results.http://www.throwtheswitch.org/unityhttps://github.com/buserror/simavrNow I would like to do the same, but this time with C++ code. I'm therefore looking for a C++ test suite that:a) Is written in C++, or can be called from C++ codeb) Runs on an AVR microcontrollerc) Can send it's messages to the serial port. (So I can run the code also in a real AtMega32a connected to a serial port of my PC)Do you know of such a suite?Cheers,Cedric

author: thm_w
author_rank: Super Contributor
timestamp: May 28, 2020, 07:55:22 pm
content: Google test and Cpputest are mentioned here:https://interrupt.memfault.com/blog/unit-testing-basicsBut I don't know if they run on avr.

author: westfw
author_rank: Super Contributor
timestamp: May 29, 2020, 03:26:27 am
content: QuoteSo... What's wrong with your existing C test code? C code is "very compatible" with C++, especially at the sort of pre-processor level where I thought that most of the Unity stuff happened. Unity already has the ""extern C" stuff around the declarations... The C serial code should work fine too.

author: chriva
author_rank: Regular Contributor
timestamp: May 29, 2020, 03:50:49 am
content: I really can't recommend C++ on a a 8-bit.Any of the new things that would actually make it worthwhile is barely functional or very slow on them. Not to mention the stuff that is not working.You basically only have C with some of C++' glue available so westfw's suggestion is by far the simplest. Apply KISS

author: hans
author_rank: Super Contributor
timestamp: May 29, 2020, 07:07:22 am
content: I think the point of unit testing is that you can testfunctionalityof code (not hardware side-effects and timing)outside the environmentit's used in. For example, you can define repeatable test environments in a testbench. This is probably easier to do in C++ than in C, depending on how you structure your code and how much 'overhead' you tolerate ofcourse.I don't think it's necessary for a whole unittest framework to run on the target device. I'm pretty sure GoogleTest won't work on an AVR, as in my experience the C++ AVR GCC compiler lacks extensive STL support of C++ (due to dynamic memory allocations). In addition, Googletest makes heavy use of exceptions and whatnot that are very expensive on a microcontroller to implement.I use GoogleTest myself for C++ embedded code that I target to ARM chips, but I'm pretty sure it can be applied to AVR as well. However, I run the GoogleTest in a x86 PC environment, with either hardware abstractions or mock data collected from simulators.

author: andersm
author_rank: Super Contributor
timestamp: May 29, 2020, 09:22:11 am
content: Quote from: hans on May 29, 2020, 07:07:22 amWhich brings us to the question, why test on the device in the first place?

author: cdwijs
author_rank: Regular Contributor
timestamp: May 29, 2020, 10:30:38 am
content: Quote from: andersm on May 29, 2020, 09:22:11 amMy reasons to run my unit tests also on the real uC (without the surrounding hardware)-This is the closest to the real situation. If my unit tests work on the real uC, but not on the simulated uC, it's time to look what's wrong with (in my case) simavr.-I have access to a real PCB, with the real uC and a debugger. This allows me to step through the code without having to learn anything new (I'm used to debug by stepping code on the real device)My reasons to run my unit tests also on the simulated micro controller (using simavr)-This allows me to automatically run the unit tests in a docker container, triggered by a git commit of my code. This makes sure the unit tests are actually run, as I'm too lazy to hook up the real uC with every git commit.My reasons to run my unit tests also natively on an AMD64 machine:-This does not require me to setup simavr, so it takes less steps to setup the environment. It also enables unit tests that consume much more CPU and RAM. The downside is that the unit tests say less about the target processor, but more about how portable the C routines are between the microcontroller and the AMD64 machine.My main reason to do unit tests on the actual hardware is to test my simulator

author: cdwijs
author_rank: Regular Contributor
timestamp: May 29, 2020, 10:47:32 am
content: Quote from: westfw on May 29, 2020, 03:26:27 amThank you. I've made a minimal program, you can check it out here:https://github.com/cdwijs/cpp_unit_testI can't get it to work yet. I don't know yet howto call the test routines. For normal C unit tests I can call them like this in main():Code:int main(void){int numfailedtests=0;UNITY_BEGIN();RUN_TEST(parLcdExecuteTest);numfailedtests = UNITY_END();}The following stuff gives various errors:Code:int main(void){UNITY_BEGIN();//RUN_TEST(myPrivate.executeTest); //unity_internals.h(707,65): error: invalid use of non-static member function//RUN_TEST((void*)myPrivate.executeTest); //error: invalid use of member function (did you forget the '()' ?)//RUN_TEST((func)))myPrivate.executeTest); //error: 'func' was not declared in this scope//RUN_TEST(&myPrivate.executeTest); //error: cannot convert 'void (Private::*)()' to 'UnityTestFunction {aka void (*)()}' for argument '1' to 'void UnityDefaultTestRun(UnityTestFunction, const char*, int)'UNITY_END();myPrivate.more();myPrivate.more();myPrivate.less();/* Replace with your application code */while (1){}}Any idea's?

author: cdwijs
author_rank: Regular Contributor
timestamp: May 29, 2020, 10:57:13 am
content: Quote from: chriva on May 29, 2020, 03:50:49 amAgreed. My colleague however has made a c++ program for a uC, and I'm trying to show him howto create unit tests for it.

author: ejeffrey
author_rank: Super Contributor
timestamp: May 29, 2020, 05:59:55 pm
content: Quote from: chriva on May 29, 2020, 03:50:49 amDepending what version of C and C++ your compiler supports and how good your C++ compiler is, C++ can also just be used as "C with some nice syntactic sugar", which is fine for an 8 bit micro that is big enough to support standard C. That is basically what arduino does (arduino libraries are pretty heavy weight given their target, but that is not the fault of the language). C++ is designed so that -- compiler allowing -- you don't pay overhead for features you don't use. A lot of compilers have not really reached this ideal, but then usually provide options to turn off features (like exceptions) that can cause lots of overhead.It may not be worth it to you given the limitations of the platform, and I generally wouldn't choose to use C++ on such a platform myself, but I wouldn't tell someone with working C++ code that they shouldn't do it.Even some language features that can be very problematic on constrained platforms -- such as templates -- can be used carefully and be useful. I can certainly see the argument that since it is so easy to get into trouble those features aren't well suited to memory and flash constrained platforms, but others may find it worth the effort.

author: cv007
author_rank: Frequent Contributor
timestamp: May 29, 2020, 06:11:08 pm
content: >I really can't recommend C++ on a a 8-bit.I'm not on the c++ enforcement committee, and I mostly don't care what anyone else uses to get the pins to wiggle, and I don't want to take a whack at every 'c++ is not good' comment on the internet, but maybe I need to whack one once in a while for practice...I think c++ works great on 8 bit or any other bits, and I would recommend it. There can be reasons not to use, but its not because '8 bits'. Many that recommend against it have never tried it, and that may not be the case here, but many times it is. The avr has no big c++ things available for it, so you are left with the smaller toolbox, but there are still plenty of nice tools in that toolbox.One advantage that may apply to this thread, is c++ can have enum types, which means function arguments can be essentially asserted at compile time. That can be used is many cases and reduce the need to assert in the first place. You can also do compile time assertions in other ways- for example I can set the cpu speed and have a compile time assertion if I chose something that cannot be done with the current fuse settings. For things that cannot be compile time asserted, I just make a decision about what to do if I get value out of range, and it is taken care of (most likely has to be dealt with at runtime anyway).a quick, simple example for a mega328-https://godbolt.org/z/4Ai487the resulting code is as small as any c/asm programmer could do with the benefit you no longer have to deal with the normal bit set/clear code and its associated defines and all the |= &=~ symbols.At the bottom of that example is the C equivalent, and ends up with theexactsame code produced. You could make that c code a little nicer, but you most likely will end up with a set of macros in addition to your pin defines.I have c++ header only drivers for almost every peripheral for any avr0/1, and it makes everything so much simpler to use. The code is simple also (1 datasheet chapter = 1 peripheral = 1 header file, so you are 1 file away from seeing the source).So, c++ can be a good thing even for 8 bits. Me thinks.

author: thm_w
author_rank: Super Contributor
timestamp: May 29, 2020, 08:09:17 pm
content: Quote from: cv007 on May 29, 2020, 06:11:08 pmGood examples.Would love to see vendors release some C++ header files for their micros. But I suppose the issue is its going to then fork headers into C and C++ versions, which means twice the maintenance.