AU: Don't use sparse holes as scratch space in the delta generator.

This patch fixes a number of bugs related to handling of sparse holes
in the context of scratch space in the delta diff generator and adds
appropriate unit tests. Most notably:

- Ignore sparse holes for the purposes of ExtentRanges. This prevents
  the generator from using sparse holes as scratch.

- Adds two unit tests to catch using sparse holes as scratch in a more
  deterministric way.

- Handle correctly sparse holes in
  GraphUtils::AppendBlockToExtents. For example, previously, if one
  adds block 0 to a single-block kSparseHole extent, the extent would
  have been simply extended.

BUG=chromium:238440
TEST=unit tests, trybots

Change-Id: I3fedcc93af319ee741821ad9d1a2a57b7a7d5de2
Reviewed-on: https://gerrit.chromium.org/gerrit/50448
Commit-Queue: Darin Petkov <petkov@chromium.org>
Reviewed-by: Darin Petkov <petkov@chromium.org>
Tested-by: Darin Petkov <petkov@chromium.org>
diff --git a/extent_ranges.cc b/extent_ranges.cc
index a8836c9..5193d3d 100644
--- a/extent_ranges.cc
+++ b/extent_ranges.cc
@@ -20,6 +20,8 @@
 bool ExtentRanges::ExtentsOverlapOrTouch(const Extent& a, const Extent& b) {
   if (a.start_block() == b.start_block())
     return true;
+  if (a.start_block() == kSparseHole || b.start_block() == kSparseHole)
+    return false;
   if (a.start_block() < b.start_block()) {
     return a.start_block() + a.num_blocks() >= b.start_block();
   } else {
@@ -30,6 +32,8 @@
 bool ExtentRanges::ExtentsOverlap(const Extent& a, const Extent& b) {
   if (a.start_block() == b.start_block())
     return true;
+  if (a.start_block() == kSparseHole || b.start_block() == kSparseHole)
+    return false;
   if (a.start_block() < b.start_block()) {
     return a.start_block() + a.num_blocks() > b.start_block();
   } else {
@@ -48,16 +52,18 @@
 namespace {
 
 Extent UnionOverlappingExtents(const Extent& first, const Extent& second) {
+  CHECK_NE(kSparseHole, first.start_block());
+  CHECK_NE(kSparseHole, second.start_block());
   uint64_t start = min(first.start_block(), second.start_block());
   uint64_t end = max(first.start_block() + first.num_blocks(),
                      second.start_block() + second.num_blocks());
   return ExtentForRange(start, end - start);
 }
-  
+
 }  // namespace {}
 
 void ExtentRanges::AddExtent(Extent extent) {
-  if (extent.num_blocks() == 0)
+  if (extent.start_block() == kSparseHole || extent.num_blocks() == 0)
     return;
 
   ExtentSet::iterator begin_del = extent_set_.end();
@@ -100,7 +106,7 @@
 }  // namespace {}
 
 void ExtentRanges::SubtractExtent(const Extent& extent) {
-  if (extent.num_blocks() == 0)
+  if (extent.start_block() == kSparseHole || extent.num_blocks() == 0)
     return;
 
   ExtentSet::iterator begin_del = extent_set_.end();
@@ -111,12 +117,12 @@
        it != e; ++it) {
     if (!ExtentsOverlap(*it, extent))
       continue;
-    
+
     if (begin_del == extent_set_.end())
       begin_del = it;
     end_del = it;
     ++end_del;
-    
+
     del_blocks += it->num_blocks();
 
     ExtentSet subtraction = SubtractOverlappingExtents(*it, extent);