base::MD5IntermediateFinal() generates digest non-destructively.

MD5Final() modifies the context, which prevents calculating an intermediate
digest while also continuing to build an overall context.

BUG=none

Review URL: https://codereview.chromium.org/211273009

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260731 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/md5_unittest.cc b/base/md5_unittest.cc
index 1112c4b..3e7f2ad5 100644
--- a/base/md5_unittest.cc
+++ b/base/md5_unittest.cc
@@ -204,4 +204,49 @@
   EXPECT_EQ(expected, actual);
 }
 
+// Test that a digest generated by MD5IntermediateFinal() gives the same results
+// as an independently-calculated digest, and also does not modify the context.
+TEST(MD5, IntermediateFinal) {
+  // Independent context over the header.
+  MD5Context check_header_context;
+  MD5Init(&check_header_context);
+
+  // Independent context over entire input.
+  MD5Context check_full_context;
+  MD5Init(&check_full_context);
+
+  // Context intermediate digest will be calculated from.
+  MD5Context context;
+  MD5Init(&context);
+
+  static const char kHeader[] = "header data";
+  static const char kBody[] = "payload data";
+
+  MD5Update(&context, kHeader);
+  MD5Update(&check_header_context, kHeader);
+  MD5Update(&check_full_context, kHeader);
+
+  MD5Digest check_header_digest;
+  MD5Final(&check_header_digest, &check_header_context);
+
+  MD5Digest header_digest;
+  MD5IntermediateFinal(&header_digest, &context);
+
+  MD5Update(&context, kBody);
+  MD5Update(&check_full_context, kBody);
+
+  MD5Digest check_full_digest;
+  MD5Final(&check_full_digest, &check_full_context);
+
+  MD5Digest digest;
+  MD5Final(&digest, &context);
+
+  // The header and full digest pairs are the same, and they aren't the same as
+  // each other.
+  EXPECT_TRUE(!memcmp(&header_digest, &check_header_digest,
+                      sizeof(header_digest)));
+  EXPECT_TRUE(!memcmp(&digest, &check_full_digest, sizeof(digest)));
+  EXPECT_FALSE(!memcmp(&digest, &header_digest, sizeof(digest)));
+}
+
 }  // namespace base