test-check

lvh 2016-08-17T02:52:02.000235Z

woop woop 🙂

2016-08-17T02:55:12.000236Z

it's more of a headache than it should be :(

lucasbradstreet 2016-08-17T14:41:13.000237Z

@gfredericks: re our twitter conversation, what’s your solution for generators with high variance? I think maybe it’s ok, because the common case where you’re using parallel testing will be tests passing

lucasbradstreet 2016-08-17T14:42:27.000238Z

if your tests are failing often, then generally parallelism isn’t really all that helpful anyway. Most of the time when I run test.check running overnight in #core JVMs, I do not expect to catch anything

2016-08-17T14:47:16.000239Z

It can slow down even in the passing case

2016-08-17T14:47:29.000240Z

Oh I forgot another goal

2016-08-17T14:47:41.000241Z

Given a seed, the result should be deterministic

2016-08-17T14:48:26.000242Z

So if you're preallocating work you have to give n/t trials to each thread

lucasbradstreet 2016-08-17T14:48:27.000243Z

Yeah, I agree with that goal. That’s why I was saying that you have to partition the space and check whether all threads have passed X, where X is a failing iteration

lucasbradstreet 2016-08-17T14:48:45.000244Z

I can see how it’ll slow down passing cases though

2016-08-17T14:48:52.000245Z

If one thread has lots of slow trials the others will be idle while it finished

lucasbradstreet 2016-08-17T14:48:59.000246Z

Yeah, that’s troublesome

lucasbradstreet 2016-08-17T14:49:08.000247Z

Especially if you have a bunch of tests to run through

2016-08-17T14:49:14.000248Z

So my alg has a queue of trials to run

lucasbradstreet 2016-08-17T14:49:22.000249Z

Generally I’m just running one test overnight, on X cores

lucasbradstreet 2016-08-17T14:49:33.000250Z

So this isn’t a problem, but I see where it’s a problem for a test suite

2016-08-17T14:50:05.000251Z

And the threads just pull them off the queue

lucasbradstreet 2016-08-17T14:50:19.000252Z

I was going to say, a priority queue might be the answer

2016-08-17T14:50:30.000253Z

Priority?

lucasbradstreet 2016-08-17T14:50:36.000254Z

Maybe you don’t even need to prioritise, now that I think about it

2016-08-17T14:50:40.000255Z

Yeah

2016-08-17T14:51:16.000256Z

The other problem I have is deciding how to manage the threads

2016-08-17T14:51:38.000257Z

I suppose I could have it just use N futures...?

lucasbradstreet 2016-08-17T14:51:46.000258Z

You also need to ID the test cases, in case there is some variance in when the cases finish?

2016-08-17T14:51:47.000259Z

Maybe that's best actually

2016-08-17T14:51:58.000260Z

Yes they're ordered

2016-08-17T14:52:40.000261Z

So a lot of complexity comes from when you find the first failure but have to wait for all earlier jobs to finish first

lucasbradstreet 2016-08-17T14:52:51.000262Z

Yep, I can see that

lucasbradstreet 2016-08-17T14:54:05.000263Z

If you use futures, make sure to check for (Thread/interrupted) in the processing loop, so you can cancel the thread reliably after the test is done

2016-08-17T14:57:52.000264Z

yeah cancelling things is a big deal too

2016-08-17T14:58:08.000265Z

I don't know how bad it is to .stop a thread

lucasbradstreet 2016-08-17T14:58:31.000266Z

Yeah, it doesn’t really work well

lucasbradstreet 2016-08-17T14:58:41.000267Z

It’s really up to the thread to behave well

lucasbradstreet 2016-08-17T14:59:07.000268Z

if you check whether you’ve been interrupted in between test iterations, you’ll be fine with just (future-cancel fut)

2016-08-17T14:59:18.000269Z

C-c in nrepl calls .stop I think

lucasbradstreet 2016-08-17T14:59:49.000270Z

future-cancel may do too, but it’s really up to the thread to behave properly

lucasbradstreet 2016-08-17T15:00:47.000271Z

pretty sure thread.stop has been deprecated too

