August 31, 2021
On Tuesday, 31 August 2021 at 16:22:17 UTC, H. S. Teoh wrote:
> However, this simplistic approach falls flat in the face of `dmd -i`.  Schemes like `-unittest=mod1,mod2,...` have been proposed before, but AFAIK never implemented.
>
>
> T

Why is that? couldn't dmd -i simply not compile the module that are "autoloaded" rather than explicitly provided without unittests?
August 31, 2021

On Tuesday, 31 August 2021 at 17:37:34 UTC, deadalnix wrote:

>

Why is that? couldn't dmd -i simply not compile the module that are "autoloaded" rather than explicitly provided without unittests?

It could, but then dmd -i -betterC -unittest -run testrunner.d would not work anymore, where testrunner.d looks like:

module testrunner;

static {
	import moda;
	import modb;
	import modc;
}

alias Seq(T...) = T;

extern(C) int main(int argc, const(char)** argv) {
	foreach(mod; Seq!(moda, modb, modc)) {
		static foreach (test; __traits(getUnitTests, mod)) {
			test();
		}
	}
	return 0;
}
September 02, 2021

On Tuesday, 31 August 2021 at 16:50:07 UTC, Steven Schveighoffer wrote:

>

So for instance, if you link against library X, and you didn't actually build library X with -unittest, then you won't run library X's unittests, only the ones in your project.

So I was curious at to what was meant by this. Let me try to make it explicit why the current behavior is nonsense. I ran something akin to:

$ dmd -m64 -Isrc -w -debug -g -main -unittest -i -run src/somemodule.d
3 modules passed unittests

It is clear that this is running random unitests I don't care about. Module that are brought in via the -i flag are also compiled with their unittests, which is nonsense.

On the other hand, I made an interesting discovery:

$ dmd -m64 -Isrc -w -debug -g -main -unittest -i -run src/module1.d src/module2.d

Will run exclusively the tests for module1.d and ignore module2.d , which is considered an argument to be passed to the main that don't exist and is never run.

This is complete nonsense (and means that I simply run a fraction of my unitests and have no idea how to fix my build to runt hem all).

You'll note that I didn't find a way to get rdmd to do the right thing here, so I'm recompiling everything all the time for no good reason when i want to run the tests, which is also a giant pain in the ass.

>

But my point is, the reason it's done this way is because D uses the build system that C uses -- which has a compiler and a linker as separate steps.

I don't think this is a good reason. There is nothing in the C style build.link model that prevent us from doing the right thing.

>

It's also the reason that cycle detection can't be run until program startup.

Cool, this can be done at startup from module infos. The problem is not at this level. The compiler provide set of flags that provide a sensible behavior. it's all nonsense.

September 02, 2021

On Thursday, 2 September 2021 at 17:26:46 UTC, deadalnix wrote:

>
$ dmd -m64 -Isrc -w -debug -g -main -unittest -i -run src/somemodule.d
3 modules passed unittests

It is clear that this is running random unitests I don't care about. Module that are brought in via the -i flag are also compiled with their unittests, which is nonsense.

This is the only reasonable outcome from this combination of flags. Not everything that ever surprises you is nonsense. If you're not familiar with how dmd works, then being surprised is just part of learning how it works.

>

On the other hand, I made an interesting discovery:

$ dmd -m64 -Isrc -w -debug -g -main -unittest -i -run src/module1.d src/module2.d

Will run exclusively the tests for module1.d and ignore module2.d , which is considered an argument to be passed to the main that don't exist and is never run.

Yep. That's what -run does. It passes the remaining commandline to the program to be run.

>

This is complete nonsense

The only conceivable alternative to this "complete nonsense" is to always require a -- separator, which dub does, which is more an artifact of getopt-style commandline processing than the outcome of a thoughtfully designed CLI.

dub requiring -- just means I never use it directly. Here's my two-line ~/.local/bin/dfmt:

#! /bin/bash
dub run -q --skip-registry=all dfmt -- -i --brace_style=otbs "$@"
>

