Program: 110524
Project: 110524
Buggy source:
/** 
 * Computes and returns the fingerprint for the given NestedSet contents using the given   {@link SerializationContext}, while also associating the contents with the computed fingerprint in the store. Recursively does the same for all transitive members (i.e. Object[] members) of the provided contents.
 */
@VisibleForTesting public FingerprintComputationResult computeFingerprintAndStore(Object[] contents,SerializationContext serializationContext) throws SerializationException, IOException {
  FingerprintComputationResult priorFingerprint=nestedSetCache.fingerprintForContents(contents);
  if (priorFingerprint != null) {
    return priorFingerprint;
  }
  SerializationContext newSerializationContext=serializationContext.getNewMemoizingContext();
  ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
  CodedOutputStream codedOutputStream=CodedOutputStream.newInstance(byteArrayOutputStream);
  ImmutableList.Builder<ListenableFuture<Void>> futureBuilder=ImmutableList.builder();
  try {
    codedOutputStream.writeInt32NoTag(contents.length);
    for (    Object child : contents) {
      if (child instanceof Object[]) {
        FingerprintComputationResult fingerprintComputationResult=computeFingerprintAndStore((Object[])child,serializationContext);
        futureBuilder.add(fingerprintComputationResult.writeStatus());
        newSerializationContext.serialize(fingerprintComputationResult.fingerprint(),codedOutputStream);
      }
 else {
        newSerializationContext.serialize(child,codedOutputStream);
      }
    }
    codedOutputStream.flush();
  }
 catch (  IOException e) {
    throw new SerializationException("String_Node_Str",e);
  }
  byte[] serializedBytes=byteArrayOutputStream.toByteArray();
  ByteString fingerprint=ByteString.copyFrom(Hashing.md5().hashBytes(serializedBytes).asBytes());
  futureBuilder.add(nestedSetStorageEndpoint.put(fingerprint,serializedBytes));
  ListenableFuture<Void> innerWriteFutures=newSerializationContext.createFutureToBlockWritingOn();
  if (innerWriteFutures != null) {
    futureBuilder.add(innerWriteFutures);
  }
  ListenableFuture<Void> writeFuture=Futures.whenAllComplete(futureBuilder.build()).call(() -> null,MoreExecutors.directExecutor());
  FingerprintComputationResult fingerprintComputationResult=FingerprintComputationResult.create(fingerprint,writeFuture);
  nestedSetCache.put(fingerprintComputationResult,contents);
  return fingerprintComputationResult;
}

Fixed version (ground truth):
/** 
 * Computes and returns the fingerprint for the given NestedSet contents using the given   {@link SerializationContext}, while also associating the contents with the computed fingerprint in the store. Recursively does the same for all transitive members (i.e. Object[] members) of the provided contents. <p>We wish to serialize each nested set only once. However, this is not currently enforced, due to the check-then-act race below, where we check nestedSetCache and then, significantly later, insert a result into the cache. This is a bug, but since any thread that redoes unnecessary work will return the   {@link FingerprintComputationResult} containing its own futures, theserialization work that must wait on remote storage writes to complete will wait on the correct futures. Thus it is a performance bug, not a correctness bug.
 */
FingerprintComputationResult computeFingerprintAndStore(Object[] contents,SerializationContext serializationContext) throws SerializationException, IOException {
  FingerprintComputationResult priorFingerprint=nestedSetCache.fingerprintForContents(contents);
  if (priorFingerprint != null) {
    return priorFingerprint;
  }
  SerializationContext newSerializationContext=serializationContext.getNewMemoizingContext();
  ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
  CodedOutputStream codedOutputStream=CodedOutputStream.newInstance(byteArrayOutputStream);
  ImmutableList.Builder<ListenableFuture<Void>> futureBuilder=ImmutableList.builder();
  try {
    codedOutputStream.writeInt32NoTag(contents.length);
    for (    Object child : contents) {
      if (child instanceof Object[]) {
        FingerprintComputationResult fingerprintComputationResult=computeFingerprintAndStore((Object[])child,serializationContext);
        futureBuilder.add(fingerprintComputationResult.writeStatus());
        newSerializationContext.serialize(fingerprintComputationResult.fingerprint(),codedOutputStream);
      }
 else {
        newSerializationContext.serialize(child,codedOutputStream);
      }
    }
    codedOutputStream.flush();
  }
 catch (  IOException e) {
    throw new SerializationException("String_Node_Str",e);
  }
  byte[] serializedBytes=byteArrayOutputStream.toByteArray();
  ByteString fingerprint=ByteString.copyFrom(Hashing.md5().hashBytes(serializedBytes).asBytes());
  futureBuilder.add(nestedSetStorageEndpoint.put(fingerprint,serializedBytes));
  ListenableFuture<Void> innerWriteFutures=newSerializationContext.createFutureToBlockWritingOn();
  if (innerWriteFutures != null) {
    futureBuilder.add(innerWriteFutures);
  }
  ListenableFuture<Void> writeFuture=Futures.whenAllComplete(futureBuilder.build()).call(() -> null,MoreExecutors.directExecutor());
  FingerprintComputationResult fingerprintComputationResult=FingerprintComputationResult.create(fingerprint,writeFuture);
  nestedSetCache.put(fingerprintComputationResult,contents);
  return fingerprintComputationResult;
}