blob: 6eb78d037d53f88a17724fd990abaf82d43f8ea5 [file] [log] [blame] [edit]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <binder/RecordedTransaction.h>
#include <gtest/gtest.h>
#include <utils/Errors.h>
using android::Parcel;
using android::status_t;
using android::binder::unique_fd;
using android::binder::debug::RecordedTransaction;
TEST(BinderRecordedTransaction, RoundTripEncoding) {
android::String16 interfaceName("SampleInterface");
Parcel d;
d.writeInt32(12);
d.writeInt64(2);
Parcel r;
r.writeInt32(99);
timespec ts = {1232456, 567890};
auto transaction = RecordedTransaction::fromDetails(interfaceName, 1, 42, ts, d, r, 0);
EXPECT_TRUE(transaction.has_value());
auto file = std::tmpfile();
auto fd = unique_fd(fcntl(fileno(file), F_DUPFD, 1));
status_t status = transaction->dumpToFile(fd);
ASSERT_EQ(android::NO_ERROR, status);
std::rewind(file);
auto retrievedTransaction = RecordedTransaction::fromFile(fd);
EXPECT_EQ(retrievedTransaction->getInterfaceName(), android::String8(interfaceName).c_str());
EXPECT_EQ(retrievedTransaction->getCode(), 1);
EXPECT_EQ(retrievedTransaction->getFlags(), 42);
EXPECT_EQ(retrievedTransaction->getTimestamp().tv_sec, ts.tv_sec);
EXPECT_EQ(retrievedTransaction->getTimestamp().tv_nsec, ts.tv_nsec);
EXPECT_EQ(retrievedTransaction->getDataParcel().dataSize(), 12);
EXPECT_EQ(retrievedTransaction->getReplyParcel().dataSize(), 4);
EXPECT_EQ(retrievedTransaction->getReturnedStatus(), 0);
EXPECT_EQ(retrievedTransaction->getVersion(), 0);
EXPECT_EQ(retrievedTransaction->getDataParcel().readInt32(), 12);
EXPECT_EQ(retrievedTransaction->getDataParcel().readInt64(), 2);
EXPECT_EQ(retrievedTransaction->getReplyParcel().readInt32(), 99);
}
TEST(BinderRecordedTransaction, Checksum) {
android::String16 interfaceName("SampleInterface");
Parcel d;
d.writeInt32(12);
d.writeInt64(2);
Parcel r;
r.writeInt32(99);
timespec ts = {1232456, 567890};
auto transaction = RecordedTransaction::fromDetails(interfaceName, 1, 42, ts, d, r, 0);
auto file = std::tmpfile();
auto fd = unique_fd(fcntl(fileno(file), F_DUPFD, 1));
status_t status = transaction->dumpToFile(fd);
ASSERT_EQ(android::NO_ERROR, status);
lseek(fd.get(), 9, SEEK_SET);
uint32_t badData = 0xffffffff;
write(fd.get(), &badData, sizeof(uint32_t));
std::rewind(file);
auto retrievedTransaction = RecordedTransaction::fromFile(fd);
EXPECT_FALSE(retrievedTransaction.has_value());
}
TEST(BinderRecordedTransaction, PayloadsExceedPageBoundaries) {
// File contents are read with mmap.
// This test verifies that transactions are read from portions
// of files that cross page boundaries and don't start at a
// page boundary offset of the fd.
const size_t pageSize = sysconf(_SC_PAGE_SIZE);
const size_t largeDataSize = pageSize + 100;
std::vector<uint8_t> largePayload;
uint8_t filler = 0xaa;
largePayload.insert(largePayload.end(), largeDataSize, filler);
android::String16 interfaceName("SampleInterface");
Parcel d;
d.writeInt32(12);
d.writeInt64(2);
d.writeByteVector(largePayload);
Parcel r;
r.writeInt32(99);
timespec ts = {1232456, 567890};
auto transaction = RecordedTransaction::fromDetails(interfaceName, 1, 42, ts, d, r, 0);
auto file = std::tmpfile();
auto fd = unique_fd(fcntl(fileno(file), F_DUPFD, 1));
// Write to file twice
status_t status = transaction->dumpToFile(fd);
ASSERT_EQ(android::NO_ERROR, status);
status = transaction->dumpToFile(fd);
ASSERT_EQ(android::NO_ERROR, status);
std::rewind(file);
for (int i = 0; i < 2; i++) {
auto retrievedTransaction = RecordedTransaction::fromFile(fd);
EXPECT_EQ(retrievedTransaction->getCode(), 1);
EXPECT_EQ(retrievedTransaction->getFlags(), 42);
EXPECT_EQ(retrievedTransaction->getTimestamp().tv_sec, ts.tv_sec);
EXPECT_EQ(retrievedTransaction->getTimestamp().tv_nsec, ts.tv_nsec);
EXPECT_EQ(retrievedTransaction->getDataParcel().dataSize(), d.dataSize());
EXPECT_EQ(retrievedTransaction->getReplyParcel().dataSize(), 4);
EXPECT_EQ(retrievedTransaction->getReturnedStatus(), 0);
EXPECT_EQ(retrievedTransaction->getVersion(), 0);
EXPECT_EQ(retrievedTransaction->getDataParcel().readInt32(), 12);
EXPECT_EQ(retrievedTransaction->getDataParcel().readInt64(), 2);
std::optional<std::vector<uint8_t>> payloadOut;
EXPECT_EQ(retrievedTransaction->getDataParcel().readByteVector(&payloadOut), android::OK);
EXPECT_EQ(payloadOut.value(), largePayload);
EXPECT_EQ(retrievedTransaction->getReplyParcel().readInt32(), 99);
}
}