#include <exception>
#include <iomanip>
#include <iostream>
#include "array.hpp"
template<typename T>
void test_operation(unsigned int test, std::string description,
T&& operation) {
std::cout << "Test " << std::setw(2) << std::right << test << ": ";
std::cout << std::setw(30) << std::left << std::move(description) << " ";
try {
operation();
std::cout << "ok" << std::endl;
} catch (std::exception& e) {
std::cout << "exception: " << e.what() << std::endl;
} catch (...) {
std::cout << "unknown exception" << std::endl;
}
}
struct FailingObject {
class Exception: public std::exception {
const char* what() const noexcept override {
return "FailingObject exception";
}
};
FailingObject() {
throw Exception();
}
FailingObject(const FailingObject& other) {
throw Exception();
}
FailingObject(int i) {
if (i < 0) throw Exception();
}
FailingObject& operator=(const FailingObject& other) {
throw Exception();
}
};
int main() {
unsigned int test = 0;
test_operation(++test, "Array()", []() { Array<FailingObject>(); });
test_operation(++test, "Array(0)", []() { Array<FailingObject>(0); });
test_operation(++test, "Array(1)", []() { Array<FailingObject>(1); });
test_operation(++test, "Array(1, FailingObject(1))",
[]() { Array<FailingObject>(1, FailingObject(1)); });
test_operation(++test, "Array(it1, it2) from {1, 2}", []() {
int values[] = {1, 2, 3};
Array<FailingObject>(values, values + sizeof(values)/sizeof(values[0]));
});
test_operation(++test, "Array(it1, it2) from {1, -2}", []() {
int values[] = {1, -2};
Array<FailingObject>(values, values + sizeof(values)/sizeof(values[0]));
});
test_operation(++test, "Array{1, 2}", []() {
Array<FailingObject>{1, 2};
});
test_operation(++test, "Array{1, -2}", []() {
Array<FailingObject>{1, -2};
});
test_operation(++test, "Array copy constructor", []() {
int values[] = {1, 2};
Array<FailingObject> array(values,
values + sizeof(values)/sizeof(values[0]));
Array<FailingObject> array2(array);
});
test_operation(++test, "Array move constructor", []() {
int values[] = {1, 2};
Array<FailingObject> array(values,
values + sizeof(values)/sizeof(values[0]));
Array<FailingObject>(std::move(array));
});
test_operation(++test, "Array swap", []() {
int values[] = {1, 2};
Array<FailingObject> array1(values,
values + sizeof(values)/sizeof(values[0]));
Array<FailingObject> array2(values,
values + sizeof(values)/sizeof(values[0]));
using std::swap;
swap(array1, array2);
});
test_operation(++test, "Array assignment", []() {
int values[] = {1, 2};
Array<FailingObject> array1(values,
values + sizeof(values)/sizeof(values[0]));
Array<FailingObject> array2;
array2 = std::move(array1);
});
test_operation(++test, "Array get_size", []() {
int values[] = {1, 2};
Array<FailingObject> array(values,
values + sizeof(values)/sizeof(values[0]));
array.get_size();
});
test_operation(++test, "Array access by index", []() {
int values[] = {1, 2};
Array<FailingObject> array(values,
values + sizeof(values)/sizeof(values[0]));
array(1);
});
test_operation(++test, "Array access by index const", []() {
int values[] = {1, 2};
const Array<FailingObject> array(values,
values + sizeof(values)/sizeof(values[0]));
array(1);
});
test_operation(++test, "Array out of range", []() {
int values[] = {1, 2};
Array<int> array(values, values + sizeof(values)/sizeof(values[0]));
array(2);
});
test_operation(++test, "Array const out of range", []() {
int values[] = {1, 2};
const Array<int> array(values, values + sizeof(values)/sizeof(values[0]));
array(2);
});
test_operation(++test, "Array iterators", []() {
int values[] = {1, 2};
Array<FailingObject> array(values,
values + sizeof(values)/sizeof(values[0]));
for (auto& object: array) {
}
});
test_operation(++test, "Array const iterators", []() {
int values[] = {1, 2};
const Array<FailingObject> array(values,
values + sizeof(values)/sizeof(values[0]));
for (auto& object: array) {
}
});
std::cout << test << " tests survived." << std::endl;
}