//===- 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)); }