Si deve realizzare una semplice calcolatrice in grado di sommare una lista di numeri, secondo le seguenti specifiche:
- La calcolatrice è in un ciclo infinito: continua a prendere input e dare output finché non viene interrotta
- prende l’input da una pipe ‘calcPipeIn’ e manda i risultati su una seconda pipe ‘calcPipeOut’. Le pipe vengono create dalla calcolatrice stessa quando viene eseguita
- le espressioni sono semplici somme, ad esempio 10 + 15 + 280. Vengono inviate su calcPipeIn come sequenze di char terminate da #. Ad esempio 10 + 15 + 280 viene inviata come ’10+15+280#’, ovvero 10 byte senza il terminatore di stringa e senza spazi
- il risultati vengono inviati sempre come sequenze di char separati da ‘#’. Se, ad esempio, inviamo ‘1+2#3+4#’ su calcPipeIn ci aspetteremo ‘3#7#’ su calcPipeOut
Viene fornito un programma di test che invia NT espressioni e controlla i risultati. Per vedere il formato di invio dei dati create le pipe da terminale e stampate il contenuto della pipe di output. Poi eseguite il test da un altro terminale. Ecco un esempio:
$ mkfifo calcPipeIn calcPipeOut
$ cat calcPipeIn
39+23+91+95+60+27+53+56#99+90+85+35#69+21+37+9#89+77+23+14+49+93+16#37#96+21+24+19+13+19+80+40#
$
E questo è il corrispondente ouput del file di test
$ ./calc_test
=== INIZIO TEST ===
Espressione 0 composta da 8 numeri: 39 23 91 95 60 27 53 56
somma: 444
leggo dalla pipe ... :FAIL! timeout
Espressione 1 composta da 4 numeri: 99 90 85 35
somma: 309
leggo dalla pipe ... :FAIL! timeout
Espressione 2 composta da 4 numeri: 69 21 37 9
somma: 136
leggo dalla pipe ... :FAIL! timeout
Espressione 3 composta da 7 numeri: 89 77 23 14 49 93 16
somma: 361
leggo dalla pipe ... :FAIL! timeout
Espressione 4 composta da 1 numeri: 37
somma: 37
leggo dalla pipe ... :FAIL! timeout
Espressione 5 composta da 8 numeri: 96 21 24 19 13 19 80 40
somma: 312
leggo dalla pipe ... :FAIL! timeout
=== TEST FALLITO ===
Il sorgente del programma di test è il seguente
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#define PIPE_IN "calcPipeIn"
#define PIPE_OUT "calcPipeOut"
#define MAXEXP 100
#define NT 6
#define DEBUG 1
die(char * s) {
perror(s);
exit(1);
}
// output abilitato se DEBUG == 1
void d_print(char *s, ...) {
va_list ap;
if (DEBUG) {
va_start(ap, s);
vprintf(s,ap);
va_end(ap);
}
}
main() {
int pin,pout,nums,n,i,j,k,r,fail=false,rread;
char sn[MAXEXP],ris[MAXEXP];
// apre le pipe
if( ( pin=open(PIPE_IN,O_RDWR) ) < 0 || ( pout=open(PIPE_OUT,O_RDWR | O_NONBLOCK) ) < 0 )
die("Errore apertura pipe");
srand(time(NULL)); // inizializza il generatore random
d_print("=== INIZIO TEST ===\n");
// genera NT espressioni le invia e controlla il risultato ricevuto
for(i=0;i<NT;i++) {
r=0; // azzera la somma (per il test)
nums = (int) ((float)rand() / RAND_MAX * 9) + 1; // lunghezza espressione
d_print("Espressione %i composta da %i numeri: ",i,nums);
// genera i nums numeri e li invia come stringhe separati da +
// l'ultimo numero e' terminato con #
for(j=0;j<nums;j++) {
// sceglie un numero a caso
n = (int) ((float)rand() / RAND_MAX * 100);
d_print("%i ",n);
r += n; // aggiorna la somma (per il test successivo)
sprintf(sn,"%i",n); // crea la stringa
write(pin,sn,strlen(sn)); // la invia sulla pipe
if (j==nums-1) // e' l'ultimo numero?
write(pin,"#",1); // termina l'espressione
else
write(pin,"+",1); // aggiunge il simbolo +
}
d_print("\n somma: %i",r);
// controlliamo il risultato dalla pipe
d_print("\n leggo dalla pipe ... :"); fflush(stdout);
k=0;
// leggo un risultato. La lettura e' non bloccante (vedi la open)
while(k<MAXEXP-1 && (rread=read(pout,&ris[k],1))>0 && ris[k] != '#') k++;
// se per caso non ha letto nulla ritenta dopo un secondo
if (rread < 0 && errno ==EAGAIN) {
sleep(1);
while(k<MAXEXP-1 && (rread=read(pout,&ris[k],1))>0 && ris[k] != '#') k++;
}
if (rread < 0 && errno ==EAGAIN) {
// anche al secondo tentativo non ho letto nulla
d_print("FAIL! timeout\n");
fail = true;
} else if (atoi(ris) == r)
// ho letto la somma corretta
d_print("OK\n");
else {
// ho letto un valore errato, stampo la stringa letta dalla pipe
ris[k+1] ='\0';
d_print("FAIL! Ho letto %s\n",ris);
fail = true;
}
}
if (fail) {
d_print("=== TEST FALLITO ===\n");
exit(1);
}else{
d_print("=== TEST SUPERATO ===\n");
exit(0);
}
}