blob: e378d530a27667d2e2b942a2af974572b4ceb382 [file] [log] [blame]
/*
* Copyright (C) 2021 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 "test/gtest_and_gmock.h"
#include "perfetto/ext/base/hash.h"
#include "perfetto/protozero/packed_repeated_fields.h"
#include "perfetto/protozero/scattered_heap_buffer.h"
#include "src/protozero/filtering/filter_bytecode_common.h"
#include "src/protozero/filtering/filter_bytecode_parser.h"
namespace protozero {
namespace {
bool LoadBytecode(FilterBytecodeParser* parser,
std::initializer_list<uint32_t> bytecode) {
perfetto::base::Hasher hasher;
protozero::PackedVarInt words;
for (uint32_t w : bytecode) {
words.Append(w);
hasher.Update(w);
}
words.Append(static_cast<uint32_t>(hasher.digest()));
return parser->Load(words.data(), words.size());
}
TEST(FilterBytecodeParserTest, ParserSimpleFields) {
FilterBytecodeParser parser;
EXPECT_FALSE(parser.Load(nullptr, 0));
EXPECT_FALSE(parser.Query(42, 42).allowed);
EXPECT_TRUE(LoadBytecode(&parser, {}));
EXPECT_FALSE(parser.Query(0, 0).allowed);
EXPECT_FALSE(parser.Query(0, 0xffffffff).allowed);
EXPECT_FALSE(parser.Query(1, 0).allowed);
EXPECT_FALSE(parser.Query(0, 1).allowed);
EXPECT_FALSE(parser.Query(1, 1).allowed);
EXPECT_FALSE(parser.Query(42, 42).allowed);
// An invalid field_id (0) in bytecode should cause a parse failure.
EXPECT_FALSE(LoadBytecode(
&parser, {kFilterOpcode_SimpleField | 0, kFilterOpcode_EndOfMessage}));
// A valid bytecode that has only one field.
EXPECT_TRUE(LoadBytecode(&parser, {kFilterOpcode_SimpleField | (2u << 3),
kFilterOpcode_EndOfMessage}));
EXPECT_FALSE(parser.Query(0, 0).allowed);
EXPECT_FALSE(parser.Query(0, 1).allowed);
EXPECT_TRUE(parser.Query(0, 2).allowed);
EXPECT_TRUE(parser.Query(0, 2).simple_field());
EXPECT_TRUE(parser.Query(0, 2).allowed);
EXPECT_FALSE(parser.Query(0, 3).allowed);
EXPECT_FALSE(parser.Query(1, 1).allowed);
EXPECT_FALSE(parser.Query(1, 2).allowed);
EXPECT_FALSE(parser.Query(1, 3).allowed);
// A valid bytecode that has few sparse fields < 128.
EXPECT_TRUE(LoadBytecode(&parser, {kFilterOpcode_SimpleField | (1u << 3),
kFilterOpcode_SimpleField | (7u << 3),
kFilterOpcode_SimpleField | (8u << 3),
kFilterOpcode_SimpleField | (127u << 3),
kFilterOpcode_EndOfMessage}));
EXPECT_FALSE(parser.Query(0, 0).allowed);
EXPECT_TRUE(parser.Query(0, 1).allowed);
EXPECT_FALSE(parser.Query(0, 2).allowed);
EXPECT_FALSE(parser.Query(0, 3).allowed);
EXPECT_FALSE(parser.Query(0, 6).allowed);
EXPECT_TRUE(parser.Query(0, 7).allowed);
EXPECT_TRUE(parser.Query(0, 8).allowed);
EXPECT_FALSE(parser.Query(0, 9).allowed);
EXPECT_FALSE(parser.Query(0, 126).allowed);
EXPECT_TRUE(parser.Query(0, 127).allowed);
EXPECT_FALSE(parser.Query(0, 128).allowed);
// A valid bytecode that has only fields > 128.
EXPECT_TRUE(LoadBytecode(&parser, {kFilterOpcode_SimpleField | (1000u << 3),
kFilterOpcode_SimpleField | (1001u << 3),
kFilterOpcode_SimpleField | (2000u << 3),
kFilterOpcode_EndOfMessage}));
for (uint32_t i = 0; i < 1000; ++i)
EXPECT_FALSE(parser.Query(0, i).allowed);
EXPECT_TRUE(parser.Query(0, 1000).allowed);
EXPECT_TRUE(parser.Query(0, 1001).allowed);
EXPECT_FALSE(parser.Query(0, 1002).allowed);
EXPECT_FALSE(parser.Query(0, 1999).allowed);
EXPECT_TRUE(parser.Query(0, 2000).allowed);
EXPECT_FALSE(parser.Query(0, 2001).allowed);
}
TEST(FilterBytecodeParserTest, ParserSimpleRanges) {
FilterBytecodeParser parser;
// Invalid, range length missing.
EXPECT_FALSE(
LoadBytecode(&parser, {
kFilterOpcode_SimpleFieldRange | (2u << 3),
}));
// Borderline valid: range length = 0.
EXPECT_TRUE(
LoadBytecode(&parser, {kFilterOpcode_SimpleFieldRange | (2u << 3), 0u,
kFilterOpcode_SimpleFieldRange | (127u << 3), 0u,
kFilterOpcode_SimpleFieldRange | (128u << 3), 0u,
kFilterOpcode_SimpleFieldRange | (128u << 3), 0u,
kFilterOpcode_EndOfMessage}));
for (uint32_t i = 0; i < 130; ++i)
EXPECT_FALSE(parser.Query(0, i).allowed) << i;
// A valid bytecode with two ranges [2,2], [10, 14].
EXPECT_TRUE(
LoadBytecode(&parser, {kFilterOpcode_SimpleFieldRange | (2u << 3),
1u, // length of the range,
kFilterOpcode_SimpleFieldRange | (10u << 3),
5u, // length of the range,
kFilterOpcode_EndOfMessage}));
EXPECT_FALSE(parser.Query(0, 0).allowed);
EXPECT_FALSE(parser.Query(0, 1).allowed);
EXPECT_TRUE(parser.Query(0, 2).allowed);
EXPECT_TRUE(parser.Query(0, 2).simple_field());
EXPECT_FALSE(parser.Query(0, 3).allowed);
EXPECT_FALSE(parser.Query(0, 9).allowed);
for (uint32_t i = 10; i <= 14; ++i)
EXPECT_TRUE(parser.Query(0, i).allowed);
EXPECT_FALSE(parser.Query(0, 15).allowed);
}
TEST(FilterBytecodeParserTest, ParserSimpleFieldsAndRanges) {
FilterBytecodeParser parser;
// Borderline valid: range length = 0.
EXPECT_TRUE(
LoadBytecode(&parser, {kFilterOpcode_SimpleFieldRange | (1u << 3),
2u, // [1,2]
kFilterOpcode_SimpleField | (4u << 3),
kFilterOpcode_SimpleFieldRange | (126u << 3),
4u, // [126, 129]
kFilterOpcode_SimpleField | (150u << 3),
kFilterOpcode_EndOfMessage}));
EXPECT_TRUE(parser.Query(0, 1).allowed);
EXPECT_TRUE(parser.Query(0, 2).allowed);
EXPECT_FALSE(parser.Query(0, 3).allowed);
EXPECT_TRUE(parser.Query(0, 4).allowed);
EXPECT_FALSE(parser.Query(0, 5).allowed);
EXPECT_FALSE(parser.Query(0, 125).allowed);
for (uint32_t i = 126; i <= 129; ++i)
EXPECT_TRUE(parser.Query(0, i).allowed) << i;
EXPECT_FALSE(parser.Query(0, 130).allowed);
EXPECT_TRUE(parser.Query(0, 150).allowed);
}
TEST(FilterBytecodeParserTest, ParserNestedMessages) {
FilterBytecodeParser parser;
// Invalid because there are 1 messages in total, and message index 1 is
// out of range.
EXPECT_FALSE(LoadBytecode(&parser, {kFilterOpcode_NestedField | (4u << 3),
1u, // message index
kFilterOpcode_EndOfMessage}));
// A valid bytecode consisting of 4 message, with recursive / cylical
// dependencies between them.
EXPECT_TRUE(LoadBytecode(
&parser, {
// Message 0 (root).
kFilterOpcode_SimpleFieldRange | (1u << 3),
2u, // [1,2]
kFilterOpcode_NestedField | (4u << 3),
3u, // message index
kFilterOpcode_SimpleField | (10u << 3),
kFilterOpcode_NestedField | (127u << 3),
1u, // message index
kFilterOpcode_NestedField | (128u << 3),
2u, // message index
kFilterOpcode_EndOfMessage,
// Message 1.
kFilterOpcode_NestedField | (2u << 3),
1u, // message index (recurse onto itself),
kFilterOpcode_SimpleField | (11u << 3),
kFilterOpcode_EndOfMessage,
// Message 2.
kFilterOpcode_NestedField | (2u << 3),
3u, // message index.
kFilterOpcode_EndOfMessage,
// Message 3.
kFilterOpcode_NestedField | (2u << 3),
2u, // message index (create a cycle, 2->3, 3->2).
kFilterOpcode_EndOfMessage,
}));
// Query message 0 fields.
EXPECT_TRUE(parser.Query(0, 1).allowed);
EXPECT_TRUE(parser.Query(0, 2).allowed);
EXPECT_TRUE(parser.Query(0, 2).simple_field());
EXPECT_TRUE(parser.Query(0, 4).allowed);
EXPECT_FALSE(parser.Query(0, 4).simple_field());
EXPECT_EQ(parser.Query(0, 4).nested_msg_index, 3u);
EXPECT_TRUE(parser.Query(0, 10).allowed);
EXPECT_TRUE(parser.Query(0, 10).simple_field());
EXPECT_TRUE(parser.Query(0, 127).allowed);
EXPECT_EQ(parser.Query(0, 127).nested_msg_index, 1u);
EXPECT_TRUE(parser.Query(0, 128).allowed);
EXPECT_EQ(parser.Query(0, 128).nested_msg_index, 2u);
EXPECT_FALSE(parser.Query(0, 129).allowed);
// Query message 1 fields.
EXPECT_FALSE(parser.Query(1, 1).allowed);
EXPECT_TRUE(parser.Query(1, 2).allowed);
EXPECT_EQ(parser.Query(1, 2).nested_msg_index, 1u);
EXPECT_FALSE(parser.Query(1, 3).allowed);
EXPECT_TRUE(parser.Query(1, 11).allowed);
EXPECT_TRUE(parser.Query(1, 11).simple_field());
// Query message 2 fields.
EXPECT_FALSE(parser.Query(2, 0).allowed);
EXPECT_FALSE(parser.Query(2, 1).allowed);
EXPECT_TRUE(parser.Query(2, 2).allowed);
EXPECT_EQ(parser.Query(2, 2).nested_msg_index, 3u);
EXPECT_FALSE(parser.Query(2, 4).allowed);
// Query message 3 fields.
EXPECT_FALSE(parser.Query(3, 0).allowed);
EXPECT_FALSE(parser.Query(3, 1).allowed);
EXPECT_TRUE(parser.Query(3, 2).allowed);
EXPECT_EQ(parser.Query(3, 2).nested_msg_index, 2u);
EXPECT_FALSE(parser.Query(3, 4).allowed);
}
} // namespace
} // namespace protozero