adjustment_method_unittest.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Copyright (c) 2011 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <memory>
  5. #include <sstream>
  6. #include <string>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/bind.h"
  10. #include "base/memory/ptr_util.h"
  11. #include "courgette/assembly_program.h"
  12. #include "courgette/courgette.h"
  13. #include "courgette/encoded_program.h"
  14. #include "courgette/image_utils.h"
  15. #include "courgette/streams.h"
  16. #include "testing/gtest/include/gtest/gtest.h"
  17. namespace courgette {
  18. namespace {
  19. class AdjustmentMethodTest : public testing::Test {
  20. public:
  21. void Test1() const;
  22. private:
  23. void SetUp() {
  24. }
  25. void TearDown() {
  26. }
  27. // Returns one of two similar simple programs. These differ only in Label
  28. // assignment, so it is possible to make them look identical.
  29. std::unique_ptr<AssemblyProgram> MakeProgram(int kind) const {
  30. auto prog = std::make_unique<AssemblyProgram>(EXE_WIN_32_X86, 0x00400000);
  31. RVA kRvaA = 0x00410000;
  32. RVA kRvaB = 0x00410004;
  33. std::vector<RVA> abs32_rvas;
  34. abs32_rvas.push_back(kRvaA);
  35. abs32_rvas.push_back(kRvaB);
  36. std::vector<RVA> rel32_rvas; // Stub.
  37. TrivialRvaVisitor abs32_visitor(abs32_rvas);
  38. TrivialRvaVisitor rel32_visitor(rel32_rvas);
  39. prog->PrecomputeLabels(&abs32_visitor, &rel32_visitor);
  40. Label* labelA = prog->FindAbs32Label(kRvaA);
  41. Label* labelB = prog->FindAbs32Label(kRvaB);
  42. InstructionGenerator gen = base::BindRepeating(
  43. [](Label* labelA, Label* labelB,
  44. InstructionReceptor* receptor) -> CheckBool {
  45. EXPECT_TRUE(receptor->EmitAbs32(labelA));
  46. EXPECT_TRUE(receptor->EmitAbs32(labelA));
  47. EXPECT_TRUE(receptor->EmitAbs32(labelB));
  48. EXPECT_TRUE(receptor->EmitAbs32(labelA));
  49. EXPECT_TRUE(receptor->EmitAbs32(labelA));
  50. EXPECT_TRUE(receptor->EmitAbs32(labelB));
  51. return true;
  52. },
  53. labelA, labelB);
  54. EXPECT_TRUE(prog->AnnotateLabels(gen));
  55. EXPECT_EQ(6U, prog->abs32_label_annotations().size());
  56. EXPECT_EQ(0U, prog->rel32_label_annotations().size());
  57. if (kind == 0) {
  58. labelA->index_ = 0;
  59. labelB->index_ = 1;
  60. } else {
  61. labelA->index_ = 1;
  62. labelB->index_ = 0;
  63. }
  64. prog->AssignRemainingIndexes();
  65. return prog;
  66. }
  67. std::unique_ptr<AssemblyProgram> MakeProgramA() const {
  68. return MakeProgram(0);
  69. }
  70. std::unique_ptr<AssemblyProgram> MakeProgramB() const {
  71. return MakeProgram(1);
  72. }
  73. // Returns a string that is the serialized version of |program| annotations.
  74. std::string Serialize(AssemblyProgram* program) const {
  75. std::ostringstream oss;
  76. for (const Label* label : program->abs32_label_annotations())
  77. oss << "(" << label->rva_ << "," << label->index_ << ")";
  78. oss << ";";
  79. for (const Label* label : program->rel32_label_annotations())
  80. oss << "(" << label->rva_ << "," << label->index_ << ")";
  81. EXPECT_GT(oss.str().length(), 1U); // Ensure results are non-trivial.
  82. return oss.str();
  83. }
  84. };
  85. void AdjustmentMethodTest::Test1() const {
  86. std::unique_ptr<AssemblyProgram> prog1 = MakeProgramA();
  87. std::unique_ptr<AssemblyProgram> prog2 = MakeProgramB();
  88. std::string s1 = Serialize(prog1.get());
  89. std::string s2 = Serialize(prog2.get());
  90. // Don't use EXPECT_EQ because strings are unprintable.
  91. EXPECT_FALSE(s1 == s2); // Unadjusted A and B differ.
  92. std::unique_ptr<AssemblyProgram> prog5 = MakeProgramA();
  93. std::unique_ptr<AssemblyProgram> prog6 = MakeProgramB();
  94. Status can_adjust = Adjust(*prog5, prog6.get());
  95. EXPECT_EQ(C_OK, can_adjust);
  96. std::string s5 = Serialize(prog5.get());
  97. std::string s6 = Serialize(prog6.get());
  98. EXPECT_TRUE(s1 == s5); // Adjustment did not change A (prog5)
  99. EXPECT_TRUE(s5 == s6); // Adjustment did change B into A
  100. }
  101. TEST_F(AdjustmentMethodTest, All) {
  102. Test1();
  103. }
  104. } // namespace
  105. } // namespace courgette