Advertisement
DeukausGames

Python SuSy

Feb 28th, 2020
181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.34 KB | None | 0 0
  1. import subprocess
  2. import sys
  3. import shlex
  4. import re
  5. import urllib.request
  6. import ssl
  7.  
  8. PATH_SUSY = "https://susy.ic.unicamp.br:9999/"
  9. NOME_DO_ARQUIVO = ""
  10. INPUT_EXTENSION = ".in"
  11. OUTPUT_EXTENSION = ".out"
  12.  
  13.  
  14. def descobre_comando(nome):
  15.     """ Dado o nome do arquivo, descobre o comando que deve ser executado. Há duas opções:
  16.    - python3 <nome>, caso o arquivo possua extensão .py
  17.    - ./<nome>, caso o arquivo seja um executável qualquer (ex : programa compilado em C)
  18.    """
  19.     if ".py" in nome:
  20.         """ Temos um arquivo Python. Retornamos o primeiro caso"""
  21.         return "python3 {}".format(nome)
  22.     else:
  23.         """ Temos um executável qualquer. Retornamos o segundo caso"""
  24.         return "./{}".format(nome)
  25.  
  26.  
  27. def roda_comando(comando, entrada=""):
  28.     """ Faz o parsing da string comando,executa o comando shell e retorna a saída.
  29.    Caso haja uma entrada (stdin), fornece ela ao programa.
  30.    """
  31.     args = shlex.split(comando)  # transforma os comandos em uma lista
  32.     entrada = entrada.encode("utf-8")  # converte a entrada para bytes
  33.     resultado = subprocess.run(
  34.         args, stdout=subprocess.PIPE, input=entrada
  35.     )  # roda o comando e guarda a saída
  36.     return resultado.stdout.decode("utf-8")  # converte o resultado para UTF-8 e retorna
  37.  
  38.  
  39. def faz_download(url):
  40.     """ Captura a saída de uma requisição wed a url designada"""
  41.     return (
  42.         urllib.request.urlopen(url, context=ssl.SSLContext(ssl.PROTOCOL_TLSv1))
  43.         .read()
  44.         .decode("utf-8")
  45.     )
  46.  
  47.  
  48. def descobre_arquivos(texto):
  49.     """ Dado o código html da página, descobre quais testes abertos o problema tem"""
  50.     limite = re.search(r"Testes fechados*", texto).span()[
  51.         0
  52.     ]  # obtemos a posicao em que começam os testes fechados
  53.     return re.findall(r"arq\d*", texto[:limite])
  54.  
  55.  
  56. def descobre_extensao(texto, arquivos):
  57.     """ Dado o código html da página, descobre a extensão dos arquivos de saída : .out ou .res
  58.    Esta função foi adicionada para dar compatilibilidade com turmas que não possuiam extensão .out .
  59.    """
  60.     final_com_out = arquivos[0] + ".out"  # vamos checar se há um arq*.out
  61.     if final_com_out in texto:
  62.         """ Há um arquivo com extensão .out, logo está extensão será a de todos outros arquivos"""
  63.         return ".out"
  64.     else:
  65.         """ Não há um arquivo com extensão .out, logo a extensão .res será a de todos outros arquivos"""
  66.         return ".res"
  67.  
  68.  
  69. def remove_duplicatas(lista):
  70.     """ Os arquivos de teste apareciam duplicados no HTML. Essa função remove esses testes"""
  71.     nova_lista = list(
  72.         set(lista)
  73.     )  # removemos as duplicatas com o set e após transformamos o conjunto em uma lista novamente
  74.     return sorted(nova_lista)  # ordenamos pois o set pode alterar a ordem
  75.  
  76.  
  77. class cores:
  78.     """ Armazena as contantes das cores"""
  79.  
  80.     ROXO = "\033[95m"
  81.     CIANO = "\033[96m"
  82.     CIANO_ESCURO = "\033[36m"
  83.     AZUL = "\033[94m"
  84.     VERDE = "\033[92m"
  85.     AMARELO = "\033[93m"
  86.     VERMELHO = "\033[91m"
  87.     NEGRITO = "\033[1m"
  88.     SUBLINHADO = "\033[4m"
  89.     FIM = "\033[0m"
  90.  
  91.  
  92. class TesteSusy:
  93.     def __init__(self, nome):
  94.         self.nome = nome.replace(
  95.             ".in", ""
  96.         )  # retiramos o in caso ocorra para ter o nome puro
  97.  
  98.     def roda(self):
  99.         """ Roda o código do usuário, baixa o código esperado e compara"""
  100.         PATH_DOWNLOAD_IN = PATH_SUSY + "/dados/" + self.nome + INPUT_EXTENSION
  101.         PATH_DOWNLOAD_OUT = PATH_SUSY + "/dados/" + self.nome + OUTPUT_EXTENSION
  102.         caso_teste = faz_download(PATH_DOWNLOAD_IN)
  103.         saida_esperada = faz_download(PATH_DOWNLOAD_OUT)
  104.         comando_executavel = descobre_comando(NOME_DO_ARQUIVO)
  105.         saida_obtida = roda_comando(comando_executavel, caso_teste)
  106.         if saida_esperada == saida_obtida:
  107.             """ O código executou corretamente"""
  108.             print(
  109.                 cores.NEGRITO + ("{}.in : ".format(self.nome)) + cores.AZUL + "OK" + cores.FIM
  110.             )
  111.             return 0
  112.         else:
  113.             """ O código não executou corretamente. Iremos exibir a diferença"""
  114.             print(
  115.                 cores.NEGRITO
  116.                 + ("{}.in : ".format(self.nome))
  117.                 + cores.VERMELHO
  118.                 + "Resposta Errada"
  119.                 + cores.FIM
  120.             )
  121.             print(">>> Saida esperada (SuSy):")
  122.             print(
  123.                 saida_esperada, end=""
  124.             )  # usamos end = "" para evitar duas quebras de linha
  125.             print(">>> Saida do seu programa:")
  126.             print(saida_obtida)
  127.             return 1
  128.  
  129.  
  130. if __name__ == "__main__":
  131.  
  132.     argumentos = sys.argv
  133.     if len(argumentos) < 4:
  134.         # Usuário não forneceu numero suficiente de parâmetros
  135.         print("Uso: python3 testador.py <turma> <laboratorio> <nome do arquivo>")
  136.         print(
  137.             "Exemplo: python3 testador.py mc102qrst 01 lab01.py"
  138.         )  # exemplo de arquivo Python
  139.         print(
  140.             "Exemplo: python3 testador.py mc202abc 00 lab00"
  141.         )  # exemplo de executável qualquer
  142.         exit()  # Nada acontece, feijoada
  143.  
  144.     turma = argumentos[1]
  145.     numero = argumentos[2]
  146.  
  147.     NOME_DO_ARQUIVO = argumentos[3]
  148.     PATH_SUSY = PATH_SUSY + turma + "/" + numero
  149.     PATH_TESTE = PATH_SUSY + "/dados/testes.html"
  150.  
  151.     print("Executando os testes...")
  152.  
  153.     codigo_fonte_pagina_teste = faz_download(
  154.         PATH_TESTE
  155.     )  # baixamos a página que contém os índices dos testes
  156.     lista_de_arquivos = remove_duplicatas(
  157.         descobre_arquivos(codigo_fonte_pagina_teste)
  158.     )  # gera a lista com os arquivos do lab e remove testes que aparecem duas vezes
  159.     OUTPUT_EXTENSION = descobre_extensao(
  160.         codigo_fonte_pagina_teste, lista_de_arquivos
  161.     )  # descobre se a extensão é .out ou .res
  162.  
  163.     testes_incorretos = 0
  164.  
  165.     for arquivo in lista_de_arquivos:
  166.         teste_do_arquivo = TesteSusy(arquivo)
  167.         testes_incorretos += (
  168.             teste_do_arquivo.roda()
  169.         )  # chama a função responsável por rodar cada caso teste
  170.  
  171.     print("Total de erros encontrados: {}".format(testes_incorretos))
  172.     print(
  173.         cores.NEGRITO
  174.         + "Lembre-se que o testador"
  175.         + cores.VERMELHO
  176.         + " NÃO "
  177.         + cores.FIM
  178.         + cores.NEGRITO
  179.         + "envia seu código!"
  180.         + cores.FIM
  181.     )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement