Tipos de pruebas
- Pruebas funcionales: un conjunto de consultas y scripts que incluye los siguientes subconjuntos superpuestos
- Fast test: el subconjunto mínimo
- Pruebas sin estado, que no requieren cargar datos en las bases de datos
- Pruebas secuenciales, que no pueden ejecutarse en paralelo
- Pruebas de integración, ejecutadas por
pytesten un clúster - Pruebas unitarias
- Pruebas de rendimiento
- Pruebas de compilación
- Sanitizers
- Fuzzers y algunas otras; consulta las secciones siguientes.
Pruebas funcionales
./tests/queries.
Cada prueba puede ser de uno de estos dos tipos: .sql y .sh.
- Una prueba
.sqles un script SQL sencillo que se envía por canalización aclickhouse-client. - Una prueba
.shes un script que se ejecuta por sí solo.
.sh.
Debe usar pruebas .sh solo cuando necesite probar alguna funcionalidad que no pueda ejercerse con SQL puro, como canalizar datos de entrada a clickhouse-client o probar clickhouse-local.
Un error común al probar los tipos de datos
DateTime y DateTime64 es asumir que el servidor usa una zona horaria específica (por ejemplo, “UTC”). No es así: las zonas horarias en las ejecuciones de pruebas de CI
se aleatorizan deliberadamente. La solución alternativa más sencilla es especificar explícitamente la zona horaria de los valores de prueba; por ejemplo, toDateTime64(val, 3, 'Europe/Amsterdam').Ejecutar una prueba localmente
01428_hash_set_nan_key, vaya a la carpeta del repositorio y ejecute el siguiente comando:
stderr y stdout) se escriben en los archivos 01428_hash_set_nan_key.[stderr|stdout], ubicados junto a la propia prueba (para queries/0_stateless/foo.sql, la salida estará en queries/0_stateless/foo.stdout).
Consulta tests/clickhouse-test --help para ver todas las opciones de clickhouse-test.
Puedes ejecutar todas las pruebas o solo un subconjunto indicando un filtro para los nombres de las pruebas: ./clickhouse-test substring.
También hay opciones para ejecutar las pruebas en paralelo o en orden aleatorio.
Ejecutar Fast test
t3.2xlarge amd64 con Ubuntu y 100 GB de almacenamiento.
- Instale los requisitos previos y vuelva a iniciar sesión.
- Obtenga el código fuente.
- Compila el código y ejecuta las “fast tests”.
nohup o disown para que siga ejecutándose después de que se pierda la conexión ssh.
Ejecutar pruebas sin estado
m7i.8xlarge con Ubuntu amd64 y 200 GB de almacenamiento.
- Instale los prerrequisitos y vuelva a iniciar sesión.
- Descarga el código fuente.
- Compila el código.
- Ejecute las pruebas sin estado, que pueden ejecutarse en paralelo.
python -m ci.praktika run ejecutan una tarea específica de integración continua; puedes obtener más información sobre ClickHouse CI aquí.
Añadir una nueva prueba
.sql o .sh en el directorio queries/0_stateless.
Después, genera el archivo .reference correspondiente con clickhouse-client < 12345_test.sql > 12345_test.reference o ./12345_test.sh > ./12345_test.reference.
Las pruebas solo deben crear, eliminar, consultar, etc., tablas en la base de datos test, que se crea automáticamente de antemano.
Se permite usar tablas temporales.
Para configurar localmente el mismo entorno que en CI, instala las configuraciones de prueba (usarán una implementación simulada de ZooKeeper y ajustarán algunos parámetros de configuración)
Las pruebas deberían ser
- mínimas: crear solo las tablas y columnas imprescindibles, con la mínima complejidad posible,
- rápidas: no tardar más de unos pocos segundos (mejor aún: menos de un segundo),
- correctas y deterministas: fallar si y solo si la funcionalidad en prueba no funciona,
- aisladas/sin estado: no depender del entorno ni del momento de ejecución
- exhaustivas: cubrir casos límite como ceros, nulos, conjuntos vacíos y excepciones (pruebas negativas; para ello, use la sintaxis
-- { serverError xyz }y-- { clientError xyz }), - limpiar las tablas al final de la prueba (por si quedan restos),
- asegurarse de que otras pruebas no estén comprobando lo mismo (es decir, use primero grep).
Restringir la ejecución de pruebas
.sql, las etiquetas se colocan en la primera línea como un comentario SQL:
.sh, las etiquetas se escriben como comentario en la segunda línea:
| Nombre de la etiqueta | Qué hace | Ejemplo de uso |
|---|---|---|
disabled | La prueba no se ejecuta | |
long | El tiempo de ejecución de la prueba se extiende de 1 a 10 minutos | |
deadlock | La prueba se ejecuta en un bucle durante mucho tiempo | |
race | Igual que deadlock. Se prefiere deadlock | |
shard | Es necesario que el servidor escuche en 127.0.0.* | |
distributed | Igual que shard. Se prefiere shard | |
global | Igual que shard. Se prefiere shard | |
zookeeper | La prueba requiere Zookeeper o ClickHouse Keeper para ejecutarse | La prueba usa ReplicatedMergeTree |
replica | Igual que zookeeper. Se prefiere zookeeper | |
no-fasttest | La prueba no se ejecuta en Fast test | La prueba usa el table engine MySQL, que está deshabilitado en Fast test |
fasttest-only | La prueba solo se ejecuta en Fast test | |
no-[asan, tsan, msan, ubsan] | Deshabilita las pruebas en compilaciones con sanitizers | La prueba se ejecuta en QEMU, que no funciona con sanitizers |
no-replicated-database | Deshabilita la prueba cuando la base de datos predeterminada usa ReplicatedDatabaseEngine | |
no-ordinary-database | Deshabilita la prueba cuando el database engine predeterminado es Ordinary | |
no-parallel | Deshabilita la ejecución en paralelo de otras pruebas con esta | La prueba lee de tablas system y los invariantes pueden romperse |
no-parallel-replicas | Deshabilita la prueba cuando las réplicas paralelas están habilitadas | |
no-debug | Deshabilita las pruebas en compilaciones Debug | |
no-release | Deshabilita las pruebas en compilaciones Release | |
no-darwin | Deshabilita la prueba en macOS (Darwin) | La prueba depende de características específicas de Linux, como consultas distribuidas, procfs o el servidor HTTP |
no-stress, 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.
Además de los ajustes anteriores, puede usar flags USE_* de system.build_options para definir el uso de características concretas de ClickHouse.
Por ejemplo, si su prueba usa una tabla MySQL, debe añadir la etiqueta use-mysql.
Especificación de límites para valores aleatorios de configuración
.sh, los límites se escriben como un comentario en la línea siguiente a las etiquetas o en la segunda línea si no se especifican etiquetas:
.sql, las etiquetas se colocan como comentario SQL en la línea siguiente a las etiquetas o en la primera línea:
None para el otro.
Elección del nombre de la prueba
00422_hash_function_constexpr.sql.
Para elegir el prefijo, busque el prefijo más alto que ya esté presente en el directorio e increméntelo en uno.
Comprobación de un error esperado
x.
Si no se produce ningún error, o si el error es distinto, la prueba fallará.
Si quiere asegurarse de que el error se produzca en el lado del cliente, use la anotación clientError en su lugar.
No compruebe una redacción concreta del mensaje de error; puede cambiar en el futuro y hacer que la prueba falle innecesariamente.
Compruebe solo el código de error.
Si el código de error existente no es lo bastante preciso para sus necesidades, considere añadir uno nuevo.
Prueba de una consulta distribuida
remote con direcciones 127.0.0.{1..2} para que el servidor se consulte a sí mismo; o bien usar clústeres de prueba predefinidos en el archivo de configuración del servidor, como test_shard_localhost.
Recuerda añadir las palabras shard o distributed al nombre de la prueba para que se ejecute en CI con la configuración correcta, donde el servidor está preparado para admitir consultas distribuidas.
Trabajo con archivos temporales
$CLICKHOUSE_TEST_UNIQUE_NAME para dar a los archivos temporales un nombre único para la prueba que se está ejecutando.
Así puedes asegurarte de que el archivo que creas durante la configuración o eliminas durante la limpieza es el que usa únicamente esa prueba, y no otra que se esté ejecutando en paralelo.
Errores conocidos
tests/queries/bugs.
Estas pruebas se trasladarán a tests/queries/0_stateless cuando se corrijan los errores.
Pruebas de integración
tests/integration/README.md para ver cómo ejecutar estas pruebas.
Tenga en cuenta que no se prueba la integración de ClickHouse con drivers de terceros.
Además, actualmente no tenemos pruebas de integración con nuestros drivers JDBC y ODBC.
Pruebas unitarias
ENABLE_TESTS.
Las pruebas unitarias (y otros programas de prueba) se encuentran en los subdirectorios tests repartidos por el código.
Para ejecutar las pruebas unitarias, escribe ninja test.
Algunas pruebas usan gtest, pero otras son simplemente programas que devuelven un código de salida distinto de cero cuando la prueba falla.
No es necesario tener pruebas unitarias si el código ya está cubierto por pruebas funcionales (y las pruebas funcionales suelen ser mucho más sencillas de usar).
Puedes ejecutar comprobaciones individuales de gtest llamando directamente al ejecutable, por ejemplo:
Pruebas de rendimiento
tests/performance/.
Cada prueba está representada por un archivo .xml con una descripción del caso de prueba.
Las pruebas se ejecutan con la herramienta docker/test/performance-comparison. Consulte el archivo readme para ver cómo invocarla.
Cada prueba ejecuta una o varias consultas (posiblemente con combinaciones de parámetros) en un bucle.
Si desea mejorar el rendimiento de ClickHouse en algún escenario, y las mejoras pueden observarse con consultas simples, es muy recomendable escribir una prueba de rendimiento.
Además, se recomienda escribir pruebas de rendimiento al añadir o modificar funciones SQL que estén relativamente aisladas y no sean demasiado complejas.
Siempre tiene sentido usar perf top u otras herramientas de perf durante las pruebas.
Herramientas y scripts de prueba
tests no son pruebas ya preparadas, sino herramientas de prueba.
Por ejemplo, para Lexer hay una herramienta, src/Parsers/tests/lexer, que simplemente realiza la tokenización de stdin y escribe el resultado coloreado en stdout.
Puede usar este tipo de herramientas como ejemplos de código, así como para exploración y pruebas manuales.
Pruebas diversas
tests/external_models.
Estas pruebas no se mantienen y deben trasladarse a las pruebas de integración.
Hay una prueba independiente para inserciones con quórum.
Esta prueba ejecuta un clúster de ClickHouse en servidores independientes y emula varios casos de fallo: partición de red, pérdida de paquetes (entre nodos de ClickHouse, entre ClickHouse y ZooKeeper, entre el servidor de ClickHouse y el cliente, etc.), kill -9, kill -STOP y kill -CONT, como Jepsen. Después, la prueba comprueba que todas las inserciones confirmadas se hayan escrito y que ninguna de las inserciones rechazadas se haya escrito.
Pruebas manuales
programs/clickhouse-server y ejecútalo con ./clickhouse-server. De forma predeterminada, usará la configuración (config.xml, users.xml y los archivos dentro de los directorios config.d y users.d) del directorio actual. Para conectarte al servidor de ClickHouse, ejecuta programs/clickhouse-client/clickhouse-client.
Ten en cuenta que todas las herramientas de clickhouse (server, client, etc.) son solo enlaces simbólicos a un único binario llamado clickhouse.
Puedes encontrar este binario en programs/clickhouse.
Todas las herramientas también pueden invocarse como clickhouse tool en lugar de clickhouse-tool.
Como alternativa, puedes instalar el paquete de ClickHouse: ya sea la versión estable del repositorio de ClickHouse, o bien puedes compilar el paquete tú mismo con ./release en la raíz del código fuente de ClickHouse.
Luego inicia el servidor con sudo clickhouse start (o stop para detener el servidor).
Busca los logs en /etc/clickhouse-server/clickhouse-server.log.
Cuando ClickHouse ya esté instalado en tu sistema, puedes compilar un nuevo binario clickhouse y reemplazar el binario existente:
clickhouse-server del sistema ya está en ejecución y no desea detenerlo, puede cambiar los números de puerto en su config.xml (o redefinirlos en un archivo del directorio config.d), especificar una ruta de datos adecuada y ejecutarlo.
El binario clickhouse casi no tiene dependencias y funciona en una amplia variedad de distribuciones de Linux.
Para probar rápidamente sus cambios en un servidor, puede simplemente copiar con scp el binario clickhouse recién compilado a su servidor y luego ejecutarlo como en los ejemplos anteriores.
Pruebas de compilación
- compilación cruzada para Darwin x86_64 (macOS)
- compilación cruzada para FreeBSD x86_64
- compilación cruzada para Linux AArch64
- compilación en Ubuntu con bibliotecas de los paquetes del sistema (desaconsejado)
- compilación con enlazado compartido de bibliotecas (desaconsejado)
Pruebas de compatibilidad del protocolo
- si los datos escritos por una versión anterior de ClickHouse pueden leerse correctamente con la versión nueva;
- si las consultas distribuidas funcionan en un clúster con distintas versiones de ClickHouse.
Ayuda del compilador
src) se compila con -Wall -Wextra -Werror y con algunas advertencias adicionales habilitadas.
Sin embargo, estas opciones no están habilitadas para bibliotecas de terceros.
Clang tiene aún más advertencias útiles; puedes buscarlas con -Weverything y elegir alguna para incluirla en la compilación predeterminada.
Siempre usamos clang para compilar ClickHouse, tanto en desarrollo como en producción.
Puedes compilar en tu propia máquina en modo de depuración (para ahorrar batería de tu portátil), pero ten en cuenta que el compilador puede generar más advertencias con -O3 gracias a un mejor análisis del flujo de control y entre procedimientos.
Al compilar con clang en modo de depuración, se usa la versión de depuración de libc++, lo que permite detectar más errores en tiempo de ejecución.
Sanitizers
Si el proceso (ClickHouse server o cliente) se bloquea al iniciarse al ejecutarlo en local, es posible que tengas que deshabilitar la aleatorización del espacio de direcciones:
sudo sysctl kernel.randomize_va_space=0Sanitizador de direcciones
Sanitizador de hilos
Sanitizador de memoria
Sanitizador de comportamiento indefinido
Valgrind (memcheck)
re2; consulta este artículo.
Fuzzing
src/Parsers/fuzzers/lexer_fuzzer.cpp.
Las configuraciones, diccionarios y corpus específicos de LibFuzzer se almacenan en tests/fuzz.
Le animamos a escribir pruebas de fuzzing para cualquier funcionalidad que procese entradas de usuario.
Los fuzzers no se compilan de forma predeterminada.
Para compilar los fuzzers, deben establecerse las opciones -DENABLE_FUZZING=1 y -DENABLE_TESTS=1.
Recomendamos deshabilitar Jemalloc al compilar fuzzers.
La configuración utilizada para integrar el fuzzing de ClickHouse con
Google OSS-Fuzz puede encontrarse en docker/fuzz.
También usamos una prueba de fuzzing sencilla para generar consultas SQL aleatorias y comprobar que el server no se cae al ejecutarlas.
Puede encontrarla en 00746_sql_fuzzy.pl.
Esta prueba debe ejecutarse de forma continua (durante la noche y más tiempo).
También usamos un sofisticado fuzzer de consultas basado en AST, capaz de encontrar una gran cantidad de casos límite.
Realiza permutaciones y sustituciones aleatorias en el AST de las consultas.
Recuerda nodos del AST de pruebas anteriores para utilizarlos en el fuzzing de pruebas posteriores, mientras las procesa en orden aleatorio.
Puede obtener más información sobre este fuzzer en este artículo del blog.
Prueba de estrés
- el servidor no se bloquea y que no se activan traps de depuración ni del sanitizer;
- no hay interbloqueos;
- la estructura de la base de datos es coherente;
- el servidor puede detenerse correctamente después de la prueba y volver a iniciarse sin excepciones.
Thread fuzzer
Auditoría de seguridad
Analizadores estáticos
clang-tidy en cada commit.
Las comprobaciones de clang-static-analyzer también están habilitadas.
clang-tidy también se utiliza para algunas comprobaciones de estilo.
Hemos evaluado clang-tidy, Coverity, cppcheck, PVS-Studio, tscancode, CodeQL.
Encontrará instrucciones de uso en el directorio tests/instructions/.
Si usa CLion como IDE, puede aprovechar algunas comprobaciones de clang-tidy desde el primer momento.
También usamos shellcheck para el análisis estático de scripts de shell.
Endurecimiento
Comprobaciones de integridad en tiempo de ejecución
- y no es lento.
Estilo de código
utils/check-style.
Para imponer el estilo correcto en su código, puede usar clang-format.
El archivo .clang-format se encuentra en la raíz del código fuente.
En su mayor parte, se ajusta a nuestro estilo de código actual.
Pero no se recomienda aplicar clang-format a archivos existentes porque empeora el formato.
Puede usar la herramienta clang-format-diff, que puede encontrar en el repositorio de código fuente de clang.
Como alternativa, puede probar la herramienta uncrustify para reformatear su código.
La configuración está en uncrustify.cfg, en la raíz del código fuente.
Se ha probado menos que clang-format.
CLion tiene su propio formateador de código, que debe ajustarse a nuestro estilo de código.
También usamos codespell para detectar errores tipográficos en el código.
Esto también está automatizado.