-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
285 lines (238 loc) · 8.32 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
// Gabriele Canesi
// Matricola 851637
/**
* @file main.cpp
* @author Gabriele Canesi
* @brief File che contiene il main, i test e un funtore di prova.
*/
/**
* @mainpage
* Questo progetto è volto ad implementare una matrice sparsa contenente valori di tipi
* generici, utilizzando il minimo quantitativo di
* memoria possibile.
*/
#include <iostream>
#include <cassert>
#include "SparseMatrix.h"
#include "test_class.h"
#include "sparse_matrix_exceptions.h"
/**
* @brief Funtore per test_class
*
* Questo funtore ritorna true se il il metodo value() di un oggetto test_class ritorna un valore pari, false altrimenti.
*/
struct pari{
bool operator()(const test_class &n) const {
return n.value() % 2 == 0;
}
};
/**
* @brief Funtore per std::string
*
* Questo funtore ritorna true se la lunghezza della stringa passata come argomento è pari, false altrimenti.
*/
struct stringhe_pari{
bool operator()(const std::string &str) const {
return str.length() % 2 == 0;
}
};
typedef SparseMatrix<test_class> mat_test;
/**
* @brief Test che controlla il lancio dell'eccezione in caso di dimensione negativa in input
*
* Controlla la cattura di un'eccezione di tipo invalid_matrix_exception nel caso in cui venga passata al costruttore
* una dimensione negativa
*/
void test_dimensione_negativa(){
std::cout << "Test dimensione negativa: ";
bool passed = false;
mat_test::size_type dim = -1;
test_class default_value(-1);
try{
mat_test matrice(dim, -1, default_value);
}
catch(invalid_matrix_dimension_exception& e){
std::cout << std::endl << "invalid_matrix_dimension_exception lanciata correttamente: " << e.what() << std::endl;
passed = true;
}
assert(passed);
std::cout << "passato " << std::endl;
}
/**
* @brief Test che controlla la correttezza del getter del numero di elementi inseriti
*
* Verifica che il numero di elementi inseriti corrisponda con quelli effettivamente presenti nella matrice.
*/
void test_get_elementi_inseriti(){
std::cout << "Test numero elementi inseriti: ";
test_class default_value(-1);
mat_test matrice(10, 10, default_value);
matrice.set(3, 4, test_class(5));
matrice.set(4, 5, test_class(2));
matrice.set(3, 4, test_class(3));
std::cout << matrice << std::endl;
assert(matrice.inserted_items() == 2);
std::cout << "passato" << std::endl;
}
/**
* @brief Test che controlla la correttezza della funzione evaluate.
*
* Controlle se evaluate si comporta correttamente testanto un predicato su test_class e uno su stringhe.
*/
void test_evaluate(){
std::cout << "Test evaluate: ";
test_class default_value(0);
mat_test matrice(10, 10, default_value);
matrice.set(0, 0, test_class(10));
matrice.set(3, 4, test_class(11));
matrice.set(2, 1, test_class(12));
// Prova con le stringhe
SparseMatrix<std::string> mat_stringhe(10, 10, "Ciao");
mat_stringhe.set(1, 0, "Dispari");
assert(evaluate(mat_stringhe, stringhe_pari()) == 99);
assert(evaluate(matrice, pari()) == 2 + (matrice.rows() * matrice.columns() - matrice.inserted_items()));
std::cout << "passato" << std::endl;
}
/**
* @brief Test che controlla la gestione dei limiti di righe/colonne nell'inserimento
*
* Verifica che venga lanciata correttamente un'eccezione di tipo matrix_out_of_bounds_exception
* quando si specifica una riga o una colonna che non appartiene alla matrice logica.
*/
void test_bounds(){
std::cout << "Test out of bounds: ";
bool passed = false;
test_class default_value(-1);
mat_test matrice(10, 10, default_value);
try{
matrice.set(100, 9, test_class(3));
} catch (matrix_out_of_bounds_exception& e){
std::cout << std::endl << "matrix_out_of_bounds_exception lanciata correttamente: " << e.what() << std::endl;
passed = true;
}
assert(passed);
std::cout << "passato" << std::endl;
}
/**
* @brief Test del costruttore di copia
*
* Controlla che il copy constructor di SparseMatrix non renda condivisi tra istanze i puntatori
*/
void test_copia(){
std::cout << "Test sul costruttore di copia: ";
test_class default_value(-1);
mat_test m1(10, 10, test_class(-1));
// Controllo che i dati siano separati
m1.set(0, 0, test_class(10));
mat_test m2 = m1;
const test_class& v1 = m1(0, 0);
const test_class& v2 = m2(0, 0);
// Controllo che gli indirizzi di memoria dei valori siano diversi
assert(&m1(0, 0) != &m2(0, 0));
// Controllo che le dimensioni coincidano
assert(m1.rows() == m2.rows());
assert(m1.columns() == m2.columns());
assert(m1.inserted_items() == m2.inserted_items());
// Controllo che il valore di default sia stato copiato correttamente
assert(m1.default_value().value() == m2.default_value().value());
assert(&m1.default_value() != &m2.default_value());
std::cout << "passato" << std::endl;
}
/**
* @brief Test dell'operatore di assegnamento
*
* Controlla la correttezza dell'operatore di assegnamento, controllando che non ci siano condivisioni
* di dati tra le istanze.
*/
void test_assegnamento(){
std::cout << "Test di assegnamento: ";
mat_test m1(10, 10, test_class(-1));
mat_test m2(7, 8, test_class(-1));
m1.set(0, 0, test_class(10));
m2.set(0, 0, test_class(20));
m2 = m1;
assert(m2(0, 0).value() == m1(0, 0).value());
// Controllo che i dati siano separati
assert(&m1(0, 0) != &m2(0, 0));
std::cout << "passato" << std::endl;
}
/**
* @brief Test che controlla la gestione delle dimensioni in input alla matrice.
*
* Controlla che venga lanciata correttamente una eccezione di tipo invalid_matrix_dimension_exception quando
* viene passata una dimensione troppo grande, ovvero tale da portare potenzialmente il contatore degli elementi
* inseriti in overflow.
*/
void test_dimensione_massima(){
std::cout << "Test dimensione massima:" << std::endl;
bool passed = false;
// Controllo che la dimensione totale non possa superare il limite superiore di size_type.
mat_test::size_type limit = std::numeric_limits<SparseMatrix<test_class>::size_type>::max();
mat_test::size_type v1 = limit / 100;
mat_test matrice(limit / v1, v1, test_class(-1));
try{
mat_test matrice_troppo_grossa(limit / v1, v1 + 1, test_class(-1));
} catch (invalid_matrix_dimension_exception &e) {
std::cout << "invalid_matrix_dimension_exception lanciata correttamente: " << e.what() << std::endl;
passed = true;
}
assert(passed);
std::cout << "passato" << std::endl;
}
/**
* @brief Test sul costruttore di default di SparseMatrix.
*
* Controlla che tutti i dati membro della matrice siano istanziati correttamente tramite il costruttore di default.
*/
void test_default(){
std::cout << "Test costruttore di default: ";
mat_test matrice;
assert(matrice.inserted_items() == 0);
assert(matrice.rows() == 0);
assert(matrice.columns() == 0);
assert(matrice.default_value().value() == test_class().value());
std::cout << "passato" << std::endl;
}
/**
* @Brief Test sugli iteratori
*
* Stampa tutti gli elementi fisicamente inseriti dall'utente
*/
void test_iteratori(){
std::cout << "Iteratore:" << std::endl;
mat_test matrice(10, 10, test_class(-1));
matrice.set(0, 1, test_class(-1));
matrice.set(1, 2, test_class(3));
matrice.set(1, 1, test_class(5));
matrice.set(9, 8, test_class(7));
for(mat_test::const_iterator it = matrice.begin(), end = matrice.end(); it != end; ++it){
std::cout << "(" << it->row() << ", " << (*it).column() << ") -> " << it->value().value() << std::endl;
}
}
/**
* @brief Test sui metodi di element
*
* Verifica che i metodi fondamentali si comportino nel modo corretto all'interno della classe element.
*/
void test_element(){
std::cout << "Test dei metodi di element: ";
mat_test::element el(1, 2, test_class(1));
mat_test::element el2(3, 4, test_class(34));
assert(&el.value() != &el2.value());
el2 = el;
assert(&el.value() != &el2.value());
std::cout << " passato" << std::endl;
}
int main(int argc, char* argv[]) {
test_default();
test_copia();
test_assegnamento();
test_evaluate();
test_bounds();
test_dimensione_negativa();
test_get_elementi_inseriti();
test_dimensione_massima();
test_iteratori();
test_element();
return 0;
}