blob: 8396fc7d18ff6c1fa32ba95d259e9b30bc50c1cf [file] [log] [blame]
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "libtouchraw/parser.h"
#include <string>
#include <base/files/file_util.h>
#include <base/test/task_environment.h>
#include <gtest/gtest.h>
#include "libtouchraw/consumer_interface.h"
#include "libtouchraw/mock_consumers.h"
namespace touchraw {
// TODO: b/275615279 - Add unit tests for ReportDescriptor class.
base::FilePath GetTestDataPath(const std::string& name) {
base::FilePath src = base::FilePath(getenv("SRC"));
src = src.Append("test_data");
return src.Append(name);
}
class ParserTest : public testing::Test {
protected:
void SetUp() override {
auto mock_consumer =
std::make_unique<testing::StrictMock<MockHeatmapChunkConsumer>>();
mock_consumer_ = mock_consumer.get();
parser_ = Parser::CreateForTesting(std::move(mock_consumer));
}
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
MockHeatmapChunkConsumer* mock_consumer_;
std::unique_ptr<Parser> parser_;
};
// Complete report descriptor that supports heat map.
TEST_F(ParserTest, ValidReportDescriptorWithHeatmap) {
hidraw_report_descriptor rpt_desc;
auto buf = base::ReadFileToBytes(GetTestDataPath("report_descriptor.bin"));
ASSERT_TRUE(buf.has_value());
rpt_desc.size = buf->size();
memcpy(rpt_desc.value, buf->data(), buf->size());
EXPECT_TRUE(parser_->ParseHeatmapReportsFromDescriptor(&rpt_desc));
EXPECT_EQ(parser_->usages_.size(), 82);
EXPECT_TRUE(parser_->sync_report_offset_.has_value());
EXPECT_EQ(parser_->usages_[parser_->sync_report_offset_.value()].report_id,
144);
EXPECT_TRUE(parser_->sub_report_offset_.has_value());
EXPECT_EQ(parser_->usages_[parser_->sub_report_offset_.value()].report_id,
145);
// A chunk that has unmatched payload size 5, where the expected size is 7304
// retrieved from the report descriptor.
auto hid_data = std::make_unique<HIDData>(
HIDData{144, // Report id.
{
0x11, 0x22, // Protocol vendor ID.
0x33, 0x44, // Protocol version.
0x55, 0x66, 0x77, 0x88, // Scan time.
0x99, 0xaa, // Sequence ID.
0xbb, 0xcc, 0xdd, 0xee, 0xff, // Frame data.
}});
parser_->ParseHIDData(std::move(hid_data));
// Use heat map report descriptor information to parse a valid first chunk.
parser_->usages_[parser_->sync_report_offset_.value() + 4].data_size = 3;
EXPECT_CALL(*mock_consumer_, Push(testing::_))
.WillOnce([&](std::unique_ptr<const HeatmapChunk> chunk) {
EXPECT_EQ(chunk->vendor_id, 0x2211);
EXPECT_EQ(chunk->protocol_version, 0x4433);
EXPECT_EQ(chunk->scan_time, 0x88776655);
EXPECT_EQ(chunk->byte_count, 0xccbbaa99);
EXPECT_FALSE(chunk->sequence_id.has_value());
EXPECT_EQ(chunk->report_type, ReportType::kFirst);
EXPECT_EQ(chunk->payload.size(), 3);
EXPECT_EQ(chunk->payload[0], 0xdd);
EXPECT_EQ(chunk->payload[1], 0xee);
EXPECT_EQ(chunk->payload[2], 0xff);
});
hid_data = std::make_unique<HIDData>(
HIDData{144, // Report id.
{
0x11, 0x22, // Protocol vendor ID.
0x33, 0x44, // Protocol version.
0x55, 0x66, 0x77, 0x88, // Scan time.
0x99, 0xaa, 0xbb, 0xcc, // Byte count.
0xdd, 0xee, 0xff, // Frame data.
}});
parser_->ParseHIDData(std::move(hid_data));
// Use heat map report descriptor information to parse a valid subsequent
// chunk.
parser_->usages_[parser_->sub_report_offset_.value() + 4].data_size = 5;
EXPECT_CALL(*mock_consumer_, Push(testing::_))
.WillOnce([&](std::unique_ptr<const HeatmapChunk> chunk) {
EXPECT_EQ(chunk->vendor_id, 0x2211);
EXPECT_EQ(chunk->protocol_version, 0x4433);
EXPECT_EQ(chunk->scan_time, 0x88776655);
EXPECT_FALSE(chunk->byte_count.has_value());
EXPECT_EQ(chunk->sequence_id, 0xaa99);
EXPECT_EQ(chunk->report_type, ReportType::kSubsequent);
EXPECT_EQ(chunk->payload.size(), 5);
EXPECT_EQ(chunk->payload[0], 0xbb);
EXPECT_EQ(chunk->payload[1], 0xcc);
EXPECT_EQ(chunk->payload[2], 0xdd);
});
hid_data = std::make_unique<HIDData>(
HIDData{145, // Report id.
{
0x11, 0x22, // Protocol vendor ID.
0x33, 0x44, // Protocol version.
0x55, 0x66, 0x77, 0x88, // Scan time.
0x99, 0xaa, // Sequence ID.
0xbb, 0xcc, 0xdd, 0xee, 0xff, // Frame data.
}});
parser_->ParseHIDData(std::move(hid_data));
}
// Complete report descriptor that does not support heat map.
TEST_F(ParserTest, ValidReportDescriptorWithoutHeatmap) {
hidraw_report_descriptor rpt_desc;
auto buf = base::ReadFileToBytes(
GetTestDataPath("report_descriptor_no_heatmap.bin"));
ASSERT_TRUE(buf.has_value());
rpt_desc.size = buf->size();
memcpy(rpt_desc.value, buf->data(), buf->size());
EXPECT_FALSE(parser_->ParseHeatmapReportsFromDescriptor(&rpt_desc));
EXPECT_EQ(parser_->usages_.size(), 72);
EXPECT_FALSE(parser_->sync_report_offset_.has_value());
EXPECT_FALSE(parser_->sub_report_offset_.has_value());
}
// This report descriptor contains heat map related usages with unknown hid type
// for scan time (report id 144).
TEST_F(ParserTest, UnknownHidType) {
hidraw_report_descriptor rpt_desc;
auto buf = base::ReadFileToBytes(GetTestDataPath("unknown_hid_type.bin"));
ASSERT_TRUE(buf.has_value());
rpt_desc.size = buf->size();
memcpy(rpt_desc.value, buf->data(), buf->size());
EXPECT_TRUE(parser_->ParseHeatmapReportsFromDescriptor(&rpt_desc));
EXPECT_EQ(parser_->usages_.size(), 9);
EXPECT_TRUE(parser_->sync_report_offset_.has_value());
EXPECT_EQ(parser_->usages_[parser_->sync_report_offset_.value()].report_id,
144);
EXPECT_TRUE(parser_->sub_report_offset_.has_value());
EXPECT_EQ(parser_->usages_[parser_->sub_report_offset_.value()].report_id,
145);
// Unsupported report ID.
auto hid_data = std::make_unique<HIDData>(
HIDData{140, // Report id.
{
0x11, 0x22, // Protocol vendor ID.
0x33, 0x44, // Protocol version.
0x55, 0x66, 0x77, 0x88, // Scan time.
0x99, 0xaa, 0xbb, 0xcc, // Byte count.
0xdd, 0xee, 0xff, // Frame data.
}});
parser_->ParseHIDData(std::move(hid_data));
// Report descriptor and data do not match.
parser_->usages_[parser_->sync_report_offset_.value() + 3].data_size = 7;
EXPECT_CALL(*mock_consumer_, Push(testing::_))
.WillOnce([&](std::unique_ptr<const HeatmapChunk> chunk) {
EXPECT_EQ(chunk->vendor_id, 0x2211);
EXPECT_EQ(chunk->protocol_version, 0x4433);
EXPECT_EQ(chunk->scan_time, 0);
EXPECT_EQ(chunk->byte_count, 0x88776655);
EXPECT_FALSE(chunk->sequence_id.has_value());
EXPECT_EQ(chunk->report_type, ReportType::kFirst);
EXPECT_EQ(chunk->payload.size(), 7);
EXPECT_EQ(chunk->payload[0], 0x99);
EXPECT_EQ(chunk->payload[6], 0xff);
});
hid_data = std::make_unique<HIDData>(
HIDData{144, // Report id.
{
0x11, 0x22, // Protocol vendor ID.
0x33, 0x44, // Protocol version.
0x55, 0x66, 0x77, 0x88, // Scan time.
0x99, 0xaa, 0xbb, 0xcc, // Byte count.
0xdd, 0xee, 0xff, // Frame data.
}});
parser_->ParseHIDData(std::move(hid_data));
}
} // namespace touchraw