[SPARK-3277] Fix external spilling with LZ4 assertion error

**Summary of the changes**

The bulk of this PR is comprised of tests and documentation; the actual fix is really just adding 1 line of code (see `BlockObjectWriter.scala`). We currently do not run the `External*` test suites with different compression codecs, and this would have caught the bug reported in [SPARK-3277](https://issues.apache.org/jira/browse/SPARK-3277). This PR extends the existing code to test spilling using all compression codecs known to Spark, including `LZ4`.

**The bug itself**

In `DiskBlockObjectWriter`, we only report the shuffle bytes written before we close the streams. With `LZ4`, all the bytes written reported by our metrics were 0 because `flush()` was not taking effect for some reason. In general, compression codecs may write additional bytes to the file after we call `close()`, and so we must also capture those bytes in our shuffle write metrics.

Thanks @mridulm and @pwendell for help with debugging.
A cool trick I used in YarnSparkHadoopUtilSuite is to do something like this:

    def spillingTest(name: String)(testFn: => Unit) = test(name) {
        blah blah blah testFn() blah
    }

Then you can register like this:

    spillingTest("spilling with null keys and values") {
       // body of testSpillingWithNullKeysAndValues
    }

Would look a little bit cleaner overall, but no biggie.