Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 114 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,71 +1,146 @@
# Compiler Automatic Tester
Repositório de ferramentas de avaliação de compiladores feitos na materia
# Auto Tester

Instruções para o uso do servidor para correção automática de compiladores.

## Dependências:
## Cadastro do webhook no servidor

### Dependências:

Existem duas dependências além do python
Instalar as seguintes dependências do python:

1. Gitpython usado para fazer o pull, ele pode ser instalado com:
- gitpython
- pygithub
- flask

### Instalação

Para configurar o servidor para ouvir aos webhooks:

- Clonar o repositório LogCompTester na máquina
- Instalar o apache2
- Em /etc/apache2/sites-enabled criar uma file chamada flask.conf
- Adicionar o seguinte código na file:

```
$ pip install gitpython
Listen 80
<VirtualHost *:80>

ServerAdmin webmaster@localhost
DocumentRoot /var/www/html

LogLevel debug

WSGIScriptAlias / /<path_ate_o_repositorio>/LogCompTester/Compilers/my_flask.wsgi
WSGIDaemonProcess flask-api processes=5 threads=1 user=ubuntu group=ubuntu display-name=%{GROUP}
WSGIProcessGroup flask-api
WSGIApplicationGroup %{GLOBAL}
WSGIPassAuthorization On
WSGIChunkedRequest On
ErrorLog ${APACHE_LOG_DIR}/error-80.log
CustomLog ${APACHE_LOG_DIR}/access-80.log combined

<Directory /<path_ate_o_repositorio>/LogCompTester/Compilers>
<IfVersion >= 2.4>
Require all granted
</IfVersion>
<IfVersion < 2.4>
Order allow,deny
Allow from all
</IfVersion>
</Directory>

</VirtualHost>
```

2. PyGithub usado para criar as issues ele precisa ser instalado:
- Editar a seguinte linha em LogCompTester/Compilers/servidor.py :

```
$ pip install pygithub
BASE_DIR = '/<path_ate_o_repositorio>/LogCompTester/Compilers'
```
- Editar a seguinte linha em LogCompTester/Compilers/issuer_pusher.py :

