May 23

If this Program

module foo_bar;

unittest {
   assert (1 == 2);
}

is stored under the name foo_bar.d one gets what is expected:

$ dmd -checkaction=context -unittest -main -run foo_bar.d
foo_bar.d(4): [unittest] 1 != 2
1/1 modules FAILED unittests

However, if the module name differs from the filename [1] an additional core dump is generated:

dmd -checkaction=context -unittest -main -run foo-bar.d
core.exception.AssertError@foo-bar.d(4): 1 != 2
----------------
??:? _d_unittest_msg [0x445158]
??:? void foo_bar.__unittest_L3_C1() [0x43cb14]
??:? void foo_bar.__modtest() [0x43d924]
??:? int core.runtime.runModuleUnitTests().__foreachbody_L600_C5(object.ModuleInfo*) [0x44e8e6]
??:? int object.ModuleInfo.opApply(scope int delegate(object.ModuleInfo*)).__lambda_L2459_C13(immutable(object.ModuleInfo*)) [0x44bd1b]
??:? int rt.minfo.moduleinfos_apply(scope int delegate(immutable(object.ModuleInfo*))).__foreachbody_L584_C5(ref rt.sections_elf_shared.DSO) [0x4549ab]
??:? int rt.sections_elf_shared.DSO.opApply(scope int delegate(ref rt.sections_elf_shared.DSO)) [0x454e7d]
??:? int rt.minfo.moduleinfos_apply(scope int delegate(immutable(object.ModuleInfo*))) [0x454939]
??:? int object.ModuleInfo.opApply(scope int delegate(object.ModuleInfo*)) [0x44bced]
??:? runModuleUnitTests [0x44e71b]
??:? void rt.dmain2._d_run_main2(char[][], ulong, extern (C) int function(char[][])*).runAll() [0x447134]
??:? void rt.dmain2._d_run_main2(char[][], ulong, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x4470c1]
??:? _d_run_main2 [0x44702a]
??:? _d_run_main [0x446e13]
??:? main [0x43d93b]
??:? __libc_start_main [0x7ffff700e585]
../sysdeps/x86_64/elf/start.S:113 [0x43c9f8]
1/1 modules FAILED unittests

[1] https://dlang.org/spec/module.html#module_declaration

May 23

On Friday, 23 May 2025 at 06:42:02 UTC, kdevel wrote:

>

is stored under the name foo_bar.d one gets what is expected:

That's interesting, I didn't realize it ever did that.... but

>

However, if the module name differs from the filename [1] an additional core dump is generated:

Yeah, this annoyed me in opend recently too and I pushed a fix for it just earlier this week:

 https://github.com/opendlang/opend/commit/da79e82c6507b81798c2de73c7d8ff47397e8914#diff-9a6dcca83f85a8a48ac3437327e62f02d6e9c1394e6cfc0f43c9cf4304ac98a2R126-R245

See where that isModTest function is called for this specific thing (I also wanted to generally compress things that are irrelevant to the end user in that whole commit so there's a couple other things too).

The opend output for your same program:

```
core.exception.AssertError@foo_bar.d(4): 1 != 2
----------------
  ??:? _d_unittest_msg [0x43f630]
  ./foo_bar.d:4 foo_bara.__unittest_L3_C1() [0x437760]
1/1 modules FAILED unittests
```

So yes, there's a stacktrace, but it stops at the module unittest - same as it stops at main() for normal program run exceptions - which makes it look a lot less spammy.

I'm scheduled to release a blog post on Monday detailing the other enhancements in this release so i'll save the rest for then.

But I didn't realize the module name mattered.... and yeah that behavior is present in opend too (no surprise really, opend druntime differs from upstream mostly in the added Emscripten and Freestanding support, and the merger of dmd and ldc codebases, the actual function contents mostly are the same).

And here it is:

src/core/runtime.d line 618 in opend master:

```
            if ( typeid(e) == typeid(AssertError) )
            {
                // Crude heuristic to figure whether the assertion originates in
                // the unittested module. TODO: improve.
                auto moduleName = m.name;
                if (moduleName.length && e.file.length > moduleName.length
                    && e.file[0 .. moduleName.length] == moduleName)
                {
```

Eh, I like the opend result better, it applies to all exceptions, tempting to just delete this hack entirely instead of trying to fix it more.