-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME.txt
289 lines (235 loc) · 10.5 KB
/
README.txt
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
286
287
288
289
# Exemple d'exercice en C avec correction automatique
## Enoncé
Vous devez écrire une fonction réalisant le parcours infixe d'un arbre binaire donné par la structure suivante:
```c
typedef struct tree{
int value; // the value at root of this tree
int number_elements; // number of elements in the tree bellow this root (including self)
struct tree *left; // left sub-tree
struct tree *right; // right sub-tree
}tree_t;
/**
* 1
* / \
* 0 2
* /
* -1
*
* => tree(1).number_elements = 4 because it has 3 childs + himself
*/
```
```c
/**
* @brief Travel in a in-order tour the binary tree
*
* @pre tree : the binary tree to travel
* @post int* : an array containing the list of integers according to the in-order tour;
* NULL if the tree is NULL, or if an error occurs
*/
int *in_order(tree_t *tree);
```
Exemples d'utilisation
```
/**
* t =
* 1
* / \
* 0 2
*/
- in_order(t) retourne [0, 1, 2]
/**
* t =
* 1
* / \
* 0 2
* / /
*/ 15 -1
- in_order(t) retourne [15, 0, 1, -1, 2]
/**
* t =
* 15
* / \
* 0 22
* / \ /
* -3 1 20
* \
* 21
*/
- in_order(t) retourne [-3, 0, 1, 15, 20, 21, 22]
```
## Solution correcte
-----------------
```c
int *in_order(tree_t *tree){
if (tree == NULL) return NULL;
int *ret = malloc(tree->number_elements * sizeof(int));
if (ret == NULL) return NULL;
int index = 0; // number of elements already copied to the response array
if (tree->left != NULL){
int *temp = in_order(tree->left); // result for left sub-tree
if (temp == NULL) return NULL; // error in malloc
memcpy(ret, temp, tree->left->number_elements * sizeof(int));
free(temp);
index += tree->left->number_elements;
}
*(ret+index) = tree->value;
index++;
if (tree->right != NULL){
int *temp = in_order(tree->right); // result for right sub-tree
if (temp == NULL) return NULL; // error in malloc
memcpy(ret+index, temp, tree->right->number_elements * sizeof(int));
free(temp);
}
return ret;
}
```
## Description de la suite de tests
--------------------------------
Pour la suite de test, j'utilise les propriétés des arbres binaires de recherche afin de créer des arbres facilement (toutes les clés < valeur se trouvent à gauche de la racine et les clés >= valeur se trouvent à droite de celle-ci)
Je pense à vérifier également les cas limites (arbres qui ne sont qu'une seule branche ou ayant qu'un seul enfant).
J'utilise également un test aléatoire afin de mieux garantir l'exactitude de la fonction. Je stocke dans un tableau le nombre de fois que la valeur est censée apparaître et je décrémente celle-ci afin de vérifier que chaque valeur apparait le bon nombre de fois. Je vérifie ensuite qu'elles sortent dans le bon ordre grâce à la propriété de parcours in-order des arbres binaires de recherche, retournant un tableau trié en ordre croissant.
Par la suite, j'utilise les fonction malloc_hook et free_hook pour compter le nombre de malloc et de free appelé par le code de l'étudiant lors de son exécution. Je vérifie ensuite grâce à un assert que le nombre de malloc est bien égal au nombre de free + 1 (il faut un malloc non free pour retourner le tableau d'int tel que demandé dans la spécification). Nous vérifions ainsi qu'il n'y a pas de memory leak causé par le code de l'étudiant. Ceci génère malheureusement des alertes de compilation de par le fait que malloc_hook et free_hook sont obsolètes.
Enfin, j'utilise à nouveau la fonction malloc_hook afin de forcer un malloc à retourner NULL, pour vérifier que l'étudiant traite également le cas limite lorsque le malloc échoue, et qu'il doit donc renvoyer NULL.
## Exécution de la suite de tests avec la solution correcte
--------------------------------------------------------
```
CUnit - A unit testing framework for C - Version 2.1-3
http://cunit.sourceforge.net/
Suite: Suite_1
Test: test in-order simple balanced binary tree ...passed
Test: test in-order linear binary tree (only right child) ...passed
Test: test in-order linear binary tree (only left child) ...passed
Test: test in-order binary tree (with missing right/left children) ...passed
Test: test in-order binary tree (random tree) ...passed
Test: test in-order binary tree with NULL tree ...passed
Test: test in-order binary tree with failed malloc ...passed
Run Summary: Type Total Ran Passed Failed Inactive
suites 1 1 n/a 0 0
tests 7 7 7 0 0
asserts 2024 2024 2024 0 n/a
Elapsed time = 0.016 seconds
```
## Erreurs détectées par la suite de test
--------------------------------------
Pour les exemples, j'ai désactivé le test sur un arbre aléatoire car celui-ci génère beaucoup de messages d'erreurs, troublant la visibilité des autres tests. Néanmoins, il est tout à fait possible de faire tourner ce tests pour les codes erronés, et il renverra un message d'erreur signalant que le code est incorrect.
### Exemple 1:
Code qui ne traite pas le fait qu'un malloc puisse échouer ou ne traitant pas le fait que l'arbre soit NULL
```c
int *in_order(tree_t *tree){
int *ret = malloc(tree->number_elements * sizeof(int));
int index = 0; // number of elements already copied to the response array
if (tree->left != NULL){
int *temp = in_order(tree->left); // result for left sub-tree
memcpy(ret, temp, tree->left->number_elements * sizeof(int));
free(temp);
index += tree->left->number_elements;
}
*(ret+index) = tree->value;
index++;
if (tree->right != NULL){
int *temp = in_order(tree->right); // result for right sub-tree
memcpy(ret+index, temp, tree->right->number_elements * sizeof(int));
free(temp);
}
return ret;
}
```
```
CUnit - A unit testing framework for C - Version 2.1-3
http://cunit.sourceforge.net/
Suite: Suite_1
Test: test in-order simple balanced binary tree ...passed
Test: test in-order linear binary tree (only right child) ...passed
Test: test in-order linear binary tree (only left child) ...passed
Test: test in-order binary tree (with missing right/left children) ...passed
Test: test in-order binary tree with failed malloc ...Segmentation fault (core dumped)
```
### Exemple 2:
Code qui oublie de libérer la mémoire temporaire:
```c
int *in_order(tree_t *tree){
if (tree == NULL) return NULL;
int *ret = malloc(tree->number_elements * sizeof(int));
if (ret == NULL) return NULL;
int index = 0; // number of elements already copied to the response array
if (tree->left != NULL){
int *temp = in_order(tree->left); // result for left sub-tree
if (temp == NULL) return NULL; // error in malloc
memcpy(ret, temp, tree->left->number_elements * sizeof(int));
index += tree->left->number_elements;
}
*(ret+index) = tree->value;
index++;
if (tree->right != NULL){
int *temp = in_order(tree->right); // result for right sub-tree
if (temp == NULL) return NULL; // error in malloc
memcpy(ret+index, temp, tree->right->number_elements * sizeof(int));
}
return ret;
}
```
```
CUnit - A unit testing framework for C - Version 2.1-3
http://cunit.sourceforge.net/
Suite: Suite_1
Test: test in-order simple balanced binary tree ...passed
Test: test in-order linear binary tree (only right child) ...passed
Test: test in-order linear binary tree (only left child) ...passed
Test: test in-order binary tree (with missing right/left children) ...passed
Test: test in-order binary tree (random tree) ...passed
Test: test in-order binary tree with failed malloc ...Segmentation fault (core dumped)
```
### Exemple 3:
Code qui écrase les modifications du parcours du sous-arbre de gauche
```c
int *in_order(tree_t *tree){
if (tree == NULL) return NULL;
int *ret = malloc(tree->number_elements * sizeof(int));
if (ret == NULL) return NULL;
int index = 0; // number of elements already copied to the response array
if (tree->left != NULL){
int *temp = in_order(tree->left); // result for left sub-tree
if (temp == NULL) return NULL; // error in malloc
memcpy(ret, temp, tree->left->number_elements * sizeof(int));
free(temp);
}
*(ret+index) = tree->value;
index++;
if (tree->right != NULL){
int *temp = in_order(tree->right); // result for right sub-tree
if (temp == NULL) return NULL; // error in malloc
memcpy(ret+index, temp, tree->right->number_elements * sizeof(int));
free(temp);
}
return ret;
}
```
```
CUnit - A unit testing framework for C - Version 2.1-3
http://cunit.sourceforge.net/
Suite: Suite_1
Test: test in-order simple balanced binary tree ...FAILED
1. tests.c:157 - CU_ASSERT_EQUAL(*(ret+i),expected[i])
2. tests.c:157 - CU_ASSERT_EQUAL(*(ret+i),expected[i])
3. tests.c:157 - CU_ASSERT_EQUAL(*(ret+i),expected[i])
Test: test in-order linear binary tree (only right child) ...passed
Test: test in-order linear binary tree (only left child) ...FAILED
1. tests.c:222 - CU_ASSERT_EQUAL(*(ret+i),expected[i])
2. tests.c:222 - CU_ASSERT_EQUAL(*(ret+i),expected[i])
3. tests.c:222 - CU_ASSERT_EQUAL(*(ret+i),expected[i])
Test: test in-order binary tree (with missing right/left children) ...FAILED
1. tests.c:257 - CU_ASSERT_EQUAL(*(ret+i),expected[i])
2. tests.c:257 - CU_ASSERT_EQUAL(*(ret+i),expected[i])
3. tests.c:257 - CU_ASSERT_EQUAL(*(ret+i),expected[i])
4. tests.c:257 - CU_ASSERT_EQUAL(*(ret+i),expected[i])
5. tests.c:257 - CU_ASSERT_EQUAL(*(ret+i),expected[i])
6. tests.c:257 - CU_ASSERT_EQUAL(*(ret+i),expected[i])
7. tests.c:257 - CU_ASSERT_EQUAL(*(ret+i),expected[i])
Test: test in-order binary tree with NULL tree ...passed
Test: test in-order binary tree with failed malloc ...passed
Run Summary: Type Total Ran Passed Failed Inactive
suites 1 1 n/a 0 0
tests 6 6 3 3 0
asserts 24 24 11 13 n/a
Elapsed time = 0.016 seconds
```