/proc/self/cwd/src/ir/module_test.cc
Line | Count | Source (jump to first uncovered line) |
1 | | //----------------------------------------------------------------------------- |
2 | | // Copyright 2022 Google LLC |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | // you may not use this file except in compliance with the License. |
6 | | // You may obtain a copy of the License at |
7 | | // |
8 | | // https://www.apache.org/licenses/LICENSE-2.0 |
9 | | // |
10 | | // Unless required by applicable law or agreed to in writing, software |
11 | | // distributed under the License is distributed on an "AS IS" BASIS, |
12 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | // See the License for the specific language governing permissions and |
14 | | // limitations under the License. |
15 | | //---------------------------------------------------------------------------- |
16 | | #include "src/ir/module.h" |
17 | | |
18 | | #include <string> |
19 | | #include <vector> |
20 | | |
21 | | #include "fuzztest/fuzztest.h" |
22 | | #include "src/common/testing/gtest.h" |
23 | | #include "src/ir/storage.h" |
24 | | #include "src/ir/types/type_factory.h" |
25 | | #include "src/ir/value.h" |
26 | | |
27 | | namespace raksha::ir { |
28 | | namespace { |
29 | | |
30 | | using fuzztest::Arbitrary; |
31 | | using fuzztest::NonEmpty; |
32 | | using fuzztest::PrintableAsciiString; |
33 | | using fuzztest::UniqueElementsVectorOf; |
34 | | using raksha::ir::types::TypeFactory; |
35 | | using raksha::ir::value::Any; |
36 | | using testing::IsEmpty; |
37 | | using testing::UnorderedElementsAreArray; |
38 | | |
39 | 0 | TEST(ModuleTest, DefaultConstructorCreatesEmptyBlocks) { |
40 | 0 | Module module; |
41 | 0 | EXPECT_EQ(module.blocks().size(), 0); |
42 | 0 | } |
43 | | |
44 | 0 | TEST(ModuleTest, AddBlockReturnsPassedInBlock) { |
45 | 0 | Module module; |
46 | 0 | auto block = std::make_unique<Block>(); |
47 | 0 | const Block* passed_in_block = block.get(); |
48 | 0 | const Block& returned_block = module.AddBlock(std::move(block)); |
49 | 0 | EXPECT_EQ(std::addressof(returned_block), passed_in_block); |
50 | 0 | EXPECT_EQ(returned_block.parent_module(), &module); |
51 | 0 | } |
52 | | |
53 | 0 | TEST(ModuleTest, AddBlockUpdatesBlockList) { |
54 | 0 | Module module; |
55 | 0 | const Block* block1 = |
56 | 0 | std::addressof(module.AddBlock(std::make_unique<Block>())); |
57 | 0 | const Block* block2 = |
58 | 0 | std::addressof(module.AddBlock(std::make_unique<Block>())); |
59 | 0 | EXPECT_NE(block1, block2); |
60 | 0 | EXPECT_THAT(module.blocks(), testing::UnorderedElementsAre( |
61 | 0 | testing::Pointer(testing::Eq(block1)), |
62 | 0 | testing::Pointer(testing::Eq(block2)))); |
63 | 0 | } |
64 | | |
65 | | class ModuleStorageTestFixture { |
66 | | public: |
67 | | explicit ModuleStorageTestFixture(std::vector<std::string> storage_names) |
68 | 4.43k | : module_(), type_factory_() { |
69 | 4.43k | bool first = true; |
70 | 128k | for (absl::string_view name : storage_names) { |
71 | 128k | if (first) { |
72 | 4.37k | name_not_in_storages_ = name; |
73 | 4.37k | first = false; |
74 | 4.37k | continue; |
75 | 4.37k | } |
76 | 123k | created_storages_.push_back( |
77 | 123k | &module_.CreateStorage(name, type_factory_.MakePrimitiveType())); |
78 | 123k | } |
79 | 4.43k | } |
80 | 31.1k | Module& module() { return module_; } |
81 | 829 | TypeFactory& type_factory() { return type_factory_; } |
82 | 6.97k | const std::vector<const Storage*>& created_storages() { |
83 | 6.97k | return created_storages_; |
84 | 6.97k | } |
85 | 829 | absl::string_view name_not_in_storages() { return name_not_in_storages_; } |
86 | | |
87 | | private: |
88 | | Module module_; |
89 | | TypeFactory type_factory_; |
90 | | std::vector<const Storage*> created_storages_; |
91 | | // A name that is not taken by any of the created storages. Useful for a |
92 | | // number of tests. |
93 | | std::string name_not_in_storages_; |
94 | | }; |
95 | | |
96 | | std::vector<const Storage*> MakeNamedStorageMapIntoStorageVector( |
97 | 1.65k | const Module::NamedStorageMap& map) { |
98 | 1.65k | std::vector<const Storage*> storage_vector; |
99 | 1.65k | storage_vector.reserve(map.size()); |
100 | 79.1k | for (const auto& name_storage_pair : map) { |
101 | 79.1k | CHECK(name_storage_pair.first == name_storage_pair.second->name()); |
102 | 79.1k | storage_vector.push_back(name_storage_pair.second.get()); |
103 | 79.1k | } |
104 | 1.65k | return storage_vector; |
105 | 1.65k | } |
106 | | |
107 | 829 | void TestCreateStorages(std::vector<std::string> storage_names) { |
108 | 829 | ModuleStorageTestFixture fixture(std::move(storage_names)); |
109 | 829 | EXPECT_THAT(MakeNamedStorageMapIntoStorageVector( |
110 | 829 | fixture.module().named_storage_map()), |
111 | 829 | UnorderedElementsAreArray(fixture.created_storages())); |
112 | 829 | const Storage& storage = fixture.module().CreateStorage( |
113 | 829 | fixture.name_not_in_storages(), |
114 | 829 | fixture.type_factory().MakePrimitiveType()); |
115 | 829 | std::vector<const Storage*> created_storages_plus_new_element; |
116 | 829 | created_storages_plus_new_element.push_back(&storage); |
117 | 829 | created_storages_plus_new_element.insert( |
118 | 829 | created_storages_plus_new_element.end(), |
119 | 829 | fixture.created_storages().begin(), fixture.created_storages().end()); |
120 | 829 | EXPECT_THAT(MakeNamedStorageMapIntoStorageVector( |
121 | 829 | fixture.module().named_storage_map()), |
122 | 829 | UnorderedElementsAreArray(created_storages_plus_new_element)); |
123 | 829 | } |
124 | | |
125 | | FUZZ_TEST(ModuleStorageTest, TestCreateStorages) |
126 | | .WithDomains(NonEmpty(UniqueElementsVectorOf(PrintableAsciiString()))); |
127 | | |
128 | 940 | void GetAddedStorageBehavesCorrectly(std::vector<std::string> storage_names) { |
129 | 940 | ModuleStorageTestFixture fixture(std::move(storage_names)); |
130 | 26.7k | for (const Storage* storage : fixture.created_storages()) { |
131 | 26.7k | EXPECT_EQ(&fixture.module().GetStorage(storage->name()), storage); |
132 | 26.7k | } |
133 | 940 | } |
134 | | |
135 | | FUZZ_TEST(ModuleStorageTest, GetAddedStorageBehavesCorrectly) |
136 | | .WithDomains(NonEmpty(UniqueElementsVectorOf(PrintableAsciiString()))); |
137 | | |
138 | 889 | void GetNotPresentStorageFails(std::vector<std::string> storage_names) { |
139 | 889 | ModuleStorageTestFixture fixture(std::move(storage_names)); |
140 | 889 | EXPECT_DEATH(fixture.module().GetStorage(fixture.name_not_in_storages()), |
141 | 889 | absl::StrCat(".*Could not find Storage with name.*")); |
142 | 889 | } |
143 | | |
144 | | FUZZ_TEST(ModuleStorageTest, GetNotPresentStorageFails) |
145 | | .WithDomains(NonEmpty(UniqueElementsVectorOf(PrintableAsciiString()))); |
146 | | |
147 | | void CreateStorageSameNameDies(std::vector<std::string> storage_names, |
148 | 827 | uint64_t idx) { |
149 | 827 | ModuleStorageTestFixture fixture(std::move(storage_names)); |
150 | 827 | absl::string_view name_to_duplicate = |
151 | 827 | fixture.created_storages() |
152 | 827 | .at(idx % fixture.created_storages().size()) |
153 | 827 | ->name(); |
154 | 827 | EXPECT_DEATH( |
155 | 827 | fixture.module().CreateStorage( |
156 | 827 | name_to_duplicate, fixture.type_factory().MakePrimitiveType()), |
157 | 827 | ".*Multiple stores with name.*"); |
158 | 827 | } |
159 | | |
160 | | FUZZ_TEST(ModuleStorageTest, CreateStorageSameNameDies) |
161 | | .WithDomains(UniqueElementsVectorOf(PrintableAsciiString()).WithMinSize(2), |
162 | | Arbitrary<uint64_t>()); |
163 | | |
164 | 947 | void AddValueToStorage(std::vector<std::string> storage_names, uint64_t idx) { |
165 | 947 | ModuleStorageTestFixture fixture(std::move(storage_names)); |
166 | 947 | absl::string_view name_to_add_value_to = |
167 | 947 | fixture.created_storages() |
168 | 947 | .at(idx % fixture.created_storages().size()) |
169 | 947 | ->name(); |
170 | 947 | Value value_to_add = Value(Any()); |
171 | 947 | fixture.module().AddInputValueToStorage(name_to_add_value_to, value_to_add); |
172 | 20.9k | for (const auto& [name, storage] : fixture.module().named_storage_map()) { |
173 | 20.9k | if (name == name_to_add_value_to) { |
174 | 947 | EXPECT_THAT(storage->input_values(), |
175 | 947 | UnorderedElementsAreArray({value_to_add})); |
176 | 19.9k | } else { |
177 | 19.9k | EXPECT_THAT(storage->input_values(), IsEmpty()); |
178 | 19.9k | } |
179 | 20.9k | } |
180 | 947 | } |
181 | | |
182 | | FUZZ_TEST(ModuleStorageTest, AddValueToStorage) |
183 | | .WithDomains(UniqueElementsVectorOf(PrintableAsciiString()).WithMinSize(2), |
184 | | Arbitrary<uint64_t>()); |
185 | | |
186 | | } // namespace |
187 | | } // namespace raksha::ir |