15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/third_party/bsdiff.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/base_test_unittest.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/courgette.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/streams.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BSDiffMemoryTest : public BaseTest {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GenerateAndTestPatch(const std::string& a, const std::string& b) const;
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GenerateSyntheticInput(size_t length, int seed) const;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BSDiffMemoryTest::GenerateAndTestPatch(const std::string& old_text,
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const std::string& new_text) const {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  courgette::SourceStream old1;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  courgette::SourceStream new1;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  old1.Init(old_text.c_str(), old_text.length());
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new1.Init(new_text.c_str(), new_text.length());
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  courgette::SinkStream patch1;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  courgette::BSDiffStatus status = CreateBinaryPatch(&old1, &new1, &patch1);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(courgette::OK, status);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  courgette::SourceStream old2;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  courgette::SourceStream patch2;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  old2.Init(old_text.c_str(), old_text.length());
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  patch2.Init(patch1);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  courgette::SinkStream new2;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  status = ApplyBinaryPatch(&old2, &patch2, &new2);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(courgette::OK, status);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(new_text.length(), new2.Length());
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, memcmp(new_text.c_str(), new2.Buffer(), new_text.length()));
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string BSDiffMemoryTest::GenerateSyntheticInput(size_t length, int seed)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* a[8] = {"O", "A", "x", "-", "y", ".", "|", ":"};
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string result;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (result.length() < length) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    seed = (seed + 17) * 1049 + (seed >> 27);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append(a[seed & 7]);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result.resize(length);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(BSDiffMemoryTest, TestEmpty) {
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GenerateAndTestPatch(std::string(), std::string());
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(BSDiffMemoryTest, TestEmptyVsNonempty) {
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GenerateAndTestPatch(std::string(), "xxx");
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(BSDiffMemoryTest, TestNonemptyVsEmpty) {
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GenerateAndTestPatch("xxx", std::string());
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(BSDiffMemoryTest, TestSmallInputsWithSmallChanges) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file1 =
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I would not, could not, in a box.\n"
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I could not, would not, with a fox.\n"
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I will not eat them with a mouse.\n"
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I will not eat them in a house.\n"
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I will not eat them here or there.\n"
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I will not eat them anywhere.\n"
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I do not eat green eggs and ham.\n"
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I do not like them, Sam-I-am.\n";
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file2 =
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I would not, could not, in a BOX.\n"
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I could not, would not, with a FOX.\n"
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I will not eat them with a MOUSE.\n"
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I will not eat them in a HOUSE.\n"
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I will not eat them in a HOUSE.\n"     // Extra line.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I will not eat them here or THERE.\n"
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I will not eat them ANYWHERE.\n"
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I do not eat green eggs and HAM.\n"
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "I do not like them, Sam-I-am.\n";
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateAndTestPatch(file1, file2);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(BSDiffMemoryTest, TestNearPageArrayPageSize) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This magic number is the size of one block of the PageArray in
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // third_party/bsdiff_create.cc.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t critical_size = 1 << 18;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test first-inputs with sizes that straddle the magic size to test this
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PageArray's internal boundary condition.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file1 = GenerateSyntheticInput(critical_size, 0);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file2 = GenerateSyntheticInput(critical_size, 1);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateAndTestPatch(file1, file2);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file1a = file1.substr(0, critical_size - 1);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateAndTestPatch(file1a, file2);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file1b = file1.substr(0, critical_size - 2);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateAndTestPatch(file1b, file2);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file1c = file1 + file1.substr(0, 1);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateAndTestPatch(file1c, file2);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(BSDiffMemoryTest, TestIndenticalDlls) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file1 = FileContents("en-US.dll");
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateAndTestPatch(file1, file1);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(BSDiffMemoryTest, TestDifferentExes) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file1 = FileContents("setup1.exe");
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file2 = FileContents("setup2.exe");
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateAndTestPatch(file1, file2);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(BSDiffMemoryTest, TestDifferentElfs) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file1 = FileContents("elf-32-1");
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file2 = FileContents("elf-32-2");
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GenerateAndTestPatch(file1, file2);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
126