August 20, 2021

Still working on my project of a D wrapped for libmpdec (https://www.bytereef.org/mpdecimal/).

Consider the following code:

void main()
{
  mpd_context_t ctx;
  mpd_t* a;
  mpd_ieee_context(&ctx, 128);
  a= mpd_new(&ctx);
}

It seems to work fine. mpd_new is a C function for allocating a new mpdecimal object via
malloc, prototype:

mpd_t *mpd_new(mpd_context_t *ctx);

see the documentation at:

https://www.bytereef.org/mpdecimal/doc/libmpdec/decimals.html?highlight=mpd_new#std:topic-mpd_new

However, if I put the very same code in the unittest section of a module, it fails with
a segmentation fault and I don't understand why!

Personally, I found the unittest mechanism rather obscure. For instance I have tried to debug the problem using gdb and I found that the following code was run
	
module dub_test_root;
2	import std.typetuple;
3	static import mpdec.decimal;
4	static import mpdec.mpdec;
5	alias allModules = TypeTuple!(mpdec.decimal, mpdec.mpdec);
6	
7							import std.stdio;
8							import core.runtime;
9	
10							void main() { writeln("All unit tests have been run successfully."); }
11							shared static this() {
12								version (Have_tested) {
13									import tested;
14									import core.runtime;
15									import std.exception;
16									Runtime.moduleUnitTester = () => true;
17									enforce(runUnitTests!allModules(new ConsoleTestResultWriter), "Unit tests failed.");
18								}
19							}
20	

I didn't even new that this code was there! (and I didn't manage to set a breakpoint
in my unit test, is there a way to do that?). I rather prefer a separate test program!

August 20, 2021

On Friday, 20 August 2021 at 16:02:22 UTC, Pablo De Nápoli wrote:

>

Consider the following code:

void main()
{
  mpd_context_t ctx;
  mpd_t* a;
  mpd_ieee_context(&ctx, 128);
  a= mpd_new(&ctx);
}

It seems to work fine.
...
However, if I put the very same code in the unittest section of a module, it fails with
a segmentation fault and I don't understand why!

unittest blocks are just functions, so this is pretty strange. At a guess, you have some library setup code and are putting that in a module with main() instead of in shared static this() in the module you're getting mpd_new from, so unit testing is skipping this setup code.

>
Personally, I found the unittest mechanism rather obscure. For instance I have tried to debug the problem using gdb and I found that the following code was run
	
module dub_test_root;

...

dub, probably mainly for historical dmd reasons, has some extra steps to make unittests more convenient. You can call dmd directly with -unittest to avoid that, or accept that it's there.

>

I rather prefer a separate test program!

unittest builds are generally separate programs. dub manually removes your main(), but recent dmd also skip it automatically.

If you mean that you'd prefer to have your tests in separate source files, there's nothing stopping you from doing that, you're just going slightly off the beaten path. Probably the easiest way to do it is to have a configuration that excludes your main(), and other configurations that exclude your tests. dcd's dub.json shows this off well with its client/server/library builds: https://github.com/dlang-community/DCD/blob/master/dub.json

Another way to do this is to create a separate 'tests' dub application in a subdirectory which includes all of the library. Whatever works for you.