| //===- implTest.cpp -------------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #include "mcld/Support/LEB128.h" |
| #include "LEB128Test.h" |
| |
| #include "mcld/Support/SystemUtils.h" |
| #include <ctime> |
| #include <cstdlib> |
| |
| using namespace mcld; |
| using namespace mcldtest; |
| |
| // Constructor can do set-up work for all test here. |
| LEB128Test::LEB128Test() { |
| // Initialize the seed for random number generator using during the tests. |
| sys::SetRandomSeed(::time(NULL)); |
| } |
| |
| // Destructor can do clean-up work that doesn't throw exceptions here. |
| LEB128Test::~LEB128Test() { |
| } |
| |
| // SetUp() will be called immediately before each test. |
| void LEB128Test::SetUp() { |
| } |
| |
| // TearDown() will be called immediately after each test. |
| void LEB128Test::TearDown() { |
| } |
| |
| //==========================================================================// |
| // Testcases |
| // |
| |
| TEST_F(LEB128Test, EncodeULEB_Example_from_Dwarf3_Figure22_Using_32bits) { |
| leb128::ByteType buffer[2]; |
| leb128::ByteType* result; |
| size_t size; |
| |
| result = buffer; |
| size = leb128::encode<uint32_t>(result, 2); |
| ASSERT_EQ(buffer[0], 2); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<uint32_t>(result, 127); |
| ASSERT_EQ(buffer[0], 127); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<uint32_t>(result, 128); |
| ASSERT_EQ(buffer[0], 0 + 0x80); |
| ASSERT_EQ(buffer[1], 1); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<uint32_t>(result, 129); |
| ASSERT_EQ(buffer[0], 1 + 0x80); |
| ASSERT_EQ(buffer[1], 1); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<uint32_t>(result, 130); |
| ASSERT_EQ(buffer[0], 2 + 0x80); |
| ASSERT_EQ(buffer[1], 1); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<uint32_t>(result, 12857); |
| ASSERT_EQ(buffer[0], 57 + 0x80); |
| ASSERT_EQ(buffer[1], 100); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| } |
| |
| TEST_F(LEB128Test, EncodeULEB_Example_from_Dwarf3_Figure22_Using_64bits) { |
| leb128::ByteType buffer[2]; |
| leb128::ByteType* result; |
| size_t size; |
| |
| result = buffer; |
| size = leb128::encode<uint64_t>(result, 2); |
| ASSERT_EQ(buffer[0], 2); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<uint64_t>(result, 127); |
| ASSERT_EQ(buffer[0], 127); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<uint64_t>(result, 128); |
| ASSERT_EQ(buffer[0], 0 + 0x80); |
| ASSERT_EQ(buffer[1], 1); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<uint64_t>(result, 129); |
| ASSERT_EQ(buffer[0], 1 + 0x80); |
| ASSERT_EQ(buffer[1], 1); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<uint64_t>(result, 130); |
| ASSERT_EQ(buffer[0], 2 + 0x80); |
| ASSERT_EQ(buffer[1], 1); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<uint64_t>(result, 12857); |
| ASSERT_EQ(buffer[0], 57 + 0x80); |
| ASSERT_EQ(buffer[1], 100); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| } |
| |
| TEST_F(LEB128Test, EncodeSLEB_Example_from_Dwarf3_Figure22) { |
| leb128::ByteType buffer[2]; |
| leb128::ByteType* result; |
| size_t size; |
| |
| result = buffer; |
| size = leb128::encode<int32_t>(result, 2); |
| ASSERT_EQ(buffer[0], 2); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<int32_t>(result, -2); |
| ASSERT_EQ(buffer[0], 0x7e); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<int32_t>(result, 127); |
| ASSERT_EQ(buffer[0], 127 + 0x80); |
| ASSERT_EQ(buffer[1], 0); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<int32_t>(result, -127); |
| ASSERT_EQ(buffer[0], 1 + 0x80); |
| ASSERT_EQ(buffer[1], 0x7f); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<int32_t>(result, 128); |
| ASSERT_EQ(buffer[0], 0 + 0x80); |
| ASSERT_EQ(buffer[1], 1); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<int32_t>(result, -128); |
| ASSERT_EQ(buffer[0], 0 + 0x80); |
| ASSERT_EQ(buffer[1], 0x7f); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<int32_t>(result, 129); |
| ASSERT_EQ(buffer[0], 1 + 0x80); |
| ASSERT_EQ(buffer[1], 1); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<int32_t>(result, -129); |
| ASSERT_EQ(buffer[0], 0x7f + 0x80); |
| ASSERT_EQ(buffer[1], 0x7e); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| } |
| |
| TEST_F(LEB128Test, DecodeULEB_Example_from_Dwarf3_Figure22) { |
| leb128::ByteType buffer[2]; |
| size_t size; |
| |
| buffer[0] = 2; |
| buffer[1] = 0; |
| ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 2); |
| ASSERT_TRUE(size == 1); |
| |
| buffer[0] = 127; |
| buffer[1] = 0; |
| ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 127); |
| ASSERT_TRUE(size == 1); |
| |
| buffer[0] = 0 + 0x80; |
| buffer[1] = 1; |
| ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 128); |
| ASSERT_TRUE(size == 2); |
| |
| buffer[0] = 1 + 0x80; |
| buffer[1] = 1; |
| ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 129); |
| ASSERT_TRUE(size == 2); |
| |
| buffer[0] = 2 + 0x80; |
| buffer[1] = 1; |
| ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 130); |
| ASSERT_TRUE(size == 2); |
| |
| buffer[0] = 57 + 0x80; |
| buffer[1] = 100; |
| ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 12857); |
| ASSERT_TRUE(size == 2); |
| } |
| |
| TEST_F(LEB128Test, DecodeSLEB_Example_from_Dwarf3_Figure22) { |
| leb128::ByteType buffer[2]; |
| size_t size; |
| |
| buffer[0] = 2; |
| buffer[1] = 0; |
| ASSERT_EQ(leb128::decode<int64_t>(buffer, size), 2); |
| ASSERT_TRUE(size == 1); |
| |
| buffer[0] = 0x7e; |
| buffer[1] = 0; |
| ASSERT_EQ(leb128::decode<int64_t>(buffer, size), -2); |
| ASSERT_TRUE(size == 1); |
| |
| buffer[0] = 127 + 0x80; |
| buffer[1] = 0; |
| ASSERT_EQ(leb128::decode<int64_t>(buffer, size), 127); |
| ASSERT_TRUE(size == 2); |
| |
| buffer[0] = 1 + 0x80; |
| buffer[1] = 0x7f; |
| ASSERT_EQ(leb128::decode<int64_t>(buffer, size), -127); |
| ASSERT_TRUE(size == 2); |
| |
| buffer[0] = 0 + 0x80; |
| buffer[1] = 1; |
| ASSERT_EQ(leb128::decode<int64_t>(buffer, size), 128); |
| ASSERT_TRUE(size == 2); |
| |
| buffer[0] = 0 + 0x80; |
| buffer[1] = 0x7f; |
| ASSERT_EQ(leb128::decode<int64_t>(buffer, size), -128); |
| ASSERT_TRUE(size == 2); |
| |
| buffer[0] = 1 + 0x80; |
| buffer[1] = 1; |
| ASSERT_EQ(leb128::decode<int64_t>(buffer, size), 129); |
| ASSERT_TRUE(size == 2); |
| |
| buffer[0] = 0x7f + 0x80; |
| buffer[1] = 0x7e; |
| ASSERT_EQ(leb128::decode<int64_t>(buffer, size), -129); |
| ASSERT_TRUE(size == 2); |
| } |
| |
| TEST_F(LEB128Test, DecodeULEB_Tests_Found_in_Android_dalvik_dx) { |
| leb128::ByteType content[2]; |
| const leb128::ByteType* p; |
| |
| content[0] = 0; |
| p = content; |
| ASSERT_TRUE(leb128::decode<uint64_t>(p) == 0); |
| ASSERT_EQ(p, content + 1); |
| |
| content[0] = 1; |
| p = content; |
| ASSERT_TRUE(leb128::decode<uint64_t>(p) == 1); |
| ASSERT_EQ(p, content + 1); |
| |
| content[0] = 0x80; |
| content[1] = 0x7f; |
| p = content; |
| ASSERT_TRUE(leb128::decode<uint64_t>(p) == 16256); |
| ASSERT_EQ(p, content + 2); |
| } |
| |
| TEST_F(LEB128Test, EncodeULEB_Tests_Found_in_Android_dalvik_dx) { |
| leb128::ByteType buffer[5]; |
| leb128::ByteType* result; |
| size_t size; |
| |
| result = buffer; |
| size = leb128::encode<uint32_t>(result, 0); |
| ASSERT_EQ(buffer[0], 0); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<uint64_t>(result, 0); |
| ASSERT_EQ(buffer[0], 0); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<uint32_t>(result, 1); |
| ASSERT_EQ(buffer[0], 1); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<uint64_t>(result, 1); |
| ASSERT_EQ(buffer[0], 1); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<uint32_t>(result, 16256); |
| ASSERT_EQ(buffer[0], 0x80); |
| ASSERT_EQ(buffer[1], 0x7f); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<uint64_t>(result, 16256); |
| ASSERT_EQ(buffer[0], 0x80); |
| ASSERT_EQ(buffer[1], 0x7f); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<uint32_t>(result, 0x3b4); |
| ASSERT_EQ(buffer[0], 0xb4); |
| ASSERT_EQ(buffer[1], 0x07); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<uint64_t>(result, 0x3b4); |
| ASSERT_EQ(buffer[0], 0xb4); |
| ASSERT_EQ(buffer[1], 0x07); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<uint32_t>(result, 0x40c); |
| ASSERT_EQ(buffer[0], 0x8c); |
| ASSERT_EQ(buffer[1], 0x08); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<uint64_t>(result, 0x40c); |
| ASSERT_EQ(buffer[0], 0x8c); |
| ASSERT_EQ(buffer[1], 0x08); |
| ASSERT_EQ(result, buffer + 2); |
| ASSERT_TRUE(size == 2); |
| |
| result = buffer; |
| size = leb128::encode<uint32_t>(result, 0xffffffff); |
| ASSERT_EQ(buffer[0], 0xff); |
| ASSERT_EQ(buffer[1], 0xff); |
| ASSERT_EQ(buffer[2], 0xff); |
| ASSERT_EQ(buffer[3], 0xff); |
| ASSERT_EQ(buffer[4], 0xf); |
| ASSERT_EQ(result, buffer + 5); |
| ASSERT_TRUE(size == 5); |
| |
| result = buffer; |
| size = leb128::encode<uint64_t>(result, 0xffffffff); |
| ASSERT_EQ(buffer[0], 0xff); |
| ASSERT_EQ(buffer[1], 0xff); |
| ASSERT_EQ(buffer[2], 0xff); |
| ASSERT_EQ(buffer[3], 0xff); |
| ASSERT_EQ(buffer[4], 0xf); |
| ASSERT_EQ(result, buffer + 5); |
| ASSERT_TRUE(size == 5); |
| } |
| |
| TEST_F(LEB128Test, DecodeSLEB_Tests_Found_in_Android_dalvik_dx) { |
| leb128::ByteType content[2]; |
| const leb128::ByteType* p; |
| |
| content[0] = 0; |
| p = content; |
| ASSERT_EQ(leb128::decode<int64_t>(p), 0); |
| ASSERT_EQ(p, content + 1); |
| |
| content[0] = 1; |
| p = content; |
| ASSERT_EQ(leb128::decode<int64_t>(p), 1); |
| ASSERT_EQ(p, content + 1); |
| |
| content[0] = 0x7f; |
| p = content; |
| ASSERT_EQ(leb128::decode<int64_t>(p), -1); |
| ASSERT_EQ(p, content + 1); |
| |
| content[0] = 0x3c; |
| p = content; |
| ASSERT_EQ(leb128::decode<int64_t>(p), 0x3c); |
| ASSERT_EQ(p, content + 1); |
| } |
| |
| TEST_F(LEB128Test, EncodeSLEB_Tests_Found_in_Android_dalvik_dx) { |
| leb128::ByteType buffer[5]; |
| leb128::ByteType* result; |
| size_t size; |
| |
| result = buffer; |
| size = leb128::encode<int32_t>(result, 0); |
| ASSERT_EQ(buffer[0], 0); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<int64_t>(result, 0); |
| ASSERT_EQ(buffer[0], 0); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<int32_t>(result, 1); |
| ASSERT_EQ(buffer[0], 1); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<int64_t>(result, 1); |
| ASSERT_EQ(buffer[0], 1); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<int32_t>(result, -1); |
| ASSERT_EQ(buffer[0], 0x7f); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| |
| result = buffer; |
| size = leb128::encode<int64_t>(result, -1); |
| ASSERT_EQ(buffer[0], 0x7f); |
| ASSERT_EQ(result, buffer + 1); |
| ASSERT_TRUE(size == 1); |
| } |
| |
| TEST_F(LEB128Test, Random_Regression_Test) { |
| leb128::ByteType buffer[9]; |
| |
| for (int i = 0; i < 20; i++) { |
| unsigned long int value = sys::GetRandomNum(); |
| uint64_t value2 = value * value; |
| int64_t value3 = value * value; |
| leb128::ByteType* result; |
| size_t encode_size, decode_size; |
| |
| // Test encode<uint32_t> and decode<uint64_t> on value |
| result = buffer; |
| encode_size = leb128::encode<uint32_t>(result, value); |
| ASSERT_EQ(result, buffer + encode_size); |
| ASSERT_EQ(leb128::decode<uint64_t>(buffer, decode_size), value); |
| ASSERT_EQ(encode_size, decode_size); |
| |
| // Test encode<uint64_t> and decode<uint64_t> on (value * value) |
| result = buffer; |
| encode_size = leb128::encode<uint64_t>(result, value2); |
| ASSERT_EQ(result, buffer + encode_size); |
| ASSERT_EQ(leb128::decode<uint64_t>(buffer, decode_size), value2); |
| ASSERT_EQ(encode_size, decode_size); |
| |
| // Test encode<uint64_t> and decode<uint64_t> on (value * value) |
| result = buffer; |
| encode_size = leb128::encode<int64_t>(result, value3); |
| ASSERT_EQ(result, buffer + encode_size); |
| ASSERT_EQ(leb128::decode<int64_t>(buffer, decode_size), value3); |
| ASSERT_EQ(encode_size, decode_size); |
| |
| // Test encode<uint64_t> and decode<uint64_t> on -(value * value) |
| result = buffer; |
| encode_size = leb128::encode<int64_t>(result, -value3); |
| ASSERT_EQ(result, buffer + encode_size); |
| ASSERT_EQ(leb128::decode<int64_t>(buffer, decode_size), -value3); |
| ASSERT_EQ(encode_size, decode_size); |
| } |
| } |
| |
| TEST_F(LEB128Test, Other_Test) { |
| leb128::ByteType buffer[5]; |
| leb128::ByteType* result; |
| size_t size; |
| |
| result = buffer; |
| leb128::encode<uint64_t>(result, 154452); |
| ASSERT_EQ(result, buffer + 3); |
| ASSERT_EQ(buffer[0], 0xd4); |
| ASSERT_EQ(buffer[1], 0xb6); |
| ASSERT_EQ(buffer[2], 0x9); |
| |
| ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 154452); |
| ASSERT_TRUE(size == 3); |
| } |
| |
| TEST_F(LEB128Test, Type_Conversion_Test) { |
| char buffer[5]; |
| char* result; |
| size_t size; |
| |
| result = buffer; |
| leb128::encode<uint64_t>(result, 154452); |
| ASSERT_EQ(result, buffer + 3); |
| ASSERT_EQ(buffer[0], '\xd4'); |
| ASSERT_EQ(buffer[1], '\xb6'); |
| ASSERT_EQ(buffer[2], '\x09'); |
| |
| ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 154452); |
| ASSERT_TRUE(size == 3); |
| |
| const char* p = buffer; |
| ASSERT_TRUE(leb128::decode<uint64_t>(p) == 154452); |
| ASSERT_TRUE(p == (buffer + 3)); |
| } |