(and means that I simply run a fraction of my unitests and have no idea how to fix my build to runt hem all).

$ grep . *.d
alsotest.d:unittest {
alsotest.d:    assert(!0);
alsotest.d:}
donttest.d:unittest {
donttest.d:    assert(0);
donttest.d:}
pleasetest.d:unittest {
pleasetest.d:    assert(true);
pleasetest.d:}
$ dmd -c donttest.d; dmd -c -unittest pleasetest.d alsotest.d
$ dmd -main -of=main *.o
$ ./main
2 modules passed unittests
September 02, 2021

On Thursday, 2 September 2021 at 17:51:10 UTC, jfondren wrote:

>

This is the only reasonable outcome from this combination of flags. Not everything that ever surprises you is nonsense. If you're not familiar with how dmd works, then being surprised is just part of learning how it works.

No, it clearly isn't. In fact, there are exactly 0 use case for what this combination of flag is doing and 0 combination of flags for use cases that exist in the wild.

If you don't see the problem, I don't know what to tell you. Maybe "Please do not design any software that is meant to be used by anyone ever, thanks".

>

Yep. That's what -run does. It passes the remaining commandline to the program to be run.

>

This is complete nonsense

The only conceivable alternative to this "complete nonsense" is to always require a -- separator, which dub does, which is more an artifact of getopt-style commandline processing than the outcome of a thoughtfully designed CLI.

Once again, snap out of whatever mindset you are in. This is OBVIOUSLY nonsense because there is NO PROGRAM TO BE RUN. The compiler know this because I had to pass the -main flag to begin with.

There is NO MAIN there is NO EXPECTATION THAT ANY MAIN IS RUN so passing argument to it simply does not make sense.

As Pauli would say, it's not even wrong.

Think of it this way. There is a unitest feature in the language. There are literally no way to tell the compiler "please run the unitests for this set of module". Or if there is one, it is so bizantine that nobody seems to be able to figure it out. This is a 7 pages long thread about it, full of D experts, and yet, nobody knows how to do this simple task.

September 02, 2021

On Thursday, 2 September 2021 at 18:01:34 UTC, deadalnix wrote:

>

On Thursday, 2 September 2021 at 17:51:10 UTC, jfondren wrote:

>

This is the only reasonable outcome from this combination of flags. Not everything that ever surprises you is nonsense. If you're not familiar with how dmd works, then being surprised is just part of learning how it works.

No, it clearly isn't. In fact, there are exactly 0 use case for what this combination of flag is doing and 0 combination of flags for use cases that exist in the wild.

1 use case: run all the tests in all the imported modules. The thing it does.

>

This is OBVIOUSLY nonsense because there is NO PROGRAM TO BE RUN. The compiler know this because I had to pass the -main flag to begin with.

You want -run to treat the commandline completely differently depending on whether -main has been passed? That would help you to have not been surprised in this one case, but by making the CLI more complex it's just going to be more confusing to more people in the long run.

Bug report: I removed -main and suddenly was only testing a single module instead of the several I'd been testing before.

>

Think of it this way. There is a unitest feature in the language. There are literally no way to tell the compiler "please run the unitests for this set of module".

This is fair. There's a lot of machinery set up around testing but there isn't a one-shot command. 'dub test' also isn't such a command, as it's package-oriented rather than module-oriented.

>

Or if there is one, it is so bizantine that nobody seems to be able to figure it out. This is a 7 pages long thread about it, full of D experts, and yet, nobody knows how to do this simple task.

I just demonstrated compiling three modules to only test two of them. This 7 pages long thread has all kinds of talk in it; it is not full of people asking "I have these files; how do I run only these tests in them?" or it'd be full of as many answers. The machinery built up around testing is very good and can be persuaded to work any way you want.

September 02, 2021

On Thursday, 2 September 2021 at 18:15:17 UTC, jfondren wrote:

>

You want -run to treat the commandline completely differently depending on whether -main has been passed? That would help you to have not been surprised in this one case, but by making the CLI more complex it's just going to be more confusing to more people in the long run.

