> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-fbfa8bee.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Guide pour tester ClickHouse et exécuter la suite de tests

# Tests de ClickHouse

<div id="test-types">
  ## Types de tests
</div>

ClickHouse comprend les tests suivants :

* [Tests fonctionnels](#functional-tests) - un ensemble de requêtes et de scripts comprenant les sous-ensembles suivants, qui se recoupent
  * [Test rapide](#running-fast-tests) - le sous-ensemble minimal
  * [Tests sans état](#running-stateless-tests) qui ne nécessitent pas de préremplir les bases de données avec des données
  * Tests séquentiels qui ne peuvent pas être exécutés en parallèle
* [Tests d'intégration](#integration-tests), exécutés par `pytest` dans un cluster
* [Tests unitaires](#unit-tests)
* [Tests de performance](#performance-tests)
* [Tests de build](#build-tests)
* [Sanitizers](#sanitizers)
* [Fuzzers](#fuzzing)
  et quelques autres ; voir les sections ci-dessous.

<div id="functional-tests">
  ## Tests fonctionnels
</div>

Les tests fonctionnels sont les plus simples et les plus pratiques à utiliser.
La plupart des fonctionnalités de ClickHouse peuvent être testées avec des tests fonctionnels, et ils sont obligatoires pour toute modification du code de ClickHouse pouvant être testée de cette façon.

Chaque test fonctionnel envoie une ou plusieurs requêtes au serveur ClickHouse en cours d’exécution et compare le résultat à la référence.

Les tests se trouvent dans le répertoire `./tests/queries`.

Chaque test peut être de l’un des deux types suivants : `.sql` et `.sh`.

* Un test `.sql` est un simple script SQL envoyé à `clickhouse-client` via un pipe.
* Un test `.sh` est un script exécuté directement.

Les tests SQL sont généralement préférables aux tests `.sh`.
N’utilisez les tests `.sh` que lorsque vous devez tester une fonctionnalité qui ne peut pas l’être en SQL pur, par exemple pour envoyer des données d’entrée à `clickhouse-client` via un pipe ou pour tester `clickhouse-local`.

<Note>
  Une erreur fréquente lors des tests des types de données `DateTime` et `DateTime64` consiste à supposer que le serveur utilise un fuseau horaire spécifique (par ex. "UTC"). Ce n’est pas le cas : les fuseaux horaires utilisés dans les exécutions de tests CI
  sont délibérément choisis de manière aléatoire. La solution de contournement la plus simple consiste à spécifier explicitement le fuseau horaire des valeurs de test, par ex. `toDateTime64(val, 3, 'Europe/Amsterdam')`.
</Note>

<div id="running-a-test-locally">
  ### Exécuter un test en local
</div>

Démarrez le serveur ClickHouse en local, à l’écoute du port par défaut (9000).
Pour exécuter, par exemple, le test `01428_hash_set_nan_key`, placez-vous dans le dossier du dépôt et lancez la commande suivante :

```sh theme={null}
PATH=<path to clickhouse-client>:$PATH tests/clickhouse-test 01428_hash_set_nan_key
```

Les résultats des tests (`stderr` et `stdout`) sont enregistrés dans les fichiers `01428_hash_set_nan_key.[stderr|stdout]`, situés à côté du test correspondant (pour `queries/0_stateless/foo.sql`, la sortie se trouvera dans `queries/0_stateless/foo.stdout`).

Consultez `tests/clickhouse-test --help` pour connaître toutes les options de `clickhouse-test`.
Vous pouvez exécuter tous les tests ou un sous-ensemble de tests en fournissant un filtre sur les noms de test : `./clickhouse-test substring`.
Il existe également des options pour exécuter les tests en parallèle ou dans un ordre aléatoire.

<div id="running-fast-tests">
  ### Exécution des tests rapides
</div>

Il vous faudra peut-être une machine suffisamment puissante pour exécuter un sous-ensemble de tests (appelé "test rapide"). La configuration suivante fonctionne sur une instance Ubuntu AWS amd64 `t3.2xlarge` avec 100 Go d’espace de stockage.

1. Installez les prérequis, puis reconnectez-vous.

```sh theme={null}
sudo apt-get update
sudo apt-get install docker.io
sudo usermod -aG docker "$USER"
```

2. Récupérez le code source.

```sh theme={null}
git clone --single-branch https://github.com/ClickHouse/ClickHouse
cd ClickHouse
```

3. Compilez le code et exécutez les "tests rapides".

```sh theme={null}
python -m ci.praktika run fast
```

Vous devriez obtenir

```sh theme={null}
Failed: 0, Passed: 7394, Skipped: 1795
```

Si vous laissez l’exécution sans surveillance, vous pouvez utiliser `nohup` ou `disown` pour qu’elle continue à s’exécuter après la perte de la connexion `ssh`.

<div id="running-stateless-tests">
  ### Exécution des tests sans état
</div>

Il vous faudra peut-être une machine assez puissante pour exécuter les tests sans état. La configuration ci-dessous fonctionne sur une instance Ubuntu AWS amd64 `m7i.8xlarge` avec 200 Go de stockage.

1. Installez les prérequis, puis reconnectez-vous.

```sh theme={null}
sudo apt-get update
sudo apt-get install docker.io
sudo usermod -aG docker "$USER"
sudo tee /etc/docker/daemon.json <<'EOF'
{
  "ipv6": true,
  "ip6tables": true
}
EOF
sudo systemctl restart docker
```

2. Récupérez le code source.

```sh theme={null}
git clone --single-branch https://github.com/ClickHouse/ClickHouse
cd ClickHouse
```

3. Compilez le code.

```sh theme={null}
python -m ci.praktika run build_debug
cp ci/tmp/build/programs/clickhouse ci/tmp
```

4. Exécutez des tests sans état, qui peuvent s’exécuter en parallèle.

```sh theme={null}
python -m ci.praktika run functional
```

Vous devriez obtenir

```sh theme={null}
Failed: 0, Passed: 8497, Skipped: 103
```

Remarque : les commandes `python -m ci.praktika run` lancent un job d’intégration continue spécifique. Pour en savoir plus sur la CI de ClickHouse, consultez [cette page](/fr/resources/develop-contribute/contribute/continuous-integration#running-stateless-tests).

<div id="adding-a-new-test">
  ### Ajouter un nouveau test
</div>

Pour ajouter un nouveau test, créez d’abord un fichier `.sql` ou `.sh` dans le répertoire `queries/0_stateless`.
Générez ensuite le fichier `.reference` correspondant à l’aide de `clickhouse-client < 12345_test.sql > 12345_test.reference` ou de `./12345_test.sh > ./12345_test.reference`.

Les tests doivent uniquement créer, supprimer, interroger, etc. des tables dans la base de données `test`, qui est automatiquement créée au préalable.
Il est possible d’utiliser des tables temporaires.

Pour retrouver localement le même environnement qu’en CI, installez les configurations de test (elles utiliseront une implémentation factice de ZooKeeper et ajusteront certains paramètres)

```sh theme={null}
cd <repository>/tests/config
sudo ./install.sh
```

<Note>
  Les tests doivent être

  * minimaux : ne créer que les tables, colonnes et la complexité strictement nécessaires,
  * rapides : ne pas prendre plus de quelques secondes (mieux : moins d’une seconde),
  * corrects et déterministes : échouer si et seulement si la fonctionnalité testée ne fonctionne pas,
  * isolés/sans état : ne pas dépendre de l’environnement ni du moment de l’exécution,
  * exhaustifs : couvrir les cas limites comme les zéros, les valeurs NULL, les ensembles vides et les exceptions (tests négatifs : utilisez pour cela la syntaxe `-- { serverError xyz }` et `-- { clientError xyz }`),
  * nettoyer les tables à la fin du test (au cas où il resterait des éléments),
  * s’assurer que les autres tests ne vérifient pas la même chose (autrement dit, faites d’abord un grep).
</Note>

<div id="templated-tests-with-jinja">
  ### Tests basés sur des modèles avec Jinja
</div>

Un test `.sql` peut être écrit sous forme de modèle [Jinja2](https://jinja.palletsprojects.com/) en ajoutant le suffixe `.j2` au nom du fichier ; ainsi, `foo.sql` devient `foo.sql.j2`. Avant d’exécuter le test, `clickhouse-test` génère à partir du modèle un script `.sql` ordinaire, puis exécute le résultat.

C’est utile lorsqu’un test répète la même requête avec de légères variations : une boucle génère les requêtes à partir d’un modèle compact au lieu de les écrire une par une à la main. Les constructions les plus couramment utilisées sont :

* `{% for ... %} ... {% endfor %}` pour répéter un bloc,
* `{{ expression }}` pour insérer une valeur dans la sortie,
* `-%}` et `{%-` pour supprimer les espaces adjacents afin que le script généré reste propre.

Par exemple, ce modèle :

```sql theme={null}
{% for type in ['UInt8', 'UInt16', 'UInt32'] -%}
SELECT toTypeName(0::{{ type }});
{% endfor -%}
```

s’affiche ainsi :

```sql theme={null}
SELECT toTypeName(0::UInt8);
SELECT toTypeName(0::UInt16);
SELECT toTypeName(0::UInt32);
```

La sortie attendue peut être fournie soit sous la forme d’un simple fichier `<name>.reference` contenant les résultats après expansion complète, soit sous la forme d’un modèle `<name>.reference.j2`, que `clickhouse-test` génère de la même façon avant la comparaison. Utilisez la forme avec modèle lorsque la sortie attendue suit elle aussi un schéma répétitif. Pour plus d’exemples, consultez les fichiers `*.sql.j2` existants dans `tests/queries/0_stateless/`.

<div id="restricting-test-runs">
  ### Limiter l’exécution des tests
</div>

Un test peut avoir zéro, un ou plusieurs *tags* indiquant les restrictions sur les contextes dans lesquels il s’exécute dans la CI.

Pour les tests `.sql`, les tags sont placés sur la première ligne sous forme de commentaire SQL :

```sql theme={null}
-- Tags: no-fasttest, no-replicated-database
-- no-fasttest: <provide_a_reason_for_the_tag_here>
-- no-replicated-database: <provide_a_reason_here>

SELECT 1
```

Pour les tests `.sh`, les tags sont écrits sous forme de commentaire à la deuxième ligne :

```bash theme={null}
#!/usr/bin/env bash
# Tags: no-fasttest, no-replicated-database
# - no-fasttest: <provide_a_reason_for_the_tag_here>
# - no-replicated-database: <provide_a_reason_here>
```

Liste des tags disponibles :

| Nom du tag                     | Description                                                                                | Exemple d'utilisation                                                                                              |
| ------------------------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ |
| `disabled`                     | Le test n'est pas exécuté                                                                  |                                                                                                                    |
| `long`                         | Le temps d'exécution du test passe de 1 à 10 minutes                                       |                                                                                                                    |
| `deadlock`                     | Le test est exécuté en boucle pendant une longue période                                   |                                                                                                                    |
| `race`                         | Identique à `deadlock`. Préférez `deadlock`                                                |                                                                                                                    |
| `shard`                        | Le serveur doit écouter sur `127.0.0.*`                                                    |                                                                                                                    |
| `distributed`                  | Identique à `shard`. Préférez `shard`                                                      |                                                                                                                    |
| `global`                       | Identique à `shard`. Préférez `shard`                                                      |                                                                                                                    |
| `zookeeper`                    | Le test nécessite ZooKeeper ou ClickHouse Keeper pour s'exécuter                           | Le test utilise `ReplicatedMergeTree`                                                                              |
| `replica`                      | Identique à `zookeeper`. Préférez `zookeeper`                                              |                                                                                                                    |
| `no-fasttest`                  | Le test n'est pas exécuté dans [test rapide](#test-types)                                  | Le test utilise le moteur de table `MySQL`, qui est désactivé dans test rapide                                     |
| `fasttest-only`                | Le test est exécuté uniquement dans [test rapide](#test-types)                             |                                                                                                                    |
| `no-[asan, tsan, msan, ubsan]` | Désactive les tests dans les builds avec des [sanitizers](#sanitizers)                     | Le test est exécuté sous QEMU, qui ne fonctionne pas avec les sanitizers                                           |
| `no-replicated-database`       | Désactive le test lorsque la base de données par défaut utilise `ReplicatedDatabaseEngine` |                                                                                                                    |
| `no-ordinary-database`         | Désactive le test lorsque le moteur de base de données par défaut est `Ordinary`           |                                                                                                                    |
| `no-parallel`                  | Empêche l'exécution d'autres tests en parallèle avec celui-ci                              | Le test lit les tables `system` et les invariants peuvent être rompus                                              |
| `no-parallel-replicas`         | Désactive le test lorsque les répliques parallèles sont activées                           |                                                                                                                    |
| `no-debug`                     | Désactive les tests dans les builds Debug                                                  |                                                                                                                    |
| `no-release`                   | Désactive les tests dans les builds Release                                                |                                                                                                                    |
| `no-darwin`                    | Désactive le test sur macOS (Darwin)                                                       | Le test repose sur des fonctionnalités propres à Linux, comme les distributed queries, `procfs` ou le serveur HTTP |

Les options suivantes sont également prises en charge : `no-polymorphic-parts`, `no-random-settings`, `no-random-merge-tree-settings`, `no-backward-compatibility-check`, `no-cpu-x86_64`, `no-cpu-aarch64`, `no-cpu-ppc64le`, `no-s3-storage`.

En plus des paramètres ci-dessus, vous pouvez utiliser les flags `USE_*` de `system.build_options` pour indiquer l'utilisation de fonctionnalités ClickHouse particulières.
Par exemple, si votre test utilise une table MySQL, vous devez ajouter le tag `use-mysql`.

<div id="specifying-limits-for-random-settings">
  ### Définition des limites pour les paramètres aléatoires
</div>

Un test peut définir des valeurs minimales et maximales autorisées pour les paramètres pouvant être attribués aléatoirement pendant l’exécution du test.

Pour les tests `.sh`, les limites sont indiquées sous forme de commentaire sur la ligne à côté des tags, ou sur la deuxième ligne si aucun tag n’est spécifié :

```bash theme={null}
#!/usr/bin/env bash
# Tags: no-fasttest
# Random settings limits: max_block_size=(1000, 10000); index_granularity=(100, None)
```

Pour les tests `.sql`, les tags sont indiqués sous forme de commentaire SQL sur la ligne suivante ou sur la première ligne :

```sql theme={null}
-- Tags: no-fasttest
-- Random settings limits: max_block_size=(1000, 10000); index_granularity=(100, None)
SELECT 1
```

Si vous ne devez spécifier qu’une seule limite, vous pouvez utiliser `None` pour l’autre.

<div id="choosing-the-test-name">
  ### Choisir le nom du test
</div>

Le nom du test commence par un préfixe à cinq chiffres, suivi d'un nom descriptif, comme `00422_hash_function_constexpr.sql`.
Pour choisir le préfixe, repérez le plus grand préfixe déjà présent dans le directory, puis incrémentez-le de un.

```sh theme={null}
ls tests/queries/0_stateless/[0-9]*.reference | tail -n 1
```

Entre-temps, il est possible que d'autres tests soient ajoutés avec le même préfixe numérique, mais cela ne pose aucun problème et vous n'aurez pas à le modifier par la suite.

<div id="checking-for-an-error-that-must-occur">
  ### Vérifier qu’une erreur doit se produire
</div>

Il arrive que vous souhaitiez vérifier qu’une erreur du serveur se produit avec une requête incorrecte. Nous prenons en charge des annotations spéciales à cet effet dans les tests SQL, sous la forme suivante :

```sql theme={null}
SELECT x; -- { serverError 49 }
```

Ce test vérifie que le serveur renvoie une erreur de code 49 signalant la colonne inconnue `x`.
S'il n'y a pas d'erreur, ou si l'erreur est différente, le test échouera.
Si vous voulez vous assurer qu'une erreur se produit côté client, utilisez plutôt l'annotation `clientError`.

Ne vérifiez pas le libellé exact du message d'erreur : il peut changer à l'avenir et faire échouer le test inutilement.
Vérifiez uniquement le code d'erreur.
Si le code d'erreur existant n'est pas assez précis pour vos besoins, envisagez d'en ajouter un nouveau.

<div id="testing-a-distributed-query">
  ### Tester une requête distribuée
</div>

Si vous souhaitez utiliser des requêtes distribuées dans des tests fonctionnels, vous pouvez utiliser la fonction de table `remote` avec les adresses `127.0.0.{1..2}` pour que le serveur puisse s’interroger lui-même, ou utiliser des clusters de test prédéfinis dans le fichier de configuration du serveur, comme `test_shard_localhost`.
N’oubliez pas d’ajouter les mots `shard` ou `distributed` au nom du test, afin qu’il soit exécuté par la CI dans les configurations appropriées, où le serveur est configuré pour prendre en charge les requêtes distribuées.

<div id="working-with-temporary-files">
  ### Travailler avec les fichiers temporaires
</div>

Dans un test shell, il peut parfois être nécessaire de créer un fichier à la volée pour l'utiliser.
Gardez à l'esprit que certaines vérifications CI exécutent les tests en parallèle. Si vous créez ou supprimez un fichier temporaire dans votre script sans lui donner un nom unique, cela peut faire échouer certaines vérifications CI, comme Flaky.
Pour éviter ce problème, utilisez la variable d'environnement `$CLICKHOUSE_TEST_UNIQUE_NAME` afin de donner aux fichiers temporaires un nom unique pour le test en cours d'exécution.
Vous avez ainsi la garantie que le fichier que vous créez pendant la phase de préparation ou supprimez pendant la phase de nettoyage est uniquement utilisé par ce test, et non par un autre test exécuté en parallèle.

<div id="known-bugs">
  ## Bogues connus
</div>

Lorsque nous connaissons des bogues pouvant être facilement reproduits par des tests fonctionnels, nous plaçons des tests fonctionnels préparés dans le répertoire `tests/queries/bugs`.
Ces tests seront déplacés vers `tests/queries/0_stateless` une fois les bogues corrigés.

<div id="integration-tests">
  ## Tests d’intégration
</div>

Les tests d’intégration permettent de tester ClickHouse dans une configuration en cluster, ainsi que son interaction avec d’autres serveurs comme MySQL, Postgres ou MongoDB.
Ils sont utiles pour émuler des partitions réseau, des pertes de paquets, etc.
Ces tests sont exécutés sous Docker et créent plusieurs conteneurs exécutant différents logiciels.

Consultez `tests/integration/README.md` pour savoir comment exécuter ces tests.

Notez que l’intégration de ClickHouse avec des drivers tiers n’est pas testée.
Par ailleurs, nous ne disposons actuellement pas de tests d’intégration pour nos drivers JDBC et ODBC.

<div id="unit-tests">
  ## Tests unitaires
</div>

Les tests unitaires sont utiles lorsque vous souhaitez tester non pas ClickHouse dans son ensemble, mais une bibliothèque ou une classe isolée.
Vous pouvez activer ou désactiver la compilation des tests avec l’option CMake `ENABLE_TESTS`.
Les tests unitaires (et les autres programmes de test) se trouvent dans les sous-répertoires `tests` du code.
Pour exécuter les tests unitaires, tapez `ninja test`.
Certains tests utilisent `gtest`, mais d’autres sont simplement des programmes qui renvoient un code de sortie non nul en cas d’échec.

Il n’est pas nécessaire d’avoir des tests unitaires si le code est déjà couvert par des tests fonctionnels (et les tests fonctionnels sont généralement beaucoup plus simples à utiliser).

Vous pouvez exécuter des vérifications `gtest` individuelles en appelant directement l’exécutable, par exemple :

```bash theme={null}
$ ./src/unit_tests_dbms --gtest_filter=LocalAddress*
```

<div id="performance-tests">
  ## Tests de performance
</div>

Les tests de performance permettent de mesurer et de comparer les performances de certaines parties isolées de ClickHouse à l’aide de requêtes synthétiques.
Les tests de performance se trouvent dans `tests/performance/`.
Chaque test est représenté par un fichier `.xml` contenant une description du cas de test.
Les tests sont exécutés avec l’outil `docker/test/performance-comparison`. Consultez le fichier README pour savoir comment l’utiliser.

Chaque test exécute une ou plusieurs requêtes (éventuellement avec des combinaisons de paramètres) en boucle.

Si vous souhaitez améliorer les performances de ClickHouse dans un scénario donné, et si les améliorations peuvent être observées sur des requêtes simples, il est fortement recommandé d’écrire un test de performance.
Il est également recommandé d’écrire des tests de performance lorsque vous ajoutez ou modifiez des fonctions SQL relativement isolées et peu obscures.
Il est toujours judicieux d’utiliser `perf top` ou d’autres outils `perf` pendant vos tests.

<div id="test-tools-and-scripts">
  ## Outils et scripts de test
</div>

Certains programmes du répertoire `tests` ne sont pas des tests à proprement parler, mais des outils de test.
Par exemple, pour `Lexer`, il existe un outil `src/Parsers/tests/lexer` qui se contente d'effectuer la tokenisation de stdin et d'écrire le résultat en couleur sur stdout.
Vous pouvez utiliser ce type d'outils comme exemples de code, ainsi que pour l'exploration et les tests manuels.

<div id="miscellaneous-tests">
  ## Tests divers
</div>

Il existe des tests pour les modèles d’apprentissage automatique dans `tests/external_models`.
Ces tests ne sont plus mis à jour et doivent être portés dans les tests d’intégration.

Il existe un test distinct pour les insertions avec quorum.
Ce test exécute un cluster ClickHouse sur des serveurs distincts et émule divers cas de défaillance : partition réseau, perte de paquets (entre les nœuds ClickHouse, entre ClickHouse et ZooKeeper, entre le serveur ClickHouse et le client, etc.), `kill -9`, `kill -STOP` et `kill -CONT`, comme [Jepsen](https://aphyr.com/tags/Jepsen). Ensuite, le test vérifie que toutes les insertions validées ont bien été écrites et qu’aucune des insertions rejetées ne l’a été.

<div id="manual-testing">
  ## Tests manuels
</div>

Lorsque vous développez une nouvelle fonctionnalité, il est également logique de la tester manuellement.
Vous pouvez procéder comme suit :

Compilez ClickHouse. Exécutez ClickHouse depuis le terminal : placez-vous dans le répertoire `programs/clickhouse-server` et lancez-le avec `./clickhouse-server`. Par défaut, il utilisera la configuration (`config.xml`, `users.xml` et les fichiers contenus dans les répertoires `config.d` et `users.d`) du répertoire courant. Pour vous connecter au serveur ClickHouse, exécutez `programs/clickhouse-client/clickhouse-client`.

Notez que tous les outils ClickHouse (serveur, client, etc.) ne sont en réalité que des liens symboliques vers un unique binaire nommé `clickhouse`.
Vous trouverez ce binaire dans `programs/clickhouse`.
Tous les outils peuvent également être appelés sous la forme `clickhouse tool` au lieu de `clickhouse-tool`.

Vous pouvez également installer le paquet ClickHouse : soit la release stable depuis le dépôt ClickHouse, soit compiler vous-même le paquet avec `./release` à la racine des sources ClickHouse.
Démarrez ensuite le serveur avec `sudo clickhouse start` (ou `stop` pour arrêter le serveur).
Consultez les logs dans `/etc/clickhouse-server/clickhouse-server.log`.

Si ClickHouse est déjà installé sur votre système, vous pouvez compiler un nouveau binaire `clickhouse` et remplacer le binaire existant :

```bash theme={null}
$ sudo clickhouse stop
$ sudo cp ./clickhouse /usr/bin/
$ sudo clickhouse start
```

Vous pouvez aussi arrêter le service système clickhouse-server et lancer votre propre instance avec la même configuration, mais avec les logs dans le terminal :

```bash theme={null}
$ sudo clickhouse stop
$ sudo -u clickhouse /usr/bin/clickhouse server --config-file /etc/clickhouse-server/config.xml
```

Exemple avec gdb :

```bash theme={null}
$ sudo -u clickhouse gdb --args /usr/bin/clickhouse server --config-file /etc/clickhouse-server/config.xml
```

Si le service `clickhouse-server` est déjà en cours d’exécution et que vous ne souhaitez pas l’arrêter, vous pouvez modifier les numéros de port dans votre `config.xml` (ou les surcharger dans un fichier du répertoire `config.d`), indiquer un chemin de données approprié, puis le lancer.

Le binaire `clickhouse` n’a pratiquement aucune dépendance et fonctionne sur un large éventail de distributions Linux.
Pour tester rapidement vos modifications sur un serveur de manière un peu sommaire, vous pouvez simplement copier votre binaire `clickhouse` fraîchement compilé sur votre serveur avec `scp`, puis l’exécuter comme dans les exemples ci-dessus.

<div id="build-tests">
  ## Tests de build
</div>

Les tests de build permettent de vérifier que le build n'est pas défectueux sur diverses configurations alternatives et sur certains autres systèmes.
Ces tests sont également automatisés.

Exemples :

* compilation croisée pour Darwin x86\_64 (macOS)
* compilation croisée pour FreeBSD x86\_64
* compilation croisée pour Linux AArch64
* build sur Ubuntu avec des bibliothèques issues des paquets système (déconseillé)
* build avec liaison dynamique des bibliothèques (déconseillé)

Par exemple, un build avec des paquets système est une mauvaise pratique, car nous ne pouvons pas garantir la version exacte des paquets présents sur un système.
Mais c'est réellement nécessaire pour les mainteneurs Debian.
Pour cette raison, nous devons au moins prendre en charge cette variante de build.
Autre exemple : la liaison dynamique est une source fréquente de problèmes, mais elle est nécessaire pour certains passionnés.

Même si nous ne pouvons pas exécuter tous les tests sur toutes les variantes de build, nous voulons au moins vérifier que les différentes variantes de build ne sont pas défectueuses.
C'est à cela que servent les tests de build.

Nous vérifions également qu'il n'existe pas d'unités de traduction trop longues à compiler ou nécessitant trop de RAM.

Nous vérifions également qu'il n'existe pas de frames de pile trop volumineuses.

<div id="testing-for-protocol-compatibility">
  ## Tester la compatibilité du protocole
</div>

Lorsque nous faisons évoluer le protocole réseau de ClickHouse, nous vérifions manuellement que l’ancien clickhouse-client fonctionne avec le nouveau clickhouse-server et que le nouveau clickhouse-client fonctionne avec l’ancien clickhouse-server (simplement en exécutant les binaires des paquets correspondants).

Nous testons également automatiquement certains cas à l’aide de tests d’intégration :

* si les données écrites par une ancienne version de ClickHouse peuvent être lues correctement par la nouvelle version ;
* si les requêtes distribuées fonctionnent dans un cluster utilisant différentes versions de ClickHouse.

<div id="help-from-the-compiler">
  ## Aide du compilateur
</div>

Le code principal de ClickHouse (situé dans le répertoire `src`) est compilé avec `-Wall -Wextra -Werror`, ainsi qu’avec quelques avertissements supplémentaires activés.
En revanche, ces options ne sont pas activées pour les bibliothèques tierces.

Clang propose encore davantage d’avertissements utiles : vous pouvez les passer en revue avec `-Weverything` et en retenir certains pour la compilation par défaut.

Nous utilisons toujours clang pour compiler ClickHouse, aussi bien en développement qu’en production.
Vous pouvez compiler sur votre propre machine en mode debug (pour économiser la batterie de votre ordinateur portable), mais notez que le compilateur peut générer davantage d’avertissements avec `-O3` grâce à une meilleure analyse du flux de contrôle et à l’analyse interprocédurale.
Lors d’une compilation avec clang en mode debug, la version debug de `libc++` est utilisée, ce qui permet de détecter davantage d’erreurs à l’exécution.

<div id="sanitizers">
  ## Sanitizers
</div>

<Note>
  Si le processus (serveur ClickHouse ou client) plante au démarrage lors d’une exécution en local, vous devrez peut-être désactiver la randomisation de l’espace d’adressage : `sudo sysctl kernel.randomize_va_space=0`
</Note>

<div id="address-sanitizer">
  ### Sanitizer d’adresses
</div>

Nous exécutons des tests fonctionnels, d’intégration, de stress et unitaires avec ASan à chaque commit.

<div id="thread-sanitizer">
  ### Thread sanitizer
</div>

Nous exécutons des tests fonctionnels, d’intégration, de stress et unitaires avec TSan à chaque commit.

<div id="memory-sanitizer">
  ### Sanitizer mémoire
</div>

Nous exécutons des tests fonctionnels, d’intégration, de stress et unitaires avec MSan à chaque commit.

<div id="undefined-behaviour-sanitizer">
  ### Sanitizer pour comportements indéfinis
</div>

Nous exécutons, à chaque commit, les tests fonctionnels, d’intégration, de stress et unitaires avec UBSan.
Le code de certaines bibliothèques tierces n’est pas instrumenté pour détecter les comportements indéfinis.

<div id="valgrind-memcheck">
  ### Valgrind (memcheck)
</div>

Nous exécutions autrefois les tests fonctionnels sous Valgrind pendant la nuit, mais ce n’est plus le cas.
Cela prend plusieurs heures.
Actuellement, il existe un faux positif connu dans la bibliothèque `re2`, voir [cet article](https://research.swtch.com/sparse).

<div id="fuzzing">
  ## Fuzzing
</div>

Le fuzzing de ClickHouse est mis en œuvre à la fois avec [libFuzzer](https://llvm.org/docs/LibFuzzer.html) et des requêtes SQL aléatoires.
Tous les tests de fuzzing doivent être effectués avec des sanitizers (Address et Undefined).

LibFuzzer est utilisé pour tester de manière isolée le code des bibliothèques.
Les fuzzers sont implémentés dans le code de test et portent le suffixe "\_fuzzer".
Vous trouverez un exemple de fuzzer dans `src/Parsers/fuzzers/lexer_fuzzer.cpp`.
Les configurations, dictionnaires et corpus spécifiques à LibFuzzer sont stockés dans `tests/fuzz`.
Nous vous encourageons à écrire des tests de fuzzing pour chaque fonctionnalité qui traite des entrées utilisateur.

Les fuzzers ne sont pas compilés par défaut.
Pour compiler les fuzzers, les options `-DENABLE_FUZZING=1` et `-DENABLE_TESTS=1` doivent toutes deux être définies.
Nous recommandons de désactiver Jemalloc lors de la compilation des fuzzers.
La configuration utilisée pour intégrer le fuzzing de ClickHouse à
Google OSS-Fuzz se trouve dans `docker/fuzz`.

Nous utilisons également un test de fuzzing simple pour générer des requêtes SQL aléatoires et vérifier que le serveur ne s’arrête pas pendant leur exécution.
Vous pouvez le trouver dans `00746_sql_fuzzy.pl`.
Ce test doit être exécuté en continu (pendant la nuit et au-delà).

Nous utilisons également un fuzzer de requêtes sophistiqué basé sur l’AST, capable de trouver un très grand nombre de cas limites.
Il effectue des permutations et des substitutions aléatoires dans l’AST des requêtes.
Il mémorise les nœuds AST des tests précédents pour les réutiliser dans le fuzzing des tests suivants, qu’il traite dans un ordre aléatoire.
Vous pouvez en apprendre davantage sur ce fuzzer dans [cet article de blog](https://clickhouse.com/blog/fuzzing-click-house).

<div id="stress-test">
  ## Test de stress
</div>

Les tests de stress constituent une autre forme de fuzzing.
Ils exécutent tous les tests fonctionnels en parallèle, dans un ordre aléatoire, sur un seul serveur.
Les résultats des tests ne sont pas vérifiés.

Les points suivants sont vérifiés :

* le serveur ne plante pas et aucun piège de débogage ou de sanitizer ne se déclenche ;
* il n'y a pas d'interblocages ;
* la structure de la base de données est cohérente ;
* le serveur peut s'arrêter correctement après le test puis redémarrer sans exception.

Il existe cinq variantes (Débogage, ASan, TSan, MSan, UBSan).

<div id="thread-fuzzer">
  ## Thread fuzzer
</div>

Le Thread Fuzzer (à ne pas confondre avec le Thread Sanitizer) est un autre type de fuzzing qui permet de rendre aléatoire l'ordre d'exécution des threads.
Il aide à détecter encore plus de cas particuliers.

<div id="security-audit">
  ## Audit de sécurité
</div>

Notre équipe de sécurité a effectué un examen sommaire des fonctionnalités de ClickHouse sous l’angle de la sécurité.

<div id="static-analyzers">
  ## Analyseurs statiques
</div>

Nous exécutons `clang-tidy` à chaque commit.
Les vérifications `clang-static-analyzer` sont également activées.
`clang-tidy` est aussi utilisé pour certaines vérifications de style.

Nous avons évalué `clang-tidy`, `Coverity`, `cppcheck`, `PVS-Studio`, `tscancode`, `CodeQL`.
Vous trouverez les instructions d’utilisation dans le répertoire `tests/instructions/`.

Si vous utilisez `CLion` comme IDE, vous pouvez profiter immédiatement de certaines vérifications `clang-tidy`.

Nous utilisons également `shellcheck` pour l’analyse statique des scripts shell.

<div id="hardening">
  ## Durcissement
</div>

Dans la compilation de débogage, nous utilisons un allocator personnalisé qui applique l’ASLR aux allocations au niveau utilisateur.

Nous protégeons également manuellement les régions mémoire qui sont censées être en lecture seule après l’allocation.

Dans la compilation de débogage, nous utilisons également une personnalisation de libc qui garantit qu’aucune fonction « nocive » (Obsolete, non sécurisée, non thread-safe) n’est appelée.

Les assertions de débogage sont largement utilisées.

Dans la compilation de débogage, si une exception avec le code « logical error » (ce qui indique un bug) est levée, le programme est arrêté prématurément.
Cela permet d’utiliser des exceptions dans la compilation de release, tout en les transformant en assertions dans la compilation de débogage.

La version de débogage de jemalloc est utilisée pour les compilations de débogage.
La version de débogage de libc++ est utilisée pour les compilations de débogage.

<div id="runtime-integrity-checks">
  ## Contrôles d’intégrité à l’exécution
</div>

Les données stockées sur disque font l’objet de sommes de contrôle.
Les données des tables MergeTree sont protégées simultanément par des sommes de contrôle de trois façons\* (blocs de données compressés, blocs de données non compressés, somme de contrôle globale sur l’ensemble des blocs).
Les données transférées sur le réseau entre le client et le serveur, ou entre serveurs, font également l’objet de sommes de contrôle.
La réplication garantit des données identiques bit à bit sur les répliques.

Cela est nécessaire pour se prémunir contre les défaillances matérielles (altération de bits sur les supports de stockage, inversions de bits dans la RAM du serveur, inversions de bits dans la RAM du contrôleur réseau, inversions de bits dans la RAM du commutateur réseau, inversions de bits dans la RAM du client, inversions de bits sur le réseau).
Notez que les inversions de bits sont fréquentes et susceptibles de se produire même avec de la RAM ECC et en présence de sommes de contrôle TCP (si vous exploitez des milliers de serveurs traitant chaque jour des pétaoctets de données).
[Voir la vidéo (russe)](https://www.youtube.com/watch?v=ooBAQIe0KlQ).

ClickHouse fournit des outils de diagnostic qui aideront les ingénieurs d’exploitation à détecter les défaillances matérielles.

* et ce n’est pas lent.

<div id="code-style">
  ## Style de code
</div>

Les règles de style de code sont décrites [ici](/fr/resources/develop-contribute/contribute/style).

Pour détecter certaines violations courantes des règles de style, vous pouvez utiliser le script `utils/check-style`.

Pour imposer un style correct à votre code, vous pouvez utiliser `clang-format`.
Le fichier `.clang-format` se trouve à la racine du code source.
Il correspond en grande partie à notre style de code actuel.
Mais il n'est pas recommandé d'appliquer `clang-format` à des fichiers existants, car cela dégrade le formatage.
Vous pouvez utiliser l'outil `clang-format-diff`, que vous trouverez dans le dépôt source de clang.

Vous pouvez aussi essayer l'outil `uncrustify` pour reformater votre code.
Le fichier de configuration `uncrustify.cfg` se trouve à la racine du code source.
Il est moins éprouvé que `clang-format`.

`CLion` possède son propre formateur de code, qui doit être ajusté à notre style de code.

<div id="test-coverage">
  ## Couverture des tests
</div>

Nous suivons également la couverture des tests, mais uniquement pour les tests fonctionnels et seulement pour clickhouse-server.
Elle est mesurée quotidiennement.

<div id="tests-for-tests">
  ## Tests des tests
</div>

Il existe une vérification automatisée pour détecter les tests instables.
Elle exécute tous les nouveaux tests 100 fois (pour les tests fonctionnels) ou 10 fois (pour les tests d'intégration).
Si un test échoue ne serait-ce qu'une seule fois, il est considéré comme instable.

<div id="test-automation">
  ## Automatisation des tests
</div>

Nous exécutons les tests avec [GitHub Actions](https://github.com/features/actions).

Les tâches de build et les tests sont exécutés dans Sandbox à chaque commit.
Les paquets générés et les résultats des tests sont publiés sur GitHub et peuvent être téléchargés via des liens directs.
Les artefacts sont conservés pendant plusieurs mois.
Lorsque vous envoyez une pull request sur GitHub, nous lui attribuons l’étiquette "can be tested" et notre système de CI construira pour vous des paquets ClickHouse (release, debug, avec address sanitizer, etc.).
