Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Showing
with 848 additions and 0 deletions
stages:
- build
- test
image: montavont/algodesreseaux
build_04:
stage: build
script:
- cd 04-affichage-adresse
- scons
artifacts:
paths:
- 04-affichage-adresse/receiver-udp
# run tests using the binary build before
test_04:
stage: test
needs: [build_04]
script:
- |
echo "starting tests"
cd 04-affichage-adresse
bash tests.sh
File added
# Algorithmes des réseaux
## Affichage d'adresse IP et port
Dans l'exercice précédent, les informations de l'expéditeur (adresse IP et port) n'étaient pas enregistrées lors de l'appel à `recvfrom()`. Dans cet exercice, vous allez récupérer ces informations et les afficher sous la forme de chaînes de caractères.
Le programme admet en argument l'adresse IP et le numéro de port sur lequel le programme doit écouter :
./receiver-udp ip_addr port
Les seuls numéros de port valides sont ceux contenus dans l'intervalle `[10000; 65000]`.
La sortie de votre programme doit être de la forme suivante :
./receiver-udp 192.168.1.233 10001
hello world
192.168.1.1 57123
Une telle sortie indique que votre programme a reçu le message `hello world` d'une source dont l'adresse IP est `192.168.1.1` et le port est `57123`.
On fera l'hypothèse que le message aura une taille maximum de `SIZE` caractères.
**Objectifs :** savoir récupérer les informations d'un expéditeur et les afficher.
## Marche à suivre
Reprennez le code source de l'exercice précédent et mettez à jour la gestion des arguments.
Vous pouvez récupérer des informations sur l'expéditeur via les deux derniers paramètres de la primitive `recvfrom()` qui permettent de compléter une variable de type `struct sockaddr_storage` castée en un pointeur vers une structure `struct sockaddr`.
Ensuite, vous pouvez transformer les informations contenues dans cette structure (adresse IP et port) en des chaînes de caractères via la fonction :
int getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags)
Consultez le manuel utilisateur pour connaître les options possibles et comment traiter les erreurs associées à la fonction `getnameinfo()`.
Vous pouvez tester votre programme avec le programme réalisé dans l'exercice 2 ou en exécutant la commande `nc` (netcat) dans un autre terminal. Lancez votre programme dans un terminal puis exécutez la commande suivante dans un second terminal afin d'envoyer le message `hello world` en UDP sur l'adresse (par exemple `127.0.0.1`) et le port utilisé par votre programme, et le port de votre choix en tant que port local :
echo "hello world" | nc -4u -w1 addr_du_prog port_du_prog -p port_local_pour_netcat
Vérifiez ensuite que l'adresse IP et le port affichés par votre programme sont conformes à ceux utilisés par l'expéditeur.
## Validation
Votre programme doit obligatoirement passer tous les tests sur gitlab (il suffit de `commit/push` le fichier source pour déclencher le pipeline de compilation et de tests) avant de passer à l'exercice suivant.
sources = Glob ("*.c")
CFLAGS = ["-Wall", "-Wextra", "-Werror", "-g"]
env = Environment (CCFLAGS = CFLAGS)
env.Program (sources)
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#define CHECK(op) do { if ( (op) == -1) { perror (#op); exit (EXIT_FAILURE); } \
} while (0)
#define IP "127.0.0.1"
#define SIZE 100
void raler(const char *chaine) {
fprintf(stderr, "%s\n", chaine);
exit(EXIT_FAILURE);
}
void usage(const char *chaine){
fprintf(stderr, "usage: %s ip_addr port_number\n", chaine);
exit(EXIT_FAILURE);
}
int main (int argc, char *argv [])
{
/* test arg number */
if(argc != 3){
usage(argv[0]);
}
/* convert and check port number */
int port_number = atoi(argv[2]);
if (port_number < 10000 || port_number > 65000) {
raler("Wrong port value: port_number not in [10000;65000]");
}
/* create socket */
int new_socket;
CHECK(new_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
/* complete struct sockaddr */
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET; // Use IPv4
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_NUMERICHOST;
int error = getaddrinfo(argv[1], argv[2], &hints, &res);
if (error != 0) {
fprintf(stderr,"getaddrinfo %s\n",gai_strerror(error)); // Generic error message
exit(1); // Set the exit status to 1
}
/* link socket to local IP and PORT */
CHECK(bind(new_socket,res->ai_addr,res->ai_addrlen));
/* wait for incoming message */
char buffer[SIZE];
ssize_t n;
struct sockaddr_storage ss;
socklen_t pointer_size = sizeof(ss);
CHECK(n=recvfrom(new_socket,buffer,SIZE,0,(struct sockaddr *)&ss,&pointer_size));
buffer[n] = '\0';
char host[NI_MAXHOST];
char serv[NI_MAXSERV];
if(getnameinfo((struct sockaddr*)&ss,pointer_size,host,NI_MAXHOST,serv,NI_MAXSERV,NI_NUMERICHOST | NI_NUMERICSERV)!=0){
raler("getnameinfo");
}
/* close socket */
close(new_socket);
/* free memory */
freeaddrinfo(res);
/* print received message */
printf("%s\n",buffer);
printf("%s %s",host,serv);
return 0;
}
#!/bin/bash
PROG="./receiver-udp"
FILE="$PROG.c"
PORT=`shuf -i 10000-30000 -n 1`
PORT_C=`shuf -i 30001-65000 -n 1`
IP="127.0.0.1"
OUT="/tmp/$$"
mkdir $OUT
SE=$(uname -s)
######################################
echo -n "test 01 - program usage: "
echo "usage: $PROG ip_addr port_number" > $OUT/usage
$PROG > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! cmp -s $OUT/usage $OUT/stderr && echo "KO -> unexpected output on stderr => check file \"$OUT/usage\"" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
$PROG a > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! cmp -s $OUT/usage $OUT/stderr && echo "KO -> unexpected output on stderr => check file \"$OUT/usage\"" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
$PROG a b c > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! cmp -s $OUT/usage $OUT/stderr && echo "KO -> unexpected output on stderr => check file \"$OUT/usage\"" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
echo "....................OK"
######################################
echo -n "test 02 - invalid port number: "
$PROG a 65001 > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! [ -s $OUT/stderr ] && echo "KO -> no output on stderr" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
$PROG a 9999 > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! [ -s $OUT/stderr ] && echo "KO -> no output on stderr" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
echo "..............OK"
######################################
echo -n "test 03 - getaddrinfo usage: "
ERROR="Name or service not known"
if [ "$SE" == "Darwin" ]; then
ERROR="nodename nor servname provided, or not known"
fi
LC_ALL=C $PROG a $PORT > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! grep -q "$ERROR" $OUT/stderr && echo "KO -> unexpected output on stderr, do you use gai_strerror?" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
echo "................OK"
######################################
echo -n "test 04 - check bind failure: "
timeout 8 nc -4ul $IP $PORT > /dev/null &
TO=$!
sleep 3
LC_ALL=C timeout 5 $PROG $IP $PORT > $OUT/stdout 2> $OUT/stderr
R="$?"
[ "$R" == "124" ] && echo "KO -> program times out" && exit 1
[ "$R" != "1" ] && echo "KO -> exit status $R instead of 1" && exit 1
wait $!
ERROR="Address already in use"
! grep -q "$ERROR" $OUT/stderr && echo "KO -> unexpected output on stderr, do you use perror?" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
echo "...............OK"
######################################
echo -n "test 05 - program exits without error: "
timeout 5 $PROG $IP $PORT > $OUT/stdout 2> $OUT/stderr &
TO=$!
sleep 2
echo "hello world" | nc -4u -w1 $IP $PORT -p $PORT_C
wait $TO
R=$?
[ "$R" == "124" ] && echo "KO -> program times out" && exit 1
[ "$R" != "0" ] && echo "KO -> exit status $R instead of 0" && exit 1
[ -s $OUT/stderr ] && echo "KO -> output detected on stdout" && exit 1
echo "......OK"
######################################
echo -n "test 06 - program received a message: "
! [ -s $OUT/stdout ] && echo "KO -> no message received (stdout empty)" && exit 1
echo ".......OK"
######################################
echo -n "test 07 - message is valid: "
echo "hello world" > $OUT/msg_e
head -1 $OUT/stdout > $OUT/msg_r
! cmp -s $OUT/msg_e $OUT/msg_r && echo "KO -> unexpected msg: check files \"$OUT/msg_e\" file and \"$OUT/msg_r\" (yours)" && exit 1
echo ".................OK"
######################################
echo -n "test 08 - program prints sender IP and port: "
NB=`cat $OUT/stdout | wc -l | tr -s ' ' | cut -d ' ' -f2`
[ "$NB" != "2" ] && echo "KO -> no output detected on stdout" && exit 1
echo "OK"
######################################
echo -n "test 09 - printed IP is valid: "
PRINTEDIP=`cat $OUT/stdout | tail -1 | cut -d ' ' -f1`
[ "$PRINTEDIP" != "$IP" ] && echo "KO -> printed IP: $PRINTEDIP | expected: $IP" && exit 1
echo "..............OK"
######################################
echo -n "test 10 - printed PORT is valid: "
PRINTEDPORT=`cat $OUT/stdout | tail -1 | cut -d ' ' -f2`
[ "$PRINTEDPORT" != "$PORT_C" ] && echo "KO -> printed PORT: $PRINTEDPORT | expected: $PORT_C" && exit 1
echo "............OK"
######################################
echo -n "test 11 - memory error: "
P=`which valgrind`
[ -z "$P" ] && echo "KO -> please install valgrind" && exit 1
LC_ALL=C tr -dc "A-Za-z0-9" < /dev/urandom | head -c 2048 > $OUT/toto
valgrind --leak-check=full --error-exitcode=100 --log-file=$OUT/valgrind.log $PROG $IP $PORT > /dev/null &
V=$!
sleep 4
nc -4u -w1 $IP $PORT < $OUT/toto
wait $V
[ "$?" == "100" ] && echo "KO -> memory pb please check $OUT/valgrind.log" && exit 1
echo ".....................OK"
######################################
rm -r $OUT
stages:
- build
- test
image: montavont/algodesreseaux
build_05:
stage: build
script:
- cd 05-emetteurUDPv6
- scons
artifacts:
paths:
- 05-emetteurUDPv6/sender-udp
# run tests using the binary build before
test_05:
stage: test
needs: [build_05]
script:
- |
echo "starting test"
cd 05-emetteurUDPv6
bash tests.sh
File added
# Algorithmes des réseaux
## Expéditeur UDP IPv6
Complétez le programme `sender-udp.c` pour envoyer le message texte `hello world` avec les protocoles `IPv6` et `UDP`.
Le programme admet en argument l'adresse IP et le numéro de port de l'hôte distant à contacter :
./sender-udp ip_addr port_number
Les seuls numéros de port valides sont ceux contenus dans l'intervalle `[10000; 65000]`.
**Objectifs :** savoir créer un socket IPv6 et transmettre un message texte en UDP.
## Marche à suivre :
Vous pouvez directement reprendre le code réalisé dans l'exercice 2 et mettre à jour les parties spécifiques à `IPv4`. Ici l'hôte distant sera joignable sur l'adresse `::1` et le port passé en argument du programme.
Vous pouvez tester votre programme en exécutant la commande `nc` (netcat) dans un autre terminal afin d'écouter en UDP sur l'adresse `::1` et le port de votre choix :
nc -6ul ::1 port_number
Vous pouvez ensuite lancer votre programme dans un autre terminal et vérifier que le message transmis est bien affiché par `netcat` sur la sortie standard.
## Validation
Votre programme doit obligatoirement passer tous les tests sur gitlab (il suffit de `commit/push` le fichier source pour déclencher le pipeline de compilation et de tests) avant de passer à l'exercice suivant.
sources = Glob ("*.c")
CFLAGS = ["-Wall", "-Wextra", "-Werror", "-g"]
env = Environment (CCFLAGS = CFLAGS)
env.Program (sources)
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#define CHECK(op) do { if ( (op) == -1) { perror (#op); exit (EXIT_FAILURE); } \
} while (0)
#define IP "::1"
void raler(const char *chaine) {
fprintf(stderr, "%s\n", chaine);
exit(EXIT_FAILURE);
}
void usage(const char *chaine){
fprintf(stderr, "usage: %s ip_addr port_number\n", chaine);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[]) {
const char *msg = "hello world";
/* test arg number */
if (argc != 3) {
usage(argv[0]);
}
/* convert and check port number */
int port_number = atoi(argv[2]);
if (port_number < 10000 || port_number > 65000) {
raler("Wrong port value: port_number not in [10000;65000]");
}
/* create socket */
int new_socket;
CHECK(new_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)); // 0 for protocol
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6; // Use IPv4
hints.ai_socktype = SOCK_DGRAM;
int error = getaddrinfo(argv[1], argv[2], &hints, &res);
if (error != 0) {
fprintf(stderr,"getaddrinfo %s\n",gai_strerror(error)); // Generic error message
exit(1); // Set the exit status to 1
}
/* send message to remote peer */
int bytes_sent = sendto(new_socket, msg, strlen(msg), 0, res->ai_addr, res->ai_addrlen);
CHECK(bytes_sent);
/* close socket */
close(new_socket);
freeaddrinfo(res); // Free the dynamically allocated address info
return 0;
}
#!/bin/bash
PROG="./sender-udp"
PORT=`shuf -i 10000-65000 -n 1`
OUT="/tmp/$$"
mkdir $OUT
IP="::1"
######################################
echo -n "test 01 - program without arg: "
echo "usage: $PROG ip_addr port_number" > $OUT/usage
$PROG > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! cmp -s $OUT/usage $OUT/stderr && echo "KO -> unexpected output on stderr => check file \"$OUT/usage\"" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
$PROG a > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! cmp -s $OUT/usage $OUT/stderr && echo "KO -> unexpected output on stderr => check file \"$OUT/usage\"" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
$PROG a b c > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! cmp -s $OUT/usage $OUT/stderr && echo "KO -> unexpected output on stderr => check file \"$OUT/usage\"" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
echo "........OK"
######################################
echo -n "test 02 - invalid port number: "
$PROG a 65001 > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! [ -s $OUT/stderr ] && echo "KO -> no output on stderr" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
$PROG a 9999 > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! [ -s $OUT/stderr ] && echo "KO -> no output on stderr" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
echo "........OK"
######################################
echo -n "test 03 - getaddrinfo usage: "
ERROR="Name or service not known"
LC_ALL=C $PROG a $PORT > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! grep -q "$ERROR" $OUT/stderr && echo "KO -> unexpected output on stderr, do you use gai_strerror?" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
echo "..........OK"
######################################
echo -n "test 04 - program exits without error: "
timeout 5 nc -6ul $IP $PORT > $OUT/msg_r &
sleep 2
! $PROG $IP $PORT > $OUT/stdin 2> $OUT/stderr && echo "KO -> exit status != 0" && exit 1
[ -s $OUT/stderr ] && echo "KO -> output detected on stderr" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
echo "OK"
######################################
echo -n "test 05 - program sends a message: "
! [ -s $OUT/msg_r ] && echo "KO -> no message received (stdout empty)" && exit 1
echo "....OK"
######################################
echo -n "test 06 - message is valid: "
printf "hello world" > $OUT/msg_o
! cmp -s $OUT/msg_o $OUT/msg_r && echo "KO -> check files \"$OUT/msg_o\" (expected) and \"$OUT/msg_r\" (sent)" && exit 1
echo "...........OK"
######################################
echo -n "test 07 - memory error: "
P=`which valgrind`
[ -z "$P" ] && echo "KO -> please install valgrind" && exit 1
valgrind --leak-check=full --error-exitcode=100 --log-file=$OUT/valgrind.log $PROG $IP $PORT
[ "$?" == "100" ] && echo "KO -> memory pb please check valgrind.log" && exit 1
echo "...............OK"
rm -r $OUT
stages:
- build
- test
image: montavont/algodesreseaux
build_06:
stage: build
script:
- cd 06-recepteurUDPv6
- scons
artifacts:
paths:
- 06-recepteurUDPv6/receiver-udp
# run tests using the binary build before
test_06:
stage: test
needs: [build_06]
script:
- |
echo "starting tests"
cd 06-recepteurUDPv6
bash tests.sh
File added
# Algorithmes des réseaux
## Récepteur UDP IPv6
Complétez le programme `receiver-udp.c` pour recevoir un message texte avec les protocoles `IPv6` et `UDP` et l'afficher sur la sortie standard. Vous devrez également afficher l'adresse IP et le port de l'expéditeur du message.
Le programme admet en argument l'adresse IP et le numéro de port sur lequel le programme doit écouter :
./receiver-udp ip_addr port_number
Les seuls numéros de port valides sont ceux contenus dans l'intervalle `[10000; 65000]`.
La sortie de votre programme doit être de la forme suivante :
./receiver-udp 2001:db8:dead:beef::2 10001
hello world
2001:db8:dead:beef::1 57123
Une telle sortie indique que votre programme a reçu le message `hello world` d'une source dont l'adresse IP est `2001:db8:dead:beef::1` et le port est `57123`.
On fera l'hypothèse que le message aura une taille maximum de `SIZE` caractères.
**Objectifs :** savoir recevoir un message texte en UDP.
## Marche à suivre
Vous pouvez directement reprendre le code réalisé dans l'exercice 4 et mettre à jour les parties spécifiques à `IPv4`.
Vous pouvez tester votre programme avec le programme réalisé dans l'exercice 5 ou en exécutant la commande `nc` (netcat) dans un autre terminal. Lancez votre programme dans un terminal puis exécutez la commande suivante dans un second terminal afin d'envoyer le message `hello world` en `UDP` sur l'adresse (par exemple `::1`) et le port utilisés par votre programme, et en utilisant le port local de votre choix :
echo "hello world" | nc -6u -w1 addr_du_prog port_du_prog -p port_local_pour_netcat
Vérifiez ensuite que le message ainsi que l'adresse IP et le port source sont correctement affichés par votre programme sur la sortie standard.
## Validation
Votre programme doit obligatoirement passer tous les tests sur gitlab (il suffit de `commit/push` le fichier source pour déclencher le pipeline de compilation et de tests) avant de passer à l'exercice suivant.
sources = Glob ("*.c")
CFLAGS = ["-Wall", "-Wextra", "-Werror", "-g"]
env = Environment (CCFLAGS = CFLAGS)
env.Program (sources)
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#define CHECK(op) do { if ( (op) == -1) { perror (#op); exit (EXIT_FAILURE); } \
} while (0)
#define IP "::1"
#define SIZE 100
int main (int argc, char *argv [1])
{
/* test arg number */
if(argc != 3)
{
fprintf(stderr, "usage: %s ip_addr port_number\n", argv[0]);
exit(EXIT_FAILURE);
}
/* convert and check port number */
int port_number = atoi(argv[2]);
if(port_number < 10000 || port_number > 65000){
perror("Invalid port number\n");
exit(EXIT_FAILURE);
}
/* create socket */
int new_socket=socket(AF_INET6,SOCK_DGRAM,IPPROTO_UDP);
CHECK(new_socket);
int error;
struct addrinfo *res;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
error =getaddrinfo(argv[1],argv[2],&hints,&res);
if(error!=0){
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
exit(EXIT_FAILURE);
}
/* complete struct sockaddr */
struct addrinfo *list_udp=res;
while (list_udp->ai_protocol != IPPROTO_UDP)
{
list_udp = list_udp->ai_next;
if (list_udp == NULL)
{
perror("Problème pas de protocole UDP");
exit(EXIT_FAILURE);
}
}
/* link socket to local IP and PORT */
CHECK(bind(new_socket,list_udp->ai_addr,list_udp->ai_addrlen));
/* wait for incoming message */
char buffer[SIZE],ip[SIZE],port[SIZE];
struct sockaddr_storage socket_storage;
socklen_t socket_len = sizeof(socket_storage);
int result =recvfrom(new_socket,buffer,SIZE,0,(struct sockaddr*)&socket_storage,&socket_len);
CHECK(result);
buffer[SIZE]='\0';
ip[SIZE]='\0';
port[SIZE]='\0';
/* print sender addr and port */
if(getnameinfo((struct sockaddr*)&socket_storage,socket_len,ip,SIZE,port,SIZE,NI_NUMERICHOST | NI_NUMERICSERV)==0){
fprintf(stdout,"%s",buffer);
fprintf(stdout,"%s %s\n",ip,port);
}
/* close socket */
close(new_socket);
/* free memory */
freeaddrinfo(res);
return 0;
}
#!/bin/bash
PROG="./receiver-udp"
FILE="$PROG.c"
PORT=`shuf -i 10000-30000 -n 1`
PORT_C=`shuf -i 30001-65000 -n 1`
IP="::1"
OUT="/tmp/$$"
mkdir $OUT
######################################
echo -n "test 01 - program usage: "
echo "usage: $PROG ip_addr port_number" > $OUT/usage
$PROG > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! cmp -s $OUT/usage $OUT/stderr && echo "KO -> unexpected output on stderr => check file \"$OUT/usage\"" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
$PROG a > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! cmp -s $OUT/usage $OUT/stderr && echo "KO -> unexpected output on stderr => check file \"$OUT/usage\"" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
$PROG a b c > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! cmp -s $OUT/usage $OUT/stderr && echo "KO -> unexpected output on stderr => check file \"$OUT/usage\"" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
echo "....................OK"
######################################
echo -n "test 02 - invalid port number: "
$PROG a 65001 > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! [ -s $OUT/stderr ] && echo "KO -> no output on stderr" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
$PROG a 9999 > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! [ -s $OUT/stderr ] && echo "KO -> no output on stderr" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
echo "..............OK"
######################################
echo -n "test 03 - getaddrinfo usage: "
ERROR="Name or service not known"
LC_ALL=C $PROG a $PORT > $OUT/stdout 2> $OUT/stderr && echo "KO -> exit status $? instead of 1" && exit 1
! grep -q "$ERROR" $OUT/stderr && echo "KO -> unexpected output on stderr, do you use gai_strerror?" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
echo "................OK"
######################################
echo -n "test 04 - check bind failure: "
timeout 8 nc -6ul $IP $PORT > /dev/null &
TO=$!
sleep 3
LC_ALL=C timeout 5 $PROG $IP $PORT > $OUT/stdout 2> $OUT/stderr
R="$?"
[ "$R" == "124" ] && echo "KO -> program times out" && exit 1
[ "$R" != "1" ] && echo "KO -> exit status $R instead of 1" && exit 1
wait $!
ERROR="Address already in use"
! grep -q "$ERROR" $OUT/stderr && echo "KO -> unexpected output on stderr, do you use perror?" && exit 1
[ -s $OUT/stdout ] && echo "KO -> output detected on stdout" && exit 1
echo "...............OK"
######################################
echo -n "test 05 - program exits without error: "
timeout 5 $PROG $IP $PORT > $OUT/stdout 2> $OUT/stderr &
TO=$!
sleep 2
echo "hello world" | nc -6u -w1 $IP $PORT -p $PORT_C
wait $TO
R=$?
[ "$R" == "124" ] && echo "KO -> program times out" && exit 1
[ "$R" != "0" ] && echo "KO -> exit status $R instead of 0" && exit 1
[ -s $OUT/stderr ] && echo "KO -> output detected on stdout" && exit 1
echo "......OK"
######################################
echo -n "test 06 - program received a message: "
! [ -s $OUT/stdout ] && echo "KO -> no message received (stdout empty)" && exit 1
echo ".......OK"
######################################
echo -n "test 07 - message is valid: "
echo "hello world" > $OUT/msg_e
head -1 $OUT/stdout > $OUT/msg_r
! cmp -s $OUT/msg_e $OUT/msg_r && echo "KO -> unexpected msg: check files \"$OUT/msg_e\" file and \"$OUT/msg_r\" (yours)" && exit 1
echo ".................OK"
######################################
echo -n "test 08 - program prints sender IP and port: "
NB=`cat $OUT/stdout | wc -l | tr -s ' ' | cut -d ' ' -f2`
[ "$NB" != "2" ] && echo "KO -> no output detected on stdout" && exit 1
echo "OK"
######################################
echo -n "test 09 - printed IP is valid: "
IP=`cat $OUT/stdout | tail -1 | cut -d ' ' -f1`
[ "$IP" != "$IP" ] && echo "KO -> printed IP: $IP | expected: $IP" && exit 1
echo "..............OK"
######################################
echo -n "test 10 - printed PORT is valid: "
PORT=`cat $OUT/stdout | tail -1 | cut -d ' ' -f2`
[ "$PORT" != "$PORT_C" ] && echo "KO -> printed PORT: $PORT | expected: $PORT_C" && exit 1
echo "............OK"
######################################
echo -n "test 11 - memory error: "
P=`which valgrind`
[ -z "$P" ] && echo "KO -> please install valgrind" && exit 1
LC_ALL=C tr -dc "A-Za-z0-9" < /dev/urandom | head -c 2048 > $OUT/toto
valgrind --leak-check=full --error-exitcode=100 --log-file=$OUT/valgrind.log $PROG $IP $PORT > /dev/null &
V=$!
sleep 4
nc -6u -w1 $IP $PORT < $OUT/toto
wait $V
[ "$?" == "100" ] && echo "KO -> memory pb please check $OUT/valgrind.log" && exit 1
echo ".....................OK"
rm -r $OUT
stages:
- build
- test
image: montavont/algodesreseaux
build_07:
stage: build
script:
- cd 07-emetteurTCPv4
- scons
artifacts:
paths:
- 07-emetteurTCPv4/sender-tcp
# run tests using the binary build before
test_07:
stage: test
needs: [build_07]
script:
- |
echo "starting tests"
cd 07-emetteurTCPv4
bash tests.sh
File added