blob: 2c8e6d7821d264090854774700a85375c0bd0951 [file] [log] [blame]
// Copyright 2023 The Centipede Authors.
//
// 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
//
// https://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 "./centipede/execution_metadata.h"
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace centipede {
namespace {
using ::testing::IsEmpty;
using ::testing::UnorderedElementsAreArray;
TEST(ExecutionMetadata, ForEachCmpEntryEnumeratesEntriesInRawBytes) {
ExecutionMetadata metadata{.cmp_data = {
2, // size
1, 2, // a
3, 4, // b
0, // zero-sized entry
3, // size
5, 6, 7, // a
8, 9, 10, // b
}};
std::vector<std::pair<ByteSpan, ByteSpan>> enumeration_result;
EXPECT_TRUE(metadata.ForEachCmpEntry(
[&](ByteSpan a, ByteSpan b) { enumeration_result.emplace_back(a, b); }));
EXPECT_THAT(
enumeration_result,
UnorderedElementsAreArray(std::vector<std::pair<ByteSpan, ByteSpan>>{
{{1, 2}, {3, 4}},
{{}, {}},
{{5, 6, 7}, {8, 9, 10}},
}));
}
TEST(ExecutionMetadata, ForEachCmpEntryHandlesEmptyCmpData) {
auto noop_callback = [](ByteSpan, ByteSpan) {};
EXPECT_TRUE(ExecutionMetadata{.cmp_data = {}}.ForEachCmpEntry(noop_callback));
}
TEST(ExecutionMetadata,
ForEachCmpEntryReturnsFalseOnCmpDataWithNotEnoughBytes) {
auto noop_callback = [](ByteSpan, ByteSpan) {};
const auto bad_metadata_1 = ExecutionMetadata{.cmp_data = {3, 1, 2, 3}};
EXPECT_FALSE(bad_metadata_1.ForEachCmpEntry(noop_callback));
const auto bad_metadata_2 = ExecutionMetadata{.cmp_data = {3, 1, 2, 3, 4, 5}};
EXPECT_FALSE(bad_metadata_2.ForEachCmpEntry(noop_callback));
}
TEST(ExecutionMetadata, ForEachCmpEntryEnumeratesEntriesFromAppendCmpEntry) {
ExecutionMetadata metadata;
ASSERT_TRUE(metadata.AppendCmpEntry({1, 2}, {3, 4}));
std::vector<std::pair<ByteSpan, ByteSpan>> enumeration_result;
EXPECT_TRUE(metadata.ForEachCmpEntry(
[&](ByteSpan a, ByteSpan b) { enumeration_result.emplace_back(a, b); }));
EXPECT_THAT(
enumeration_result,
UnorderedElementsAreArray(std::vector<std::pair<ByteSpan, ByteSpan>>{
{{1, 2}, {3, 4}},
}));
}
TEST(ExecutionMetadata, AppendCmpEntryReturnsFalseAndSkipsOnBadArgs) {
ExecutionMetadata metadata;
// Sizes don't match.
EXPECT_FALSE(metadata.AppendCmpEntry({}, {1}));
ByteArray long_byte_array;
long_byte_array.resize(256);
// Args too long.
EXPECT_FALSE(metadata.AppendCmpEntry(long_byte_array, long_byte_array));
// Should leave no entries and keep metadata well-formed.
std::vector<std::pair<ByteSpan, ByteSpan>> enumeration_result;
EXPECT_TRUE(metadata.ForEachCmpEntry(
[&](ByteSpan a, ByteSpan b) { enumeration_result.emplace_back(a, b); }));
EXPECT_THAT(enumeration_result, IsEmpty());
}
TEST(ExecutionMetadata, ReadAndWriteKeepsCmpEntries) {
ExecutionMetadata metadata_in;
ASSERT_TRUE(metadata_in.AppendCmpEntry({1, 2}, {3, 4}));
SharedMemoryBlobSequence blobseq("test", /*size=*/1024,
/*use_posix_shmem=*/false);
EXPECT_TRUE(metadata_in.Write(/*tag=*/1, blobseq));
blobseq.Reset();
Blob blob = blobseq.Read();
ExecutionMetadata metadata_out;
metadata_out.Read(blob);
std::vector<std::pair<ByteSpan, ByteSpan>> enumeration_result;
EXPECT_TRUE(metadata_out.ForEachCmpEntry(
[&](ByteSpan a, ByteSpan b) { enumeration_result.emplace_back(a, b); }));
EXPECT_THAT(
enumeration_result,
UnorderedElementsAreArray(std::vector<std::pair<ByteSpan, ByteSpan>>{
{{1, 2}, {3, 4}},
}));
}
} // namespace
} // namespace centipede