LIEF/tests/test_iterators.cpp
2018-05-04 12:46:28 +02:00

524 lines
12 KiB
C++

/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* 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.
*/
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include <LIEF/iterators.hpp>
using namespace LIEF;
using it_const_ref_t = const_ref_iterator<std::vector<std::string>>;
using it_ref_local_t = ref_iterator<std::vector<std::string>>;
using it_ref_t = ref_iterator<std::vector<std::string>&>;
using it_const_ref_ptr_t = const_ref_iterator<std::vector<std::string*>>;
using it_ref_ptr_t = ref_iterator<std::vector<std::string*>>;
using it_filter_ref = filter_iterator<std::vector<std::string>&>;
using it_filter_ref_local_t = filter_iterator<std::vector<std::string>>;
using it_filter_ref_ptr = filter_iterator<std::vector<std::string*>>;
using it_filter_const_ref = const_filter_iterator<const std::vector<std::string>&>;
using it_filter_const_ref_local = const_filter_iterator<std::vector<std::string>>;
using it_filter_const_ref_ptr = const_filter_iterator<std::vector<std::string*>>;
struct Dummy {
Dummy(void) : s_{"dummy"} {}
Dummy(const Dummy&) = delete;
Dummy& operator=(const Dummy&) = delete;
std::string s_;
};
using it_ref_dummies_t = ref_iterator<std::vector<Dummy>&>;
struct Foo {
Foo(void) : dummies_(10) {
bar.push_back("1");
bar.push_back("2");
bar.push_back("3");
bar.push_back("4");
bar.push_back("5");
bar.push_back("6");
bar.push_back("6");
bar.push_back("6");
bar_ptr.push_back(new std::string{"1"});
bar_ptr.push_back(new std::string{"2"});
bar_ptr.push_back(new std::string{"3"});
bar_ptr.push_back(new std::string{"4"});
bar_ptr.push_back(new std::string{"5"});
bar_ptr.push_back(new std::string{"6"});
bar_ptr.push_back(new std::string{"6"});
}
~Foo(void) {
for (std::string* ptr : this->bar_ptr) {
delete ptr;
}
}
it_const_ref_t get_bar(void) const {
return {this->bar};
}
it_ref_t get_bar(void) {
return {this->bar};
}
it_filter_ref filter_always_true(void) {
return {this->bar, [] (const std::string& v) { return true; }};
}
it_filter_ref get_bar_filter(void) {
return {this->bar, [] (const std::string& v) { return v == "6" or v == "1" or v == "foo"; }};
}
it_filter_ref get_bar_filter_empty(void) {
return {this->bar, [] (const std::string& v) { return v == "foo"; }};
}
it_filter_const_ref get_bar_filter(void) const {
return {this->bar, [] (const std::string& v) { return v == "6" or v == "1" or v == "foo"; }};
}
it_filter_ref_ptr get_bar_ptr_filter(void) {
return {this->bar_ptr, [] (const std::string* v) { return *v == "6"; }};
}
it_filter_const_ref_ptr get_bar_ptr_filter(void) const {
return {this->bar_ptr, [] (const std::string* v) { return *v == "6"; }};
}
it_ref_local_t get_bar_local(void) {
std::vector<std::string> local = {"a", "b", "c"};
return {local};
}
it_filter_const_ref_local get_bar_const_filter_local(void) const {
std::vector<std::string> local = {"a", "b", "c", "a", "a"};
return {local, [] (const std::string& v) { return v == "a"; }};
}
it_ref_dummies_t get_dummies(void) {
return {this->dummies_};
}
it_const_ref_ptr_t get_bar_ptr(void) const {
return {bar_ptr};
}
it_ref_ptr_t get_bar_ptr(void) {
return {bar_ptr};
}
std::vector<Dummy> dummies_;
std::vector<std::string> bar;
std::vector<std::string*> bar_ptr;
};
TEST_CASE("Test const ref iterators", "[lief][iterators][const_ref]") {
const Foo foo;
SECTION("operator++") {
it_const_ref_t bars = foo.get_bar();
REQUIRE(*(bars++) == "1");
REQUIRE(*bars == "2");
}
SECTION("operator++(int)") {
it_const_ref_t bars = foo.get_bar();
REQUIRE(*(++bars) == "2");
REQUIRE(*(++bars) == "3");
REQUIRE(*(++bars) == "4");
}
SECTION("operator--") {
it_const_ref_t bars = foo.get_bar();
++bars;
REQUIRE(*(bars--) == "2");
REQUIRE(*bars == "1");
}
SECTION("operator--(int)") {
it_const_ref_t bars = foo.get_bar();
++bars;
REQUIRE(*(--bars) == "1");
REQUIRE(*bars == "1");
}
SECTION("operator+=") {
it_const_ref_t bars = foo.get_bar();
bars += 2;
REQUIRE(*bars == "3");
}
SECTION("operator-=") {
it_const_ref_t bars = foo.get_bar();
bars += 4;
REQUIRE(*bars == "5");
bars -= 2;
REQUIRE(*bars == "3");
}
SECTION("operator[]") {
it_const_ref_t bars = foo.get_bar();
REQUIRE(bars[4] == "5");
}
SECTION("operator+") {
it_const_ref_t bars = foo.get_bar();
REQUIRE(*(bars + 5) == "6");
}
SECTION("operator-") {
it_const_ref_t bars = foo.get_bar();
bars += 4;
REQUIRE(*(bars - 1) == "4");
}
SECTION("Comparaisons") {
it_const_ref_t bars_lhs = foo.get_bar();
it_const_ref_t bars_rhs = foo.get_bar();
REQUIRE(bars_lhs == bars_rhs);
REQUIRE(std::begin(bars_lhs) == std::begin(bars_rhs));
REQUIRE(std::end(bars_lhs) == std::end(bars_rhs));
REQUIRE(std::end(bars_lhs) != std::begin(bars_rhs));
REQUIRE((bars_lhs + 5) == (bars_rhs + 5));
REQUIRE((bars_lhs + 5) != (bars_rhs + 6));
it_const_ref_t it1 = bars_lhs + 5;
it_const_ref_t it2 = bars_rhs + 4;
REQUIRE(it1 != it2);
REQUIRE((it1 - 1) == it2);
REQUIRE((it1 - it2) == 1);
REQUIRE(it1 > it2);
REQUIRE(it1 >= it1);
REQUIRE(it2 < it1);
REQUIRE(it2 <= it2);
}
SECTION("Internal management") {
it_const_ref_t bars = foo.get_bar();
it_const_ref_ptr_t bars_ptr = foo.get_bar_ptr();
REQUIRE(bars.size() == foo.bar.size());
REQUIRE(bars_ptr.size() == foo.bar_ptr.size());
REQUIRE(*bars_ptr == "1");
REQUIRE(std::string(bars_ptr->c_str()) == "1");
REQUIRE(bars_ptr[2] == "3");
REQUIRE(std::string(bars->c_str()) == "1");
REQUIRE(std::string(bars_ptr->c_str()) == "1");
size_t count = std::count_if(
std::begin(bars),
std::end(bars),
[] (const std::string& s) {
return s == "6";
});
REQUIRE(count == 3);
it_const_ref_t bar_operator_equal{bars};
bar_operator_equal += 2;
//bar_operator_equal.operator=(bars);
//REQUIRE(bar_operator_equal == bars);
}
}
TEST_CASE("Test ref iterators", "[lief][iterators][ref]") {
Foo foo;
SECTION("operator++") {
it_ref_t bars = foo.get_bar();
REQUIRE(*(bars++) == "1");
REQUIRE(*bars == "2");
}
SECTION("operator++(int)") {
it_ref_t bars = foo.get_bar();
REQUIRE(*(++bars) == "2");
REQUIRE(*(++bars) == "3");
REQUIRE(*(++bars) == "4");
}
SECTION("operator--") {
it_ref_t bars = foo.get_bar();
++bars;
REQUIRE(*(bars--) == "2");
REQUIRE(*bars == "1");
}
SECTION("operator--(int)") {
it_ref_t bars = foo.get_bar();
++bars;
REQUIRE(*(--bars) == "1");
REQUIRE(*bars == "1");
}
SECTION("operator+=") {
it_ref_t bars = foo.get_bar();
bars += 2;
REQUIRE(*bars == "3");
}
SECTION("operator-=") {
it_ref_t bars = foo.get_bar();
bars += 4;
REQUIRE(*bars == "5");
bars -= 2;
REQUIRE(*bars == "3");
}
SECTION("operator[]") {
it_ref_t bars = foo.get_bar();
REQUIRE(bars[4] == "5");
}
SECTION("operator+") {
it_ref_t bars = foo.get_bar();
REQUIRE(*(bars + 5) == "6");
}
SECTION("operator-") {
it_ref_t bars = foo.get_bar();
bars += 4;
REQUIRE(*(bars - 1) == "4");
}
SECTION("Comparaisons") {
it_ref_t bars_lhs = foo.get_bar();
it_ref_t bars_rhs = foo.get_bar();
REQUIRE(bars_lhs == bars_rhs);
REQUIRE(std::begin(bars_lhs) == std::begin(bars_lhs));
REQUIRE(std::end(bars_lhs) == std::end(bars_lhs));
REQUIRE(std::begin(bars_lhs) == std::begin(bars_rhs));
REQUIRE(std::end(bars_lhs) == std::end(bars_rhs));
REQUIRE(std::end(bars_lhs) != std::begin(bars_rhs));
REQUIRE((bars_lhs + 5) == (bars_rhs + 5));
REQUIRE((bars_lhs + 5) != (bars_rhs + 6));
it_ref_t it1 = bars_lhs + 5;
it_ref_t it2 = bars_rhs + 4;
REQUIRE(it1 != it2);
REQUIRE((it1 - 1) == it2);
REQUIRE((it1 - it2) == 1);
REQUIRE(it1 > it2);
REQUIRE(it1 >= it1);
REQUIRE(it2 < it1);
REQUIRE(it2 <= it2);
}
SECTION("Internal management") {
it_ref_t bars = foo.get_bar();
it_ref_ptr_t bars_ptr = foo.get_bar_ptr();
REQUIRE(bars.size() == foo.bar.size());
REQUIRE(bars_ptr.size() == foo.bar_ptr.size());
REQUIRE(*bars_ptr == "1");
REQUIRE(std::string(bars_ptr->c_str()) == "1");
REQUIRE(bars_ptr[2] == "3");
REQUIRE(std::string(bars->c_str()) == "1");
REQUIRE(std::string(bars_ptr->c_str()) == "1");
size_t count = std::count_if(
std::begin(bars),
std::end(bars),
[] (const std::string& s) {
return s == "6";
});
REQUIRE(count == 3);
it_ref_t bar_operator_equal{bars};
bar_operator_equal += 2;
bar_operator_equal.operator=(bars);
REQUIRE(bar_operator_equal == bars);
std::string& first_one_ptr = *bars_ptr;
first_one_ptr = "123456";
REQUIRE(foo.get_bar_ptr()[0] == "123456");
*foo.get_bar() = "123456";
CHECK(*foo.get_bar() == "123456");
auto&& dummies = foo.get_dummies();
Dummy& d = dummies[0];
d.s_ = "zigzag";
CHECK(foo.get_dummies()->s_ == "zigzag");
it_ref_local_t local = foo.get_bar_local();
CHECK(*local == "a");
CHECK(std::begin(local) == std::begin(local));
CHECK(std::end(local) == std::end(local));
}
}
TEST_CASE("Test filter ref iterators", "[lief][iterators][filter][ref]") {
Foo foo;
SECTION("Always true") {
it_filter_ref true_list = foo.filter_always_true();
CHECK(true_list.size() == 8);
}
SECTION("operator++") {
it_filter_ref bar_filtred = foo.get_bar_filter();
it_filter_ref_ptr bar_ptr_filtred = foo.get_bar_ptr_filter();
CHECK(std::begin(bar_filtred) == std::begin(bar_filtred));
CHECK(*bar_filtred == "1");
CHECK(*(++bar_filtred) == "6");
CHECK(*(bar_filtred++) == "6");
CHECK(*(++bar_filtred) == "6");
CHECK(*(bar_filtred++) == "6");
CHECK(bar_filtred == std::end(bar_filtred));
}
SECTION("size()") {
it_filter_ref bar_filtred = foo.get_bar_filter();
it_filter_ref bar_filtred_empty = foo.get_bar_filter_empty();
it_filter_ref_ptr bar_ptr_filtred = foo.get_bar_ptr_filter();
CHECK(bar_filtred.size() == 4);
CHECK(bar_filtred_empty.size() == 0);
CHECK(bar_ptr_filtred.size() == 2);
}
SECTION("operator[]") {
it_filter_ref bar_filtred = foo.get_bar_filter();
it_filter_ref_ptr bar_ptr_filtred = foo.get_bar_ptr_filter();
CHECK(bar_filtred[0] == "1");
}
SECTION("Internal management") {
it_filter_ref bar_filtred = foo.get_bar_filter();
it_filter_ref_ptr bar_ptr_filtred = foo.get_bar_ptr_filter();
bar_ptr_filtred[1] = "7";
bar_filtred[0] = "foo";
CHECK(foo.get_bar_filter()[0] == "foo");
CHECK(foo.get_bar_ptr_filter().size() == 1);
}
}
TEST_CASE("Test const filter ref iterators", "[lief][iterators][filter][const_ref]") {
const Foo foo;
SECTION("operator++") {
it_filter_const_ref bar_filtred = foo.get_bar_filter();
it_filter_const_ref_ptr bar_ptr_filtred = foo.get_bar_ptr_filter();
CHECK(std::begin(bar_filtred) == std::begin(bar_filtred));
CHECK(*bar_filtred == "1");
CHECK(*(++bar_filtred) == "6");
CHECK(*(bar_filtred++) == "6");
CHECK(*(++bar_filtred) == "6");
CHECK(*(bar_filtred++) == "6");
CHECK(bar_filtred == std::end(bar_filtred));
}
SECTION("size()") {
it_filter_const_ref bar_filtred = foo.get_bar_filter();
it_filter_const_ref_ptr bar_ptr_filtred = foo.get_bar_ptr_filter();
CHECK(bar_filtred.size() == 4);
CHECK(bar_ptr_filtred.size() == 2);
}
SECTION("operator[]") {
it_filter_const_ref bar_filtred = foo.get_bar_filter();
it_filter_const_ref_ptr bar_ptr_filtred = foo.get_bar_ptr_filter();
CHECK(bar_filtred[1] == "6");
CHECK(bar_filtred[0] == "1");
CHECK(bar_ptr_filtred[1] == "6");
CHECK(bar_ptr_filtred[0] == "6");
}
SECTION("local") {
it_filter_const_ref_local bar_ptr_filtred = foo.get_bar_const_filter_local();
CHECK(bar_ptr_filtred.size() == 3);
}
}