add upload test case zip test

This commit is contained in:
virusdefender 2017-01-25 23:01:33 +08:00
parent e6deec0834
commit 681a88ea83
3 changed files with 88 additions and 5 deletions

View File

@ -1,6 +1,7 @@
import hashlib import hashlib
from django.utils import timezone from django.utils import timezone
from utils.api.tests import APITestCase from utils.api.tests import APITestCase
from .models import JudgeServer, JudgeServerToken, SMTPConfig from .models import JudgeServer, JudgeServerToken, SMTPConfig

View File

@ -1,3 +1,9 @@
import os
import shutil
from zipfile import ZipFile
from django.conf import settings
from utils.api.tests import APITestCase from utils.api.tests import APITestCase
from .models import ProblemTag from .models import ProblemTag
@ -16,6 +22,8 @@ class ProblemTagListAPITest(APITestCase):
class TestCaseUploadAPITest(APITestCase): class TestCaseUploadAPITest(APITestCase):
def setUp(self): def setUp(self):
self.api = TestCaseUploadAPI() self.api = TestCaseUploadAPI()
self.url = self.reverse("test_case_upload_api")
self.create_super_admin()
def test_filter_file_name(self): def test_filter_file_name(self):
self.assertEqual(self.api.filter_name_list(["1.in", "1.out", "2.in", ".DS_Store"], spj=False), ["1.in", "1.out"]) self.assertEqual(self.api.filter_name_list(["1.in", "1.out", "2.in", ".DS_Store"], spj=False), ["1.in", "1.out"])
@ -23,3 +31,45 @@ class TestCaseUploadAPITest(APITestCase):
self.assertEqual(self.api.filter_name_list(["1.in", "1.out", "2.in"], spj=True), ["1.in", "2.in"]) self.assertEqual(self.api.filter_name_list(["1.in", "1.out", "2.in"], spj=True), ["1.in", "2.in"])
self.assertEqual(self.api.filter_name_list(["2.in", "3.in"], spj=True), []) self.assertEqual(self.api.filter_name_list(["2.in", "3.in"], spj=True), [])
def make_test_case_zip(self):
base_dir = os.path.join("/tmp", "test_case")
shutil.rmtree(base_dir, ignore_errors=True)
os.mkdir(base_dir)
file_names = ["1.in", "1.out", "2.in", ".DS_Store"]
for item in file_names:
with open(os.path.join(base_dir, item), "w", encoding="utf-8") as f:
f.write(item + "\n" + item + "\r\n" + "end")
zip_file = os.path.join(base_dir, "test_case.zip")
with ZipFile(os.path.join(base_dir, "test_case.zip"), "w") as f:
for item in file_names:
f.write(os.path.join(base_dir, item), item)
return zip_file
def test_upload_spj_test_case_zip(self):
with open(self.make_test_case_zip(), "rb") as f:
resp = self.client.post(self.url,
data={"spj": "true", "file": f}, format="multipart")
self.assertSuccess(resp)
data = resp.data["data"]
self.assertEqual(data["spj"], True)
test_case_dir = os.path.join(settings.TEST_CASE_DIR, data["id"])
self.assertTrue(os.path.exists(test_case_dir))
for item in data["info"]:
name = item["input_name"]
with open(os.path.join(test_case_dir, name), "r", encoding="utf-8") as f:
self.assertEqual(f.read(), name + "\n" + name + "\n" + "end")
def test_upload_test_case_zip(self):
with open(self.make_test_case_zip(), "rb") as f:
resp = self.client.post(self.url,
data={"spj": "false", "file": f}, format="multipart")
self.assertSuccess(resp)
data = resp.data["data"]
self.assertEqual(data["spj"], False)
test_case_dir = os.path.join(settings.TEST_CASE_DIR, data["id"])
self.assertTrue(os.path.exists(test_case_dir))
for item in data["info"]:
name = item["input_name"]
with open(os.path.join(test_case_dir, name), "r", encoding="utf-8") as f:
self.assertEqual(f.read(), name + "\n" + name + "\n" + "end")

View File

@ -1,12 +1,13 @@
import hashlib
import json
import os import os
import zipfile import zipfile
from django.conf import settings from django.conf import settings
from utils.api import CSRFExemptAPIView
from account.decorators import admin_required from account.decorators import admin_required
from utils.api import CSRFExemptAPIView
from utils.shortcuts import rand_str from utils.shortcuts import rand_str
from ..serializers import TestCaseUploadForm from ..serializers import TestCaseUploadForm
@ -51,7 +52,7 @@ class TestCaseUploadAPI(CSRFExemptAPIView):
f.write(chunk) f.write(chunk)
try: try:
zip_file = zipfile.ZipFile(tmp_file) zip_file = zipfile.ZipFile(tmp_file)
except zipfile.BadZipfile: except zipfile.BadZipFile:
return self.error("Bad zip file") return self.error("Bad zip file")
name_list = zip_file.namelist() name_list = zip_file.namelist()
test_case_list = self.filter_name_list(name_list, spj=spj) test_case_list = self.filter_name_list(name_list, spj=spj)
@ -62,11 +63,42 @@ class TestCaseUploadAPI(CSRFExemptAPIView):
test_case_dir = os.path.join(settings.TEST_CASE_DIR, test_case_id) test_case_dir = os.path.join(settings.TEST_CASE_DIR, test_case_id)
os.mkdir(test_case_dir) os.mkdir(test_case_dir)
size_cache = {}
md5_cache = {}
for item in test_case_list: for item in test_case_list:
with open(os.path.join(test_case_dir, item), "wb") as f: with open(os.path.join(test_case_dir, item), "wb") as f:
f.write(zip_file.read(item).replace(b"\r\n", b"\n")) content = zip_file.read(item).replace(b"\r\n", b"\n")
size_cache[item] = len(content)
if item.endswith(".out"):
md5_cache[item] = hashlib.md5(content).hexdigest()
f.write(content)
test_case_info = {"spj": spj, "test_cases": {}}
hint = None hint = None
diff = set(name_list).difference(set(test_case_list)) diff = set(name_list).difference(set(test_case_list))
if diff: if diff:
hint = ", ".join(diff) + " are ignored" hint = ", ".join(diff) + " are ignored"
return self.success({"id": test_case_id, "file_list": test_case_list, "hint": hint, "spj": spj})
ret = []
if spj:
for index, item in enumerate(test_case_list):
data = {"input_name": item, "input_size": size_cache[item]}
ret.append(data)
test_case_info["test_cases"][str(index + 1)] = data
else:
# ["1.in", "1.out", "2.in", "2.out"] => [("1.in", "1.out"), ("2.in", "2.out")]
test_case_list = zip(*[test_case_list[i::2] for i in range(2)])
for index, item in enumerate(test_case_list):
data = {"stripped_output_md5": md5_cache[item[1]],
"input_size": size_cache[item[0]],
"output_size": size_cache[item[1]],
"input_name": item[0],
"output_name": item[1]}
ret.append(data)
test_case_info["test_cases"][str(index + 1)] = data
with open(os.path.join(test_case_dir, "info"), "w", encoding="utf-8") as f:
f.write(json.dumps(test_case_info, indent=4))
return self.success({"id": test_case_id, "info": ret, "hint": hint, "spj": spj})