| #include "mpact/sim/decoder/bin_encoding_info.h" |
| |
| #include "absl/log/check.h" |
| #include "absl/status/status.h" |
| #include "googletest/include/gtest/gtest.h" |
| #include "mpact/sim/decoder/decoder_error_listener.h" |
| #include "mpact/sim/decoder/format.h" |
| #include "mpact/sim/decoder/instruction_group.h" |
| |
| // This file provides for testing of the BinEncodingInfo class interfaces, with |
| // the exception of PropagateExtractors, as that cannot be tested in isolation. |
| |
| namespace { |
| |
| using ::mpact::sim::decoder::DecoderErrorListener; |
| using ::mpact::sim::decoder::bin_format::BinEncodingInfo; |
| |
| constexpr char kOpcodeEnumName[] = "OpcodeEnumName"; |
| constexpr char kIncludeFile0[] = "IncludeFile0"; |
| constexpr char kIncludeFile1[] = "IncludeFile1"; |
| constexpr char kIncludeFile2[] = "IncludeFile2"; |
| constexpr const char *kIncludeFiles[] = {kIncludeFile0, kIncludeFile1, |
| kIncludeFile2}; |
| constexpr char kFormat0[] = "Format0"; |
| constexpr char kFormat1[] = "Format1"; |
| constexpr char kFormat2[] = "Format2"; |
| constexpr char kGroup0[] = "Group0"; |
| constexpr char kBinDecoder[] = "BinDecoder"; |
| constexpr int kFormatWidth32 = 32; |
| constexpr int kFormatWidth16 = 16; |
| |
| class BinEncodingInfoTest : public ::testing::Test { |
| protected: |
| BinEncodingInfoTest() { |
| error_listener_ = new DecoderErrorListener(); |
| bin_encoding_info_ = new BinEncodingInfo(kOpcodeEnumName, error_listener_); |
| } |
| ~BinEncodingInfoTest() override { |
| for (auto &[name, instruction_group_ptr] : |
| bin_encoding_info_->instruction_group_map()) { |
| delete instruction_group_ptr; |
| } |
| delete bin_encoding_info_; |
| delete error_listener_; |
| } |
| |
| DecoderErrorListener *error_listener_ = nullptr; |
| BinEncodingInfo *bin_encoding_info_ = nullptr; |
| }; |
| |
| // Test for proper initialization of object. |
| TEST_F(BinEncodingInfoTest, Constructed) { |
| EXPECT_FALSE(error_listener_->HasError()); |
| EXPECT_TRUE(bin_encoding_info_->format_map().empty()); |
| EXPECT_TRUE(bin_encoding_info_->include_files().empty()); |
| EXPECT_TRUE(bin_encoding_info_->instruction_group_map().empty()); |
| EXPECT_EQ(bin_encoding_info_->decoder(), nullptr); |
| EXPECT_EQ(bin_encoding_info_->error_listener(), error_listener_); |
| } |
| |
| // Test that include files are properly added/kept. |
| TEST_F(BinEncodingInfoTest, AddIncludeFile) { |
| EXPECT_TRUE(bin_encoding_info_->include_files().empty()); |
| for (auto const &include_file : kIncludeFiles) { |
| bin_encoding_info_->AddIncludeFile(include_file); |
| } |
| EXPECT_FALSE(bin_encoding_info_->include_files().empty()); |
| for (auto const &include_file : kIncludeFiles) { |
| EXPECT_TRUE(bin_encoding_info_->include_files().contains(include_file)); |
| } |
| EXPECT_FALSE(bin_encoding_info_->include_files().contains("NoIncludeFile")); |
| } |
| |
| // Test that formats are properly added/kept. |
| TEST_F(BinEncodingInfoTest, AddFormat) { |
| // Adding a new format should work. |
| auto res0 = bin_encoding_info_->AddFormat(kFormat0, kFormatWidth32); |
| EXPECT_TRUE(res0.status().ok()); |
| auto *format = res0.value(); |
| EXPECT_EQ(format->name(), kFormat0); |
| EXPECT_EQ(format->declared_width(), kFormatWidth32); |
| |
| // Make sure we get the format back when calling GetFormat. |
| auto *get_format = bin_encoding_info_->GetFormat(kFormat0); |
| EXPECT_EQ(get_format, format); |
| // Adding the same format again should fail. |
| res0 = bin_encoding_info_->AddFormat(kFormat0, kFormatWidth32); |
| EXPECT_EQ(absl::StatusCode::kAlreadyExists, res0.status().code()); |
| |
| // Add a different format should work. |
| auto res1 = bin_encoding_info_->AddFormat(kFormat1, kFormatWidth16); |
| EXPECT_TRUE(res1.status().ok()); |
| format = res1.value(); |
| EXPECT_EQ(format->name(), kFormat1); |
| EXPECT_EQ(format->declared_width(), kFormatWidth16); |
| |
| // Add format with parent. |
| auto res2 = bin_encoding_info_->AddFormat(kFormat2, kFormatWidth32, kFormat0); |
| EXPECT_TRUE(res2.status().ok()); |
| format = res2.value(); |
| EXPECT_EQ(format->name(), kFormat2); |
| EXPECT_EQ(format->declared_width(), kFormatWidth32); |
| |
| // Can't add the same format twice. |
| res2 = bin_encoding_info_->AddFormat(kFormat2, kFormatWidth32, kFormat0); |
| EXPECT_EQ(absl::StatusCode::kAlreadyExists, res2.status().code()); |
| |
| // Format map. Verify that the formats are in the map. |
| auto &format_map = bin_encoding_info_->format_map(); |
| EXPECT_EQ(format_map.size(), 3); |
| EXPECT_NE(format_map.find(kFormat0), format_map.end()); |
| EXPECT_NE(format_map.find(kFormat1), format_map.end()); |
| EXPECT_NE(format_map.find(kFormat2), format_map.end()); |
| } |
| |
| // Instruction groups. |
| TEST_F(BinEncodingInfoTest, AddInstructionGroup) { |
| EXPECT_TRUE(bin_encoding_info_->instruction_group_map().empty()); |
| |
| // Add an instruction group. |
| auto res = bin_encoding_info_->AddInstructionGroup(kGroup0, kFormatWidth32, |
| kFormat0); |
| EXPECT_TRUE(res.status().ok()); |
| auto *instruction_group = res.value(); |
| EXPECT_EQ(instruction_group->name(), kGroup0); |
| EXPECT_EQ(instruction_group->width(), kFormatWidth32); |
| EXPECT_EQ(instruction_group->format_name(), kFormat0); |
| EXPECT_EQ(instruction_group->opcode_enum(), kOpcodeEnumName); |
| |
| // Adding it a second time doesn't work. |
| res = bin_encoding_info_->AddInstructionGroup(kGroup0, kFormatWidth32, |
| kFormat0); |
| EXPECT_EQ(absl::StatusCode::kAlreadyExists, res.status().code()); |
| } |
| |
| // Bin decoder. |
| TEST_F(BinEncodingInfoTest, AddDecoder) { |
| // Add BinDecoder. |
| auto *bin_dec = bin_encoding_info_->AddBinDecoder(kBinDecoder); |
| EXPECT_NE(bin_dec, nullptr); |
| EXPECT_FALSE(error_listener_->HasError()); |
| // Try adding it again. |
| bin_dec = bin_encoding_info_->AddBinDecoder(kBinDecoder); |
| EXPECT_EQ(bin_dec, nullptr); |
| EXPECT_TRUE(error_listener_->HasError()); |
| } |
| |
| } // namespace |