// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include #include #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_file.h" #include "base/files/scoped_temp_dir.h" #include "base/message_loop/message_loop.h" #include "base/strings/utf_string_conversions.h" #include "chromeos/binder/binder_driver_api.h" #include "chromeos/binder/command_broker.h" #include "chromeos/binder/driver.h" #include "chromeos/binder/local_object.h" #include "chromeos/binder/remote_object.h" #include "chromeos/binder/transaction_data_reader.h" #include "chromeos/binder/writable_transaction_data.h" #include "testing/gtest/include/gtest/gtest.h" namespace binder { TEST(BinderTransactionDataReadWriteTest, Data) { std::vector input(3); for (size_t i = 0; i < input.size(); ++i) { input[i] = i; } WritableTransactionData data; EXPECT_EQ(0u, data.GetDataSize()); data.WriteData(input.data(), input.size()); EXPECT_EQ(4u, data.GetDataSize()); // Padded for 4-byte alignment. for (size_t i = 0; i < input.size(); ++i) { SCOPED_TRACE(i); EXPECT_EQ(input[i], reinterpret_cast(data.GetData())[i]); } TransactionDataReader reader(data); EXPECT_TRUE(reader.HasMoreData()); std::vector result(input.size()); EXPECT_TRUE(reader.ReadData(result.data(), result.size())); EXPECT_EQ(input, result); // Although we read only 3 bytes, we've already consumed 4 bytes because of // padding. EXPECT_FALSE(reader.HasMoreData()); } TEST(BinderTransactionDataReadWriteTest, ScalarValues) { const int32_t kInt32Value = -1; const uint32_t kUint32Value = 2; const int64_t kInt64Value = -3; const uint64_t kUint64Value = 4; const float kFloatValue = 5.55; const double kDoubleValue = 6.66; WritableTransactionData data; data.WriteInt32(kInt32Value); data.WriteUint32(kUint32Value); data.WriteInt64(kInt64Value); data.WriteUint64(kUint64Value); data.WriteFloat(kFloatValue); data.WriteDouble(kDoubleValue); { BufferReader reader(reinterpret_cast(data.GetData()), data.GetDataSize()); { int32_t result = 0; EXPECT_TRUE(reader.Read(&result, sizeof(result))); EXPECT_EQ(kInt32Value, result); } { uint32_t result = 0; EXPECT_TRUE(reader.Read(&result, sizeof(result))); EXPECT_EQ(kUint32Value, result); } { int64_t result = 0; EXPECT_TRUE(reader.Read(&result, sizeof(result))); EXPECT_EQ(kInt64Value, result); } { uint64_t result = 0; EXPECT_TRUE(reader.Read(&result, sizeof(result))); EXPECT_EQ(kUint64Value, result); } { float result = 0; EXPECT_TRUE(reader.Read(&result, sizeof(result))); EXPECT_EQ(kFloatValue, result); } { double result = 0; EXPECT_TRUE(reader.Read(&result, sizeof(result))); EXPECT_EQ(kDoubleValue, result); } EXPECT_FALSE(reader.HasMoreData()); } TransactionDataReader reader(data); EXPECT_TRUE(reader.HasMoreData()); { int32_t result = 0; EXPECT_TRUE(reader.ReadInt32(&result)); EXPECT_EQ(kInt32Value, result); } { uint32_t result = 0; EXPECT_TRUE(reader.ReadUint32(&result)); EXPECT_EQ(kUint32Value, result); } { int64_t result = 0; EXPECT_TRUE(reader.ReadInt64(&result)); EXPECT_EQ(kInt64Value, result); } { uint64_t result = 0; EXPECT_TRUE(reader.ReadUint64(&result)); EXPECT_EQ(kUint64Value, result); } { float result = 0; EXPECT_TRUE(reader.ReadFloat(&result)); EXPECT_EQ(kFloatValue, result); } { double result = 0; EXPECT_TRUE(reader.ReadDouble(&result)); EXPECT_EQ(kDoubleValue, result); } EXPECT_FALSE(reader.HasMoreData()); } TEST(BinderTransactionDataReadWriteTest, CString) { const char kValue[] = "FooBar"; WritableTransactionData data; data.WriteCString(kValue); EXPECT_EQ(8u, data.GetDataSize()); // Padded for 4-byte alignment. { BufferReader reader(reinterpret_cast(data.GetData()), data.GetDataSize()); char result[sizeof(kValue)]; EXPECT_TRUE(reader.Read(&result, sizeof(result))); EXPECT_STREQ(kValue, result); } TransactionDataReader reader(data); const char* result = nullptr; EXPECT_TRUE(reader.ReadCString(&result)); EXPECT_STREQ(kValue, result); EXPECT_FALSE(reader.HasMoreData()); } TEST(BinderTransactionDataReadWriteTest, String) { const std::string kValue = "FooBar"; WritableTransactionData data; data.WriteString(kValue); // 12 = 4 (length) + 6 (string) + 1 (null) + 1 (padding). EXPECT_EQ(12u, data.GetDataSize()); { BufferReader reader(reinterpret_cast(data.GetData()), data.GetDataSize()); int32_t len = 0; EXPECT_TRUE(reader.Read(&len, sizeof(len))); EXPECT_EQ(kValue.size(), len); std::vector result(kValue.size() + 1); EXPECT_TRUE(reader.Read(result.data(), result.size())); EXPECT_EQ(kValue, std::string(result.data(), result.size() - 1)); EXPECT_EQ(0, result.back()); // null-terminated. } TransactionDataReader reader(data); std::string result; EXPECT_TRUE(reader.ReadString(&result)); EXPECT_EQ(kValue, result); EXPECT_FALSE(reader.HasMoreData()); } // Empty string is handled specially. TEST(BinderTransactionDataReadWriteTest, EmptyString) { WritableTransactionData data; data.WriteString(std::string()); EXPECT_EQ(4u, data.GetDataSize()); // Only the length is written. { BufferReader reader(reinterpret_cast(data.GetData()), data.GetDataSize()); int32_t len = 0; EXPECT_TRUE(reader.Read(&len, sizeof(len))); EXPECT_EQ(0, len); EXPECT_FALSE(reader.HasMoreData()); } TransactionDataReader reader(data); std::string result; EXPECT_TRUE(reader.ReadString(&result)); EXPECT_EQ(std::string(), result); EXPECT_FALSE(reader.HasMoreData()); } TEST(BinderTransactionDataReadWriteTest, String16) { const base::string16 kValue = base::ASCIIToUTF16("FooBar"); WritableTransactionData data; data.WriteString16(kValue); // 20 = 4 (length) + 12 (string) + 2 (null) + 2 (padding). EXPECT_EQ(20u, data.GetDataSize()); { BufferReader reader(reinterpret_cast(data.GetData()), data.GetDataSize()); int32_t len = 0; EXPECT_TRUE(reader.Read(&len, sizeof(len))); EXPECT_EQ(kValue.size(), len); std::vector result(kValue.size() + 1); EXPECT_TRUE( reader.Read(result.data(), result.size() * sizeof(base::char16))); EXPECT_EQ(kValue, base::string16(result.data(), result.size() - 1)); EXPECT_EQ(0, result.back()); // null-terminated. } TransactionDataReader reader(data); base::string16 result; EXPECT_TRUE(reader.ReadString16(&result)); EXPECT_EQ(kValue, result); EXPECT_FALSE(reader.HasMoreData()); } TEST(BinderTransactionDataReadWriteTest, Object) { base::MessageLoopForIO message_loop; Driver driver; ASSERT_TRUE(driver.Initialize()); CommandBroker command_broker(&driver); scoped_refptr local( new LocalObject(scoped_ptr())); const int32_t kDummyHandle = 42; scoped_refptr remote( new RemoteObject(&command_broker, kDummyHandle)); // Write a local object & a remote object. WritableTransactionData data; data.WriteObject(local); data.WriteObject(remote); // Check object offsets. ASSERT_EQ(2u, data.GetNumObjectOffsets()); EXPECT_EQ(0u, data.GetObjectOffsets()[0]); EXPECT_EQ(sizeof(flat_binder_object), data.GetObjectOffsets()[1]); { // Check the written local object. BufferReader reader(reinterpret_cast(data.GetData()), data.GetDataSize()); flat_binder_object result = {}; EXPECT_TRUE(reader.Read(&result, sizeof(result))); EXPECT_EQ(BINDER_TYPE_BINDER, result.type); EXPECT_EQ(reinterpret_cast(local.get()), result.cookie); EXPECT_EQ(reinterpret_cast(local.get()), result.binder); // Check the written remote object. EXPECT_TRUE(reader.Read(&result, sizeof(result))); EXPECT_EQ(BINDER_TYPE_HANDLE, result.type); EXPECT_EQ(kDummyHandle, result.handle); } // Read the local object. TransactionDataReader reader(data); scoped_refptr result = reader.ReadObject(&command_broker); ASSERT_TRUE(result); ASSERT_EQ(Object::TYPE_LOCAL, result->GetType()); EXPECT_EQ(local.get(), static_cast(result.get())); // Read the remote object. result = reader.ReadObject(&command_broker); ASSERT_TRUE(result); ASSERT_EQ(Object::TYPE_REMOTE, result->GetType()); EXPECT_EQ(kDummyHandle, static_cast(result.get())->GetHandle()); EXPECT_FALSE(reader.HasMoreData()); } TEST(BinderTransactionDataReadWriteTest, FileDescriptor) { // Prepare a test file. base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); base::FilePath path; ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &path)); base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); ASSERT_TRUE(file.IsValid()); base::ScopedFD scoped_fd(file.TakePlatformFile()); int kFdValue = scoped_fd.get(); // Write the file descriptor. WritableTransactionData data; data.WriteFileDescriptor(std::move(scoped_fd)); // Check object offsets. ASSERT_EQ(1u, data.GetNumObjectOffsets()); EXPECT_EQ(0u, data.GetObjectOffsets()[0]); { // Check the written file descriptor. BufferReader reader(reinterpret_cast(data.GetData()), data.GetDataSize()); flat_binder_object result = {}; EXPECT_TRUE(reader.Read(&result, sizeof(result))); EXPECT_EQ(BINDER_TYPE_FD, result.type); EXPECT_EQ(kFdValue, result.handle); } // Read the file descriptor. TransactionDataReader reader(data); int result = -1; EXPECT_TRUE(reader.ReadFileDescriptor(&result)); EXPECT_EQ(kFdValue, result); } } // namespace binder