1// Copyright 2014 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
5#include "run_length_encoder.h"
6
7#include <vector>
8#include "elf.h"
9#include "elf_traits.h"
10#include "testing/gtest/include/gtest/gtest.h"
11
12namespace {
13
14void AddRelocation(ELF::Addr addr, std::vector<ELF::Rel>* relocations) {
15  ELF::Rel relocation;
16  relocation.r_offset = addr;
17  relocation.r_info = ELF_R_INFO(0, ELF::kRelativeRelocationCode);
18  relocations->push_back(relocation);
19}
20
21bool CheckRelocation(ELF::Addr addr, const ELF::Rel& relocation) {
22  return relocation.r_offset == addr &&
23      ELF_R_SYM(relocation.r_info) == 0 &&
24      ELF_R_TYPE(relocation.r_info) == ELF::kRelativeRelocationCode;
25}
26
27}  // namespace
28
29namespace relocation_packer {
30
31TEST(RunLength, Encode) {
32  std::vector<ELF::Rel> relocations;
33  std::vector<ELF::Xword> packed;
34
35  RelocationRunLengthCodec codec;
36
37  packed.clear();
38  codec.Encode(relocations, &packed);
39
40  EXPECT_EQ(0, packed.size());
41
42  // Add one relocation (insufficient data to encode).
43  AddRelocation(0xf00d0000, &relocations);
44
45  packed.clear();
46  codec.Encode(relocations, &packed);
47
48  EXPECT_EQ(0, packed.size());
49
50  // Add a second relocation, 4 byte delta (minimum data to encode).
51  AddRelocation(0xf00d0004, &relocations);
52
53  packed.clear();
54  codec.Encode(relocations, &packed);
55
56  EXPECT_EQ(4, packed.size());
57  // One count-delta pair present.
58  EXPECT_EQ(1, packed[0]);
59  // Initial relocation.
60  EXPECT_EQ(0xf00d0000, packed[1]);
61  // Run of a single relocation, 4 byte delta.
62  EXPECT_EQ(1, packed[2]);
63  EXPECT_EQ(4, packed[3]);
64
65  // Add a third relocation, 4 byte delta.
66  AddRelocation(0xf00d0008, &relocations);
67
68  // Add three more relocations, 8 byte deltas.
69  AddRelocation(0xf00d0010, &relocations);
70  AddRelocation(0xf00d0018, &relocations);
71  AddRelocation(0xf00d0020, &relocations);
72
73  packed.clear();
74  codec.Encode(relocations, &packed);
75
76  EXPECT_EQ(6, packed.size());
77  // Two count-delta pairs present.
78  EXPECT_EQ(2, packed[0]);
79  // Initial relocation.
80  EXPECT_EQ(0xf00d0000, packed[1]);
81  // Run of two relocations, 4 byte deltas.
82  EXPECT_EQ(2, packed[2]);
83  EXPECT_EQ(4, packed[3]);
84  // Run of three relocations, 8 byte deltas.
85  EXPECT_EQ(3, packed[4]);
86  EXPECT_EQ(8, packed[5]);
87}
88
89TEST(RunLength, Decode) {
90  std::vector<ELF::Xword> packed;
91  std::vector<ELF::Rel> relocations;
92
93  RelocationRunLengthCodec codec;
94  codec.Decode(packed, &relocations);
95
96  EXPECT_EQ(0, relocations.size());
97
98  // Two count-delta pairs.
99  packed.push_back(2);
100  // Initial relocation.
101  packed.push_back(0xc0de0000);
102  // Run of two relocations, 4 byte deltas.
103  packed.push_back(2);
104  packed.push_back(4);
105  // Run of three relocations, 8 byte deltas.
106  packed.push_back(3);
107  packed.push_back(8);
108
109  relocations.clear();
110  codec.Decode(packed, &relocations);
111
112  EXPECT_EQ(6, relocations.size());
113  // Initial relocation.
114  EXPECT_TRUE(CheckRelocation(0xc0de0000, relocations[0]));
115  // Two relocations, 4 byte deltas.
116  EXPECT_TRUE(CheckRelocation(0xc0de0004, relocations[1]));
117  EXPECT_TRUE(CheckRelocation(0xc0de0008, relocations[2]));
118  // Three relocations, 8 byte deltas.
119  EXPECT_TRUE(CheckRelocation(0xc0de0010, relocations[3]));
120  EXPECT_TRUE(CheckRelocation(0xc0de0018, relocations[4]));
121  EXPECT_TRUE(CheckRelocation(0xc0de0020, relocations[5]));
122}
123
124}  // namespace relocation_packer
125