Avoid double `done` call in `join` and add tests

Some iterators might mutate their state in the `done()` method (eg Task)
and that will give wrong results when `join` calls `done` twice per
iteration. This fixes that, and add a few tests to `join` that were
missing.

Fixes #9178