lucasbradstreet 2016-08-17T15:01:15.000272Z

yep, http://stackoverflow.com/questions/16504140/thread-stop-deprecated

2016-08-17T15:01:44.000274Z

yeah that's the entire reason for my hesitation

2016-08-17T15:02:09.000275Z

it's tough in this case to ensure the thread behaves properly though since it's running user code, and so might hang

2016-08-17T15:02:47.000276Z

so if I don't call thread.stop, the caveat to users is "if your test or your generator hangs, you're just going to have an extra thread on your jvm until you restart it, sorry"

lucasbradstreet 2016-08-17T15:03:03.000277Z

if user code hangs, it’s not your problem in my opinion

lucasbradstreet 2016-08-17T15:03:10.000278Z

best you can do is exit between iterations

2016-08-17T15:03:21.000279Z

sure, but users have the expectation that they can C-c their tests and everything stops

2016-08-17T15:03:35.000280Z

what is "exit between iterations"?

lucasbradstreet 2016-08-17T15:04:00.000281Z

I agree, but there’s nothing you can do to guarantee that. User code can always cause situations where that is not true

lucasbradstreet 2016-08-17T15:04:26.000282Z

I mean, a thread will, at minimum, stop between an test iteration

lucasbradstreet 2016-08-17T15:05:42.000283Z

as far as I know, there may be other situations where their code can bail safely, but there can always be other situations where things are blocked and C-c is never going to help

2016-08-17T15:06:12.000285Z

that's true when users are explicitly using threading constructs

lucasbradstreet 2016-08-17T15:06:26.000286Z

when I say “may”, I mean, it depends on their code

2016-08-17T15:06:32.000287Z

but for user code on the main thread I think it's always true that C-c in nrepl stops it

2016-08-17T15:07:11.000288Z

I suppose this discussion overlaps with the "should tests run in parallel by default?" question

lucasbradstreet 2016-08-17T15:09:25.000289Z

Ah yes, I can see how that is important

2016-08-17T15:17:41.000290Z

I think using futures and using an atom to aggregate the results will simplify that code a lot

2016-08-17T15:18:23.000291Z

so I'm glad about that;

2016-08-17T15:19:02.000292Z

I'm a little grumpy about how this interacts with the reporter-fn, since I think that has to be nondeterministic now

2016-08-17T15:19:39.000293Z

and the behavior when the reporter-fn throws an exception is potentially weirder

alexmiller 2016-08-17T18:47:27.000294Z

calling .stop on a thread is bad - it frees all monitors which can badly impact others using them

alexmiller 2016-08-17T18:48:01.000295Z

much preferred to interrupt

2016-08-17T20:07:49.000296Z

@alexmiller: do you think it's a problem that nrepl does it on ctrl-c?

2016-08-17T20:08:28.000297Z

should we be resigned to forcing repl users to restart their jvm if they execute an infinite loop?

2016-08-17T20:09:53.000298Z

I see ctrl-c at the builtin clojure repl just kills the whole jvm

2016-08-17T20:11:26.000299Z

I'm also curious if you have any sense for how realistic the monitor problem is to a user who isn't explicitly using monitors

alexmiller 2016-08-17T20:28:06.000300Z

I don’t know that there is any better solution for nrepl, but that doesn’t make it good

alexmiller 2016-08-17T20:29:35.000301Z

the thread stop thing is a real problem, which is why its deprecated. any code that uses Java locks will be affected and that includes code that is calling into the Clojure runtime in places where synchronization is used (every lazy seq uses synchronization).

alexmiller 2016-08-17T20:31:10.000303Z

that said, typically at the repl, the person typing is the one likely to be affected and they will probably just start over with (mostly) fresh resources

alexmiller 2016-08-17T20:32:42.000304Z

Java Concurrency in Practice is probably the best resource on these problems and their recommended alternatives

2016-08-17T21:44:16.000305Z

Yeah that's about what I thought. Seems like there's not much you can do in a general context where you don't control all the code. I'm surprised it hasn't been worth fixing (or is too hard to fix) on modern jvms