Para lançar a issue, crie um token no Github (https://github.com/settings/tokens) e o armazene em uma variável de ambiente chamada *GITHUB_TOKEN*.
## Configurando projeto:
```
token = "<github_token_do_monitor>"
```
- Editar a seguinte linha em LogCompTester/Compilers/my_flask.wsgi :

O codigo esta divido em três partes, fetch_release.py, auto_test.py e autorun.py elas em ordem fazem pull de todos um repositório, fazem todos os testes para um repositório e faz ambas as partes anteriores automaticamente.
```
sys.path.insert(0, "/<path_ate_o_repositorio>/LogCompTester/Compilers")
```
- Adicionar a seguinte linha ao .bashrc :

O fetch_release precisa de uma chave SSH configurada para se comunicar com o github é esperado que ela esteja no path "~/.ssh/id_rsa" que é o padrão.
Um tutorial de como criar uma chave ssh para o github pode ser encontrado [aqui](https://help.github.com/en/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)
```
export GITHUB_TOKEN="<github_token_do_monitor>"
```
- Restartar o servidor apache2
- Para testar se o servidor está rodando é possível acessar http://<ip_do_servidor>/ onde deve receber uma mensagem de "Hello World"

Quando o auto_test identifica uma falha em algum teste, uma issue é criada automaticamente no repositório.
### Adicionando ao banco de dados

## Como rodar:
Editar o arquivo LogCompTester/Compilers/db/populate.sql

Importante: todos os caminhos do código estão relativos, assim eles os programas precisam ser executados por um cmd que está dentro da pasta Compiler
- Para inserir uma nova versão:

Ao executar o fetch_releases ele deleta o repositório em src:
1. Para puxar a release vx.x.x de um aluno e repositorio, basta usar:
```
$ python fetch_release.py git_username repository vx.x.x
INSERT INTO version (version_name, direct_input, extension, date_from, date_to) VALUES(<version_name>, <1 (True) ou 0 (False)>, <extension>, <date_from>, <date_to>);
```
Se a release não for encontrada, é criado uma issue

2. Para rodar os testes para um aluno
- Para inserir um novo aluno:

```
$ python3 auto_test.py git_username repository vx.x.x
INSERT INTO users (git_username, name, surname) VALUES(<git_username>, <name>, <surname>);
```
Como o auto_test somente chama um subprocess para executar o código, o computador utilizado precisa ser capaz de compilar e executar o código.

O auto_testes tambem tem algumas constantes no começo do código, elas são:
1. acepeted_languages - lista das linguagem que esse programa foi testado com, se uma linguagem não estiver aqui o codigo da um raise, já que isso nunca deveria acontecer.
2. compile_languages - lista as linguagens que precisam de uma etapa de compilação antes da execução.
3. maxtime - tempo maximo que cada teste deve rodar antes de dar um timeout em segundos (é um float).
4. direct_input -(True ou False) diz se é passado o conteúdo de um teste, em vez do caminho dele, é usado para as versões baixas.
5. assembly - (True ou False) usado para testar a versão assembly, somente roda o arquivo de teste para cada aluno, e mostra um erro no terminal se ouve um erro na execução do teste, ele não gera reports automáticos.
6. assembly_test - o número do teste de assembly, geralmente só vai ter 1, é usado somente se assembly = True.
- Para inserir um novo repositório:

```
INSERT INTO repository (git_username, repository_name, language, compiled, program_call) VALUES(<git_username>, <repository_name>, <language>, <1 (True) ou 0 (False)>, <program_call>);
```

O auto_test pega o conteúdo de um report de erro e cria uma issue com o nome autoIssue para cada aluno, se um report não existe não é criado uma issue para o aluno.
O resultado do teste também é armazenado na base sqlite3.
Após editar o populate.sql, rodar o arquivo populate.py

### Logs

## Criando novos testes:
Logs do servidor podem ser acessadas em /var/log/apache2/access-80.log e /var/log/apache2/error-80.log

Todos os testes devem estar dentro da pasta tests e devem estar organizados por versão, o auto_test irá executar todos os testes da pasta especificada, porém ele não podem pular um número (ou seja não deve existir teste2.php sem teste1.php). Para um teste ser executado ele precisa de um teste{x}.php (ou .txt nos testes das versões baixos) que contem contem o código que deve ser testado, também precisa de um sol{x}.txt que contém a solução do teste correspondente, a solução deve ser exatamente o que o print do compilador deve gerar (cuidado com \n), ou seja precisa ter um número par de arquivos e todo o teste precisa ter um sol correspondente. Se o teste for feito para gerar um erro a solução correspondente deve conter somente a string "Error" qualquer outro conteúdo (incluindo \n) e o teste não é considerado um teste de erro.
## Cadastro do webhook para o aluno

Para adicionar o corretor automático ao seu repositório, o aluno deve:

- Ir na aba Settings -> Webhooks -> Add Webhook
- Em "Payload URL" o aluno deve adicionar http://<ip_do_servidor>/webhook
- Em "Content Type" o aluno deve selecionar a opção application/json
- Em "Which events would you like to trigger this webhook?" o aluno deve selecionar "Let me select individual events" e em seguida marcar APENAS as opções "Branch or tag creation" e "Releases"
- Ao final deixar a opção "Active" ligada

OBS: A pessoa (monitor) que tiver com o seu GITHUB_TOKEN cadastrado no servidor deve ser adicionada como colaborador no repositório do aluno

## Imagem SVG dos resultados

### Adicionando o SVG ao README

Para adicionar a imagem svg dos resultados dos testes o aluno deve:

- Adicionar a seguinte chamada de API ao seu README.md:

Também é possível gerar um teste que recebe um input, nesse caso é preciso criar um outro arquivo dentro da pasta inputs que deve estar dentro da pasta {X}_tests , ele deve se chamar input{x}.txt sendo que x deve ser o número do teste que deve receber o input, diferente dos testes que não podem pular um número, os inputs podem. Pode ser criado mais de um input para um teste, para isso necessário usar um \n dentro do input{x}.txt, como exemplo, no input abaixo o 4 e o 2 são passados como inputs diferentes (ou seja cada linha do input{x}.txt é um input novo).
```
4
2
![git_status](http://<ip_do_servidor>/svg/<Usuario_Github>/<Repositorio_Compilador>/)
```
Cuidado com \n se eles existirem como primeira linha input{x}.txt é mandado algo vazio para o stdin provavelmente gerando um teste diferente do esperado.

Usei um código simples que esta dentro de util chamdo simple_test_maker.py para ajudar na criação de novos testes.
### Legenda do SVG

Os possíveis valores para a coluna do meio são:

- **Delayed**: Quando o aluno falha em passar nos testes até o deadline de entrega da versão
- **On time**: Quando ainda há prazo até o deadline da versão ou se o aluno passou nos testes a tempo

Os possíveis valores para a terceira coluna são:

- **Error**: Quando ocorre algum erro ao executar os testes na release do aluno
- **Failed**: Quando o resultado dos testes é diferente do esperado
- **To do**: Quando você ainda não soltou nenhuma release da versão
- **Pass**: Quando passou em todos os testes

## Uso

O corretor é "acionado" quando uma release ou tag é criada pelo aluno