Skip to main content
Algumas extensões precisam se comunicar com um servidor HTTP externo ou outro listener de rede durante os testes (por exemplo, uma extensão que faz requisições HTTP de saída precisa de um servidor de echo local para recebê-las). Esta página aborda como estruturar esses testes para que sejam executados de forma confiável sob --parallel=auto e em diferentes sistemas operacionais. Os padrões apresentados aqui se aplicam igualmente a extensões em C++ e Rust, pois ambos usam o MTR como executor de testes por meio de cargo vsql test.

Por que portas fixas falham

Dois modos de falha tornam as portas fixas não confiáveis no MTR: Conflitos de porta sob --parallel. O MTR atribui a cada worker uma faixa de portas em torno do seu valor @@port. Uma porta fixa fora dessa faixa (digamos, 18777) pode colidir com o bloco reservado de outro worker ou com um serviço do sistema, o que causa EADDRINUSE intermitente que só se reproduz em alto paralelismo. Mudanças no nível do sistema operacional. Novas imagens de runner e versões de sistema operacional periodicamente reservam ou restringem portas que antes funcionavam. Uma porta que passa localmente e no CI hoje pode falhar silenciosamente ao vincular amanhã. A solução em ambos os casos é a mesma: vincule à porta 0 e deixe o sistema operacional atribuir uma porta disponível, depois comunique a porta real de volta ao teste.

Padrão A: Listener integrado ao servidor

Use este quando o listener de rede é executado dentro do processo do MySQL (por exemplo, uma extensão que incorpora um servidor HTTP). Na extensão, exponha a porta vinculada como uma variável de status após a vinculação:
No teste, use o wait_condition.inc do MTR para consultar a variável de status até que ela seja diferente de zero, depois capture a porta em uma variável do MTR. Releia após qualquer ciclo de UNINSTALL EXTENSION / INSTALL EXTENSION, pois uma porta efêmera muda a cada vinculação.

Padrão B: Listener em processo externo

Use este quando o listener é um processo independente — um servidor auxiliar em Python, uma API simulada ou qualquer programa externo que o MTR não controle diretamente.
Este padrão requer python3 no PATH. Os runners hospedados pelo GitHub o incluem; verifique a disponibilidade em runners auto-hospedados antes de usar.

O lançador em primeiro plano

Em vez de colocar o servidor em segundo plano com --exec ... & e consultar uma porta, use um script de lançamento em primeiro plano que:
  1. Inicia o servidor em um subprocesso com start_new_session=True
  2. Bloqueia até que o servidor tenha vinculado e escrito um arquivo de prontidão
  3. Encerra, permitindo que o MTR continue
O MTR bloqueia em chamadas --exec em primeiro plano, então isso garante que o servidor esteja pronto antes que qualquer SQL seja executado, sem a necessidade de um poller ou sleep separado. launcher.py — escreva isto com --write_file:
echo_server.py — o servidor em si, escrevendo sua porta antes de atender:

No teste

Inicie o lançador (em primeiro plano, já que o MTR bloqueia até que ele encerre), depois inclua o arquivo de porta:

Mantendo a porta fora do arquivo de resultado

O arquivo de resultado registra o SQL conforme escrito. Se uma URL contiver o número da porta efêmera, o arquivo de resultado conteria um valor diferente a cada execução e o teste sempre falharia no registro/replay. Inclua o arquivo de porta e defina a variável de sessão do MySQL em conjunto sob --disable_query_log, para que nem a atribuição let nem a porta efêmera apareçam na saída. Use a variável de sessão em todos os lugares onde uma URL for necessária:

Gerenciamento de processos

Registre a saída do auxiliar e nunca a descarte. O padrão de lançador acima escreve o stderr do servidor em echo_server.log e o imprime em caso de falha. Descartar a saída do auxiliar torna as instabilidades inexplicáveis nos artefatos do CI. Encerre por PID, não por nome. No Linux, pkill -f echo_server.py pode corresponder ao próprio processo do MTR via /proc/cmdline. Use o arquivo de PID escrito pelo lançador:
Remova todos os arquivos temporários antes de o teste terminar. O check-testcase do MTR sinaliza qualquer arquivo deixado em $MYSQLTEST_VARDIR/tmp/ como estado sujo e faz o teste falhar:
Para uma implementação completa e testada do Padrão B, consulte vsql-http/mysql-test/t/vsql_http_requests.test, que cobre todo o ciclo de vida do teste, do --write_file até a limpeza.

Veja também