No.

I want a way to run the unitests in a set of module, and only these modules. I don't care about -run, -main or whatever. I care about the fact that there is no sensible combination of these flags that can achieve this.

>

I just demonstrated compiling three modules to only test two of them. This 7 pages long thread has all kinds of talk in it; it is not full of people asking "I have these files; how do I run only these tests in them?" or it'd be full of as many answers. The machinery built up around testing is very good and can be persuaded to work any way you want.

This is certainly possible. Nobody ever argued this wasn't possible. What was argued is that you pretty much have to rollout your own test framework to do this, and that it doesn't compose well when you import 3rd party code, which your demonstration confirms.

The machinery built around testing is absolutely not very good. You can claim it is, but the very fact that you have to raise scafolding that do not compose to do the most basic thing is a demonstration that it isn't. You simply can't argue with facts.

The fact is that all the functionality that are desired to do something sensible exist. There is just no way to plug them into each other in any sensible way because all the utilities and flags provided do some weird shit that is kinda useful but not really.

September 02, 2021

On Thursday, 2 September 2021 at 18:35:48 UTC, deadalnix wrote:

>

The fact is that all the functionality that are desired to do something sensible exist. There is just no way to plug them into each other in any sensible way because all the utilities and flags provided do some weird shit that is kinda useful but not really.

The fact is that dmd is a compiler and not a build system. It therefore has flags that have simple, dumb, easy to compose behaviors rather than too-smart ones that would ever entertain considerations like "There is NO MAIN there is NO EXPECTATION THAT ANY MAIN IS RUN so ---" or "who would ever want what this combination of flags clearly does?"

When you pass -main, dmd adds a module to your build that includes a main function, job done. When you pass -unittest, dmd compiles in unittests and (as of recent versions) even has a somewhat nice default testing framework that provides feedback and skips running main(). When you pass --version, dmd prints out the version number without even asking if the commandline also asked for other stuff to be done.

The alternative to simple dumb flags is not a paradise where dmd always does what everyone expects; it's its own confusing hell where people are constantly surprised by behaviors that are too complex for the outcome to ever be predicted without a week-long course, instead of a quick check of the current manpage where each flag only needs a single sentence for a description.

I think there's an argument to be made that maybe a 'dmd test' should be added to run the tests of a single module. This wouldn't make anything easy that wasn't easy already, but it's a defensible bit of streamlining and it'd support one of D's advantages as a language. I think the very first complaint that someone would raise about it, in all caps, is that the use case of "dmd test a; dmd test b; dmd test c" would incur a lot of recompilation when these modules depend on each other, e.g. c might be built twice without unit tests and then a third time with them.

September 02, 2021

On Thursday, 2 September 2021 at 19:16:38 UTC, jfondren wrote:

>

The fact is that dmd is a compiler and not a build system.
...
I think there's an argument to be made that maybe a 'dmd test' should be added to run the tests of a single module.

Nah, this discussion is meandering due to some frustration and some specific complaints taking the place of the original complaint. If anyone's following this thread, this is a good time to go back to the original post: https://forum.dlang.org/post/rgalgunhtubgeoyrfwxd@forum.dlang.org

Where the use case is roughly

  1. the developer is knee-deep in a big D project with a bunch of dependencies and modules
  2. the developer is doing work on a single module
  3. the developer wants to run that module's tests to confirm that #2 didn't break anything
  4. the developer wants to do this without incurring a "testing!" variant of https://xkcd.com/303/ and without needing a bunch of boilerplate like Unittest_ThisModule version blocks in each module.
September 02, 2021

On Thursday, 2 September 2021 at 19:16:38 UTC, jfondren wrote:

>

The alternative to simple dumb flags is not a paradise where dmd always does what everyone expects; it's its own confusing hell where people are constantly surprised by behaviors that are too complex for the outcome to ever be predicted without a week-long course, instead of a quick check of the current manpage where each flag only needs a single sentence for a description.

This is not the alternative. This what exists today.