From 70c64507ccb5f18c25e0b45156328b7ffcf38f6b Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Wed, 26 Aug 2015 14:25:14 +0800 Subject: [PATCH 01/20] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 16 +++++--------- judge/Dockerfile | 19 ++++++++++++++++ judge/judger_controller/settings.py | 7 +++++- oj/daocloud_settings.py | 19 ---------------- oj/local_settings.py | 9 +++++--- oj/server_settings.py | 34 +++++++++++++++++++++++++++++ oj/settings.py | 10 ++------- requirements.txt | 3 ++- 8 files changed, 74 insertions(+), 43 deletions(-) create mode 100644 judge/Dockerfile delete mode 100644 oj/daocloud_settings.py diff --git a/Dockerfile b/Dockerfile index f10b84c..2e10830 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,7 @@ FROM python:2.7 -ENV PYTHONUNBUFFERED 1 -ENV oj_env daocloud -RUN mkdir /var/oj -COPY . /var/oj/ -WORKDIR /var/oj/ +ENV PYTHONBUFFERED 1 +RUN mkdir -p /code/log /code/test_case +WORKDIR /code +ADD requirements.txt /code/ RUN pip install -r requirements.txt -EXPOSE 8080 -RUN mkdir LOG -RUN mkdir test_case -RUN mkdir tmp -RUN python manage.py migrate -CMD python manage.py runserver 0.0.0.0:8080 +EXPOSE 8010 \ No newline at end of file diff --git a/judge/Dockerfile b/judge/Dockerfile new file mode 100644 index 0000000..32897e2 --- /dev/null +++ b/judge/Dockerfile @@ -0,0 +1,19 @@ +FROM ubuntu:14.04 +MAINTAINER virusdefender +RUN mkdir /var/install/ +WORKDIR /var/install/ +ENV DEBIAN_FRONTEND noninteractive +RUN apt-get update +RUN apt-get -y install software-properties-common python-software-properties +RUN add-apt-repository -y ppa:webupd8team/java +RUN apt-get update +RUN apt-get -y install python gcc g++ rake pkg-config git make autoconf automake libtool python-pip +RUN echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections +RUN echo debconf shared/accepted-oracle-license-v1-1 seen true | sudo debconf-set-selections +RUN apt-get install -y oracle-java7-installer +RUN apt-get -y install libseccomp-dev +RUN git clone https://github.com/quark-zju/lrun.git +RUN cd lrun && make install +RUN mkdir -p /var/judger/run/ && mkdir /var/judger/test_case/ && mkdir /var/judger/code/ +RUN chmod -R 777 /var/judger/run/ +WORKDIR /var/judger/code/ \ No newline at end of file diff --git a/judge/judger_controller/settings.py b/judge/judger_controller/settings.py index a0d3e66..668838b 100644 --- a/judge/judger_controller/settings.py +++ b/judge/judger_controller/settings.py @@ -1,4 +1,5 @@ # coding=utf-8 +# 这个redis 是 celery 使用的,包括存储队列信息还有部分统计信息 redis_config = { "host": "121.42.32.129", "port": 6379, @@ -6,6 +7,7 @@ redis_config = { } +# 判题的 docker 容器的配置参数 docker_config = { "image_name": " a7673b55d263", "docker_path": "docker", @@ -13,10 +15,13 @@ docker_config = { } +# 测试用例的路径,是主机上的实际路径 test_case_dir = "/root/test_case/" -source_code_dir = "/root/" +# 源代码路径,也就是 manage.py 所在的实际路径 +source_code_dir = "/root/OnlineJudge/" +# 存储提交信息的数据库,是 celery 使用的,与 oj.settings/local_settings 等区分,那是 web 服务器访问的地址 submission_db = { "host": "127.0.0.1", "port": 3306, diff --git a/oj/daocloud_settings.py b/oj/daocloud_settings.py deleted file mode 100644 index a99e009..0000000 --- a/oj/daocloud_settings.py +++ /dev/null @@ -1,19 +0,0 @@ -# coding=utf-8 -import os - -LOG_PATH = "LOG/" - -# Database -# https://docs.djangoproject.com/en/1.8/ref/settings/#databases -BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - 'CONN_MAX_AGE': 1, - } -} - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True \ No newline at end of file diff --git a/oj/local_settings.py b/oj/local_settings.py index da1a672..196c5ad 100644 --- a/oj/local_settings.py +++ b/oj/local_settings.py @@ -5,22 +5,23 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 下面是需要自己修改的 -LOG_PATH = "LOG/" +LOG_PATH = "log/" # 注意这是web 服务器访问的地址,判题端访问的地址不一定一样,因为可能不在一台机器上 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - 'CONN_MAX_AGE': 0.3, }, + # submission 的 name 和 engine 请勿修改,其他代码会用到 'submission': { 'NAME': 'oj_submission', 'ENGINE': 'django.db.backends.mysql', 'HOST': "121.42.32.129", 'POST': 3306, 'USER': 'root', - 'PASSWORD': 'mypwd' + 'PASSWORD': 'mypwd', + 'CONN_MAX_AGE': 0.1, } } @@ -31,3 +32,5 @@ TEST_CASE_DIR = os.path.join(BASE_DIR, 'test_case/') DATABASE_ROUTERS = ['oj.db_router.DBRouter'] + +ALLOWED_HOSTS = [] diff --git a/oj/server_settings.py b/oj/server_settings.py index 9bad579..0395846 100644 --- a/oj/server_settings.py +++ b/oj/server_settings.py @@ -1 +1,35 @@ # coding=utf-8 +import os + +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# 下面是需要自己修改的 +LOG_PATH = "log/" + +# 注意这是web 服务器访问的地址,判题端访问的地址不一定一样,因为可能不在一台机器上 +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + }, + # submission 的 name 和 engine 请勿修改,其他代码会用到 + 'submission': { + 'NAME': 'oj_submission', + 'ENGINE': 'django.db.backends.mysql', + 'HOST': "121.42.32.129", + 'POST': 3306, + 'USER': 'root', + 'PASSWORD': 'mypwd', + 'CONN_MAX_AGE': 0.1, + } +} + +DEBUG = False + +# 同理 这是 web 服务器的上传路径 +TEST_CASE_DIR = os.path.join(BASE_DIR, 'test_case/') + +DATABASE_ROUTERS = ['oj.db_router.DBRouter'] + +ALLOWED_HOSTS = ['*'] \ No newline at end of file diff --git a/oj/settings.py b/oj/settings.py index cf4dafc..05cddc8 100644 --- a/oj/settings.py +++ b/oj/settings.py @@ -14,15 +14,13 @@ https://docs.djangoproject.com/en/1.8/ref/settings/ # Build paths inside the project like this: os.path.join(BASE_DIR, ...) import os -# todo 判断运行环境 +# 判断运行环境 ENV = os.environ.get("oj_env", "local") if ENV == "local": from .local_settings import * elif ENV == "server": from .server_settings import * -elif ENV == "daocloud": - from .daocloud_settings import * BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -33,7 +31,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'hzfp^8mbgapc&x%$#xv)0=t8s7_ilingw(q3!@h&2fty6v6fxz' -ALLOWED_HOSTS = [] + # Application definition @@ -115,10 +113,6 @@ STATIC_URL = '/static/' STATICFILES_DIRS = (os.path.join(BASE_DIR, "static/src/"),) -TEMPLATE_DIRS = ( - os.path.join(BASE_DIR, "template/src"), -) - AUTH_USER_MODEL = 'account.User' LOGGING = { diff --git a/requirements.txt b/requirements.txt index 9ad8f3f..3a706b4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,5 @@ django-rest-swagger celery gunicorn coverage -django-extensions \ No newline at end of file +django-extensions +supervisor \ No newline at end of file From 3e7dfa9dc8c343bd589c0db7a47dc16c29e86d51 Mon Sep 17 00:00:00 2001 From: hohoTT <609029365@qq.com> Date: Wed, 26 Aug 2015 16:59:00 +0800 Subject: [PATCH 02/20] =?UTF-8?q?=E7=9B=AE=E5=89=8D=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E8=BF=98=E6=9C=89=E8=A6=81=E5=AE=8C=E5=96=84=E7=9A=84=E5=9C=B0?= =?UTF-8?q?=E6=96=B9,=20=20contest=E3=80=81=E8=BF=98=E6=9C=89=E7=B1=BB?= =?UTF-8?q?=E4=BC=BC=E9=A1=B5=E9=9D=A2=E4=B8=8D=E5=AD=98=E5=9C=A8=E7=9A=84?= =?UTF-8?q?=E6=83=85=E5=86=B5=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contest/test_urls.py | 9 + contest/tests.py | 176 +++++++++++++++++- contest/views.py | 16 +- contest_submission/tests.py | 89 ++++++++- contest_submission/views.py | 9 +- static/src/js/app/oj/problem/problem.js | 2 +- submission/tests.py | 91 +++++++-- .../oj/submission/my_submissions_list.html | 2 +- 8 files changed, 353 insertions(+), 41 deletions(-) create mode 100644 contest/test_urls.py diff --git a/contest/test_urls.py b/contest/test_urls.py new file mode 100644 index 0000000..234c600 --- /dev/null +++ b/contest/test_urls.py @@ -0,0 +1,9 @@ +# coding=utf-8 +from django.conf.urls import include, url +from django.views.generic import TemplateView + + +urlpatterns = [ + + url(r'^login/$', TemplateView.as_view(template_name="oj/account/login.html"), name="user_login_page"), +] diff --git a/contest/tests.py b/contest/tests.py index 58c9127..2063c4e 100644 --- a/contest/tests.py +++ b/contest/tests.py @@ -1,15 +1,18 @@ # coding=utf-8 import json from django.core.urlresolvers import reverse -from django.test import TestCase +from django.test import TestCase, Client +from django.http import HttpResponse from rest_framework.test import APITestCase, APIClient from account.models import User from group.models import Group from contest.models import Contest, ContestProblem +from .models import ContestSubmission from announcement.models import Announcement from account.models import REGULAR_USER, ADMIN, SUPER_ADMIN +from decorators import check_user_contest_permission class ContestAdminAPITest(APITestCase): @@ -398,3 +401,174 @@ class ContestProblemAdminAPItEST(APITestCase): response = self.client.put(self.url, data=data) self.assertEqual(response.data["code"], 1) + +class ContestPasswordVerifyAPITest(APITestCase): + def setUp(self): + self.client = APIClient() + self.url = reverse('contest_password_verify_api') + self.user = User.objects.create(username="test1", admin_type=SUPER_ADMIN) + self.user.set_password("testaa") + self.user.save() + self.user2 = User.objects.create(username="test2", admin_type=ADMIN) + self.user2.set_password("testbb") + self.user2.save() + self.client.login(username="test1", password="testaa") + self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1, + contest_type=2, show_rank=True, show_user_submission=True, + start_time="2015-08-15T10:00:00.000Z", + end_time="2015-08-15T12:00:00.000Z", + password="aacc", created_by=User.objects.get(username="test1")) + + def test_invalid_format(self): + self.client.login(username="test2", password="testbb") + data = {"contest_id": self.global_contest.id} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data["code"], 1) + + def test_contest_does_not_exist(self): + self.client.login(username="test2", password="testbb") + data = {"contest_id": self.global_contest.id + 1, "password": "aacc"} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data, {"code": 1, "data": u"比赛不存在"}) + + def test_contest_password_verify_unsuccessfully(self): + self.client.login(username="test2", password="testbb") + data = {"contest_id": self.global_contest.id, "password": "aabb"} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data, {"code": 1, "data": u"密码错误"}) + + def test_contest_password_verify_successfully(self): + self.client.login(username="test2", password="testbb") + data = {"contest_id": self.global_contest.id, "password": "aacc"} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data["code"], 0) + + +class ContestPageTest(TestCase): + # 单个比赛详情页的测试 + def setUp(self): + self.client = Client() + self.user1 = User.objects.create(username="test1", admin_type=SUPER_ADMIN) + self.user1.set_password("testaa") + self.user1.save() + self.client.login(username="test1", password="testaa") + self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1, + contest_type=2, show_rank=True, show_user_submission=True, + start_time="2015-08-15T10:00:00.000Z", + end_time="2015-08-15T12:00:00.000Z", + password="aacc", created_by=User.objects.get(username="test1")) + + def test_visit_contest_page_successfully(self): + response = self.client.get('/contest/1/') + self.assertEqual(response.status_code, 200) + + def test_visit_contest_page_unsuccessfully(self): + response = self.client.get('/contest/10/') + self.assertTemplateUsed(response, "utils/error.html") + + +class ContestProblemPageTest(TestCase): + # 单个比赛题目详情页的测试 + def setUp(self): + self.client = Client() + self.user1 = User.objects.create(username="test1", admin_type=SUPER_ADMIN) + self.user1.set_password("testaa") + self.user1.save() + self.client.login(username="test1", password="testaa") + self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1, + contest_type=2, show_rank=True, show_user_submission=True, + start_time="2015-08-15T10:00:00.000Z", + end_time="2015-08-15T12:00:00.000Z", + password="aacc", created_by=User.objects.get(username="test1")) + self.contest_problem = ContestProblem.objects.create(title="titlex", + description="descriptionx", + input_description="input1_description", + output_description="output1_description", + test_case_id="1", + samples=json.dumps([{"input": "1 1", "output": "2"}]), + time_limit=100, + memory_limit=1000, + hint="hint1", + created_by=User.objects.get(username="test1"), + contest=Contest.objects.get(title="titlex"), + sort_index="a") + + def test_visit_contest_problem_page_successfully(self): + response = self.client.get('/contest/1/problem/1/') + self.assertEqual(response.status_code, 200) + + def test_visit_contest_page_unsuccessfully(self): + response = self.client.get('/contest/10/') + self.assertTemplateUsed(response, "utils/error.html") + + def test_visit_contest_submissions_page_successfully(self): + ContestSubmission.objects.create(user=self.user1, + contest=self.global_contest, + problem=self.contest_problem, + ac=True) + response = self.client.get('/contest/1/problem/1/submissions/') + self.assertEqual(response.status_code, 200) + + +class ContestProblemListPageTest(TestCase): + # 比赛题目列表的测试 + def setUp(self): + self.client = Client() + self.user1 = User.objects.create(username="test1", admin_type=SUPER_ADMIN) + self.user1.set_password("testaa") + self.user1.save() + self.client.login(username="test1", password="testaa") + self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1, + contest_type=2, show_rank=True, show_user_submission=True, + start_time="2015-08-15T10:00:00.000Z", + end_time="2015-08-15T12:00:00.000Z", + password="aacc", created_by=User.objects.get(username="test1")) + self.contest_problem = ContestProblem.objects.create(title="titlex", + description="descriptionx", + input_description="input1_description", + output_description="output1_description", + test_case_id="1", + samples=json.dumps([{"input": "1 1", "output": "2"}]), + time_limit=100, + memory_limit=1000, + hint="hint1", + created_by=User.objects.get(username="test1"), + contest=Contest.objects.get(title="titlex"), + sort_index="a") + + def test_visit_contest_problem_list_page_successfully(self): + response = self.client.get('/contest/1/problems/') + self.assertEqual(response.status_code, 200) + + def test_visit_contest_problem_page_unsuccessfully(self): + response = self.client.get('/contest/1/problem/100/') + self.assertTemplateUsed(response, "utils/error.html") + + +class ContestListPageTest(TestCase): + # 以下是所有比赛列表页的测试 + def setUp(self): + self.client = Client() + self.user1 = User.objects.create(username="test1", admin_type=SUPER_ADMIN) + self.user1.set_password("testaa") + self.user1.save() + self.url = reverse('contest_list_page') + self.client.login(username="test1", password="testaa") + self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1, + contest_type=2, show_rank=True, show_user_submission=True, + start_time="2015-08-15T10:00:00.000Z", + end_time="2015-08-15T12:00:00.000Z", + password="aacc", created_by=User.objects.get(username="test1")) + + def test_visit_contest_list_page_successfully(self): + response = self.client.get('/contests/') + self.assertEqual(response.status_code, 200) + + def test_visit_contest_list_page_unsuccessfully(self): + response = self.client.get('/contests/2/') + self.assertTemplateUsed(response, "utils/error.html") + + + + + diff --git a/contest/views.py b/contest/views.py index 8c2e29f..72dffbe 100644 --- a/contest/views.py +++ b/contest/views.py @@ -258,10 +258,10 @@ class ContestPasswordVerifyAPIView(APIView): try: contest = Contest.objects.get(id=data["contest_id"], contest_type=2) except Contest.DoesNotExist: - return error_response(u"密码错误") + return error_response(u"比赛不存在") if data["password"] != contest.password: - return error_response(u" 密码错误") + return error_response(u"密码错误") else: if "contests" not in request.session: request.session["contests"] = [] @@ -279,10 +279,7 @@ def contest_page(request, contest_id): """ 单个比赛的详情页 """ - try: - contest = Contest.objects.get(id=contest_id) - except Contest.DoesNotExist: - return error_page(request, u"比赛不存在") + contest = Contest.objects.get(id=contest_id) return render(request, "oj/contest/contest_index.html", {"contest": contest}) @@ -292,10 +289,7 @@ def contest_problem_page(request, contest_id, contest_problem_id): """ 单个比赛题目的详情页 """ - try: - contest = Contest.objects.get(id=contest_id) - except Contest.DoesNotExist: - return error_page(request, u"比赛不存在") + contest = Contest.objects.get(id=contest_id) try: contest_problem = ContestProblem.objects.get(id=contest_problem_id, visible=True) except ContestProblem.DoesNotExist: @@ -324,7 +318,7 @@ def contest_problems_list_page(request, contest_id): """ try: contest_problems = ContestProblem.objects.filter(contest=Contest.objects.get(id=contest_id)).order_by("sort_index") - except Contest.DoesNotExist: + except ContestProblem.DoesNotExist: return error_page(request, u"比赛题目不存在") # 右侧的公告列表 announcements = Announcement.objects.filter(is_global=True, visible=True).order_by("-create_time") diff --git a/contest_submission/tests.py b/contest_submission/tests.py index 7ce503c..836df09 100644 --- a/contest_submission/tests.py +++ b/contest_submission/tests.py @@ -1,3 +1,88 @@ -from django.test import TestCase +# coding=utf-8 +import json +from django.test import TestCase, Client +from django.core.urlresolvers import reverse +from account.models import User, REGULAR_USER, ADMIN, SUPER_ADMIN +from problem.models import Problem +from contest.models import Contest, ContestProblem +from submission.models import Submission +from rest_framework.test import APITestCase, APIClient -# Create your tests here. + +class ContestSubmissionAPITest(APITestCase): + def setUp(self): + self.client = APIClient() + self.url = reverse('contest_submission_api') + self.user1 = User.objects.create(username="test1", admin_type=SUPER_ADMIN) + self.user1.set_password("testaa") + self.user1.save() + self.user2 = User.objects.create(username="test2", admin_type=REGULAR_USER) + self.user2.set_password("testbb") + self.user2.save() + self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1, + contest_type=1, show_rank=True, show_user_submission=True, + start_time="2015-08-15T10:00:00.000Z", + end_time="2015-08-30T12:00:00.000Z", + created_by=User.objects.get(username="test1")) + self.contest_problem = ContestProblem.objects.create(title="titlex", + description="descriptionx", + input_description="input1_description", + output_description="output1_description", + test_case_id="1", + samples=json.dumps([{"input": "1 1", "output": "2"}]), + time_limit=100, + memory_limit=1000, + hint="hint1", + created_by=User.objects.get(username="test1"), + contest=Contest.objects.get(title="titlex"), + sort_index="a") + + # 以下是创建比赛的提交 + def test_invalid_format(self): + self.client.login(username="test1", password="testaa") + data = {"contest_id": self.global_contest.id, "language": 1} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data["code"], 1) + + def test_contest_submission_successfully(self): + self.client.login(username="test1", password="testaa") + data = {"contest_id": self.global_contest.id, "problem_id": self.contest_problem.id, + "language": 1, "code": '#include "stdio.h"\nint main(){\n\treturn 0;\n}'} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data["code"], 0) + + def test_contest_problem_does_not_exist(self): + self.client.login(username="test1", password="testaa") + data = {"contest_id": self.global_contest.id, "problem_id": self.contest_problem.id + 10, + "language": 1, "code": '#include "stdio.h"\nint main(){\n\treturn 0;\n}'} + response = self.client.post(self.url, data=data) + self.assertEqual(response.data, {"code": 1, "data": u"题目不存在"}) + + +class ContestProblemMySubmissionListTest(TestCase): + # 以下是我比赛单个题目的提交列表的测试 + def setUp(self): + self.client = Client() + self.user1 = User.objects.create(username="test1", admin_type=SUPER_ADMIN) + self.user1.set_password("testaa") + self.user1.save() + self.user2 = User.objects.create(username="test2", admin_type=REGULAR_USER) + self.user2.set_password("testbb") + self.user2.save() + self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1, + contest_type=1, show_rank=True, show_user_submission=True, + start_time="2015-08-15T10:00:00.000Z", + end_time="2015-08-30T12:00:00.000Z", + created_by=User.objects.get(username="test1")) + self.contest_problem = ContestProblem.objects.create(title="titlex", + description="descriptionx", + input_description="input1_description", + output_description="output1_description", + test_case_id="1", + samples=json.dumps([{"input": "1 1", "output": "2"}]), + time_limit=100, + memory_limit=1000, + hint="hint1", + created_by=self.user1, + contest=self.global_contest, + sort_index="a") diff --git a/contest_submission/views.py b/contest_submission/views.py index 0dba7cb..efab6ad 100644 --- a/contest_submission/views.py +++ b/contest_submission/views.py @@ -34,16 +34,13 @@ class ContestSubmissionAPIView(APIView): serializer = CreateContestSubmissionSerializer(data=request.data) if serializer.is_valid(): data = serializer.data - try: - contest = Contest.objects.get(id=data["contest_id"]) - except Contest.DoesNotExist: - return error_response(u"比赛不存在") + contest = Contest.objects.get(id=data["contest_id"]) try: problem = ContestProblem.objects.get(contest=contest, id=data["problem_id"]) # 更新题目提交计数器 problem.total_submit_number += 1 problem.save() - except Problem.DoesNotExist: + except ContestProblem.DoesNotExist: return error_response(u"题目不存在") submission = Submission.objects.create(user_id=request.user.id, language=int(data["language"]), @@ -74,7 +71,7 @@ def contest_problem_my_submissions_list_page(request, contest_id, contest_proble return error_page(request, u"比赛不存在") try: contest_problem = ContestProblem.objects.get(id=contest_problem_id, visible=True) - except Problem.DoesNotExist: + except ContestProblem.DoesNotExist: return error_page(request, u"比赛问题不存在") submissions = Submission.objects.filter(user_id=request.user.id, problem_id=contest_problem.id).order_by("-create_time"). \ values("id", "result", "create_time", "accepted_answer_time", "language") diff --git a/static/src/js/app/oj/problem/problem.js b/static/src/js/app/oj/problem/problem.js index d936e0f..1faeb6d 100644 --- a/static/src/js/app/oj/problem/problem.js +++ b/static/src/js/app/oj/problem/problem.js @@ -48,7 +48,7 @@ require(["jquery", "codeMirror", "csrfToken", "bsAlert"], function ($, codeMirro if (!data.result) { html += "CPU time: " + data.accepted_answer_time + "ms   "; } - html += ('查看详情 '); + html += ('查看详情 '); return html; } diff --git a/submission/tests.py b/submission/tests.py index e745bde..99bfee9 100644 --- a/submission/tests.py +++ b/submission/tests.py @@ -1,6 +1,6 @@ # coding=utf-8 import json -from django.test import TestCase +from django.test import TestCase, Client from django.core.urlresolvers import reverse from account.models import User, REGULAR_USER, ADMIN, SUPER_ADMIN from problem.models import Problem @@ -11,7 +11,7 @@ from rest_framework.test import APITestCase, APIClient class SubmissionsListPageTest(TestCase): def setUp(self): - self.client = APIClient() + self.client = Client() self.user = User.objects.create(username="gogoing", admin_type=REGULAR_USER) self.user2 = User.objects.create(username="cool", admin_type=REGULAR_USER) self.user2.set_password("666666") @@ -115,32 +115,85 @@ class SubmissionAPITest(APITestCase): response = self.client.get(self.url, data=data) self.assertEqual(response.data["code"], 0) + def test_parameter_error(self): + self.client.login(username="test1", password="testaa") + response = self.client.get(self.url) + self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) -class ContestSubmissionAPITest(APITestCase): + +class SubmissionAdminAPITest(APITestCase): def setUp(self): self.client = APIClient() - self.url = reverse('contest_submission_api') - self.user1 = User.objects.create(username="test1", admin_type=REGULAR_USER) - self.user1.set_password("testaa") - self.user1.save() - self.user2 = User.objects.create(username="test2", admin_type=SUPER_ADMIN) - self.user2.set_password("testbb") - self.user2.save() + self.url = reverse('submission_admin_api_view') + self.user = User.objects.create(username="test1", admin_type=SUPER_ADMIN) + self.user.set_password("testaa") + self.user.save() + self.client.login(username="test1", password="testaa") + self.problem = Problem.objects.create(title="title1", + description="description1", + input_description="input1_description", + output_description="output1_description", + test_case_id="1", + source="source1", + samples=json.dumps([{"input": "1 1", "output": "2"}]), + time_limit=100, + memory_limit=1000, + difficulty=1, + hint="hint1", + created_by=User.objects.get(username="test1")) self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1, contest_type=2, show_rank=True, show_user_submission=True, start_time="2015-08-15T10:00:00.000Z", end_time="2015-08-15T12:00:00.000Z", - password="aacc", created_by=User.objects.get(username="test2")) + password="aacc", created_by=User.objects.get(username="test1")) + + self.submission = Submission.objects.create(user_id=self.user.id, + language=1, + code='#include "stdio.h"\nint main(){\n\treturn 0;\n}', + problem_id=self.problem.id) def test_invalid_format(self): + response = self.client.get(self.url) + self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) + + def test_problem_does_not_exist(self): + data = {"problem_id": self.problem.id} + response = self.client.get(self.url, data=data) + self.assertEqual(response.data["code"], 0) + + +class SubmissionPageTest(TestCase): + # 单个题目的提交详情页 + def setUp(self): + self.client = Client() + self.user1 = User.objects.create(username="test1", admin_type=SUPER_ADMIN) + self.user1.set_password("testaa") + self.user1.save() + self.user2 = User.objects.create(username="test2", admin_type=ADMIN) + self.user2.set_password("testbb") + self.user2.save() self.client.login(username="test1", password="testaa") - data = {"language": 1} - response = self.client.post(self.url, data=data) - pass - - - - - + self.problem = Problem.objects.create(title="title1", + description="description1", + input_description="input1_description", + output_description="output1_description", + test_case_id="1", + source="source1", + samples=json.dumps([{"input": "1 1", "output": "2"}]), + time_limit=100, + memory_limit=1000, + difficulty=1, + hint="hint1", + created_by=User.objects.get(username="test1")) + self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1, + contest_type=2, show_rank=True, show_user_submission=True, + start_time="2015-08-15T10:00:00.000Z", + end_time="2015-08-15T12:00:00.000Z", + password="aacc", created_by=User.objects.get(username="test1")) + + self.submission = Submission.objects.create(user_id=self.user1.id, + language=1, + code='#include "stdio.h"\nint main(){\n\treturn 0;\n}', + problem_id=self.problem.id) diff --git a/template/oj/submission/my_submissions_list.html b/template/oj/submission/my_submissions_list.html index 279bee6..ce9f063 100644 --- a/template/oj/submission/my_submissions_list.html +++ b/template/oj/submission/my_submissions_list.html @@ -18,7 +18,7 @@ {% for item in submissions %} - + {{ forloop.counter |add:start_id }} {{ item.create_time }} {{ item.result|translate_result }} From 2252107a8017e58628166cc010f421724e334962 Mon Sep 17 00:00:00 2001 From: hohoTT <609029365@qq.com> Date: Sat, 29 Aug 2015 15:20:49 +0800 Subject: [PATCH 03/20] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- account/tests.py | 2 +- contest/tests.py | 7 +++++++ contest_submission/tests.py | 5 +++++ problem/tests.py | 14 ++++++++++++++ submission/tests.py | 9 ++------- .../src/oj/submission/my_submissions_list.html | 2 +- 6 files changed, 30 insertions(+), 9 deletions(-) diff --git a/account/tests.py b/account/tests.py index f8cc9d0..3473c6c 100644 --- a/account/tests.py +++ b/account/tests.py @@ -379,7 +379,7 @@ class UserLogoutTest(TestCase): user.set_password("1") user.save() - def logout_success(self): + def test_logout_success(self): self.client = Client() self.client.login(username="test", password="1") response = self.client.get("/logout/") diff --git a/contest/tests.py b/contest/tests.py index 2063c4e..1605e02 100644 --- a/contest/tests.py +++ b/contest/tests.py @@ -568,6 +568,13 @@ class ContestListPageTest(TestCase): response = self.client.get('/contests/2/') self.assertTemplateUsed(response, "utils/error.html") + def test_query_by_keyword(self): + response = self.client.get(self.url + "?keyword=title1") + self.assertEqual(response.status_code, 200) + + def test_query_by_join_successfully(self): + response = self.client.get(self.url + "?join=True") + self.assertEqual(response.status_code, 200) diff --git a/contest_submission/tests.py b/contest_submission/tests.py index debd64b..975d11c 100644 --- a/contest_submission/tests.py +++ b/contest_submission/tests.py @@ -87,6 +87,11 @@ class ContestProblemMySubmissionListTest(TestCase): contest=self.global_contest, sort_index="a") + def test_contestsList_page_not_exist(self): + self.client.login(username="test1", password="testaa") + response = self.client.get('/contest/1/submissions/999/') + self.assertTemplateUsed(response, "utils/error.html") + class SubmissionAPITest(APITestCase): def setUp(self): diff --git a/problem/tests.py b/problem/tests.py index ab6d898..6313695 100644 --- a/problem/tests.py +++ b/problem/tests.py @@ -187,5 +187,19 @@ class ProblemListPageTest(TestCase): hint="hint1", created_by=User.objects.get(username="test")) + def test_problemListPage_not_exist(self): + response = self.client.get('/problems/999/') + self.assertTemplateUsed(response, "utils/error.html") + def test_query_by_keyword(self): + response = self.client.get(self.url + "?keyword=title1") + self.assertEqual(response.status_code, 200) + + def test_query_by_tag_successfully(self): + response = self.client.get(self.url + "?tag=") + self.assertEqual(response.status_code, 200) + + def test_tag_does_not_exists(self): + response = self.client.get(self.url + "?tag=xxxxxx") + self.assertTemplateUsed(response, "utils/error.html") diff --git a/submission/tests.py b/submission/tests.py index 80fd111..bb1d46d 100644 --- a/submission/tests.py +++ b/submission/tests.py @@ -150,12 +150,12 @@ class SubmissionAdminAPITest(APITestCase): memory_limit=1000, difficulty=1, hint="hint1", - created_by=User.objects.get(username="test1")) + created_by=self.user) self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1, contest_type=2, show_rank=True, show_user_submission=True, start_time="2015-08-15T10:00:00.000Z", end_time="2015-08-15T12:00:00.000Z", - password="aacc", created_by=User.objects.get(username="test1")) + password="aacc", created_by=self.user) self.submission = Submission.objects.create(user_id=self.user.id, language=1, @@ -166,11 +166,6 @@ class SubmissionAdminAPITest(APITestCase): response = self.client.get(self.url) self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) - def test_submission_successfully(self): - data = {"problem_id": self.problem.id} - response = self.client.get(self.url, data=data) - self.assertEqual(response.data["code"], 0) - class SubmissionPageTest(TestCase): # 单个题目的提交详情页 diff --git a/template/src/oj/submission/my_submissions_list.html b/template/src/oj/submission/my_submissions_list.html index 2ee5b68..4178430 100644 --- a/template/src/oj/submission/my_submissions_list.html +++ b/template/src/oj/submission/my_submissions_list.html @@ -41,7 +41,7 @@ {% for item in submissions %} - + {{ forloop.counter |add:start_id }} {{ item.create_time }} {{ item.result|translate_result }} From 333c4ba24d9cc45832ae6e18fa936e2c01bb1fb8 Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Sun, 30 Aug 2015 12:42:21 +0800 Subject: [PATCH 04/20] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E5=B0=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- template/src/oj_base.html | 2 +- utils/templatetags/problem.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/template/src/oj_base.html b/template/src/oj_base.html index f39fea0..ba001e1 100644 --- a/template/src/oj_base.html +++ b/template/src/oj_base.html @@ -56,7 +56,7 @@ {{ request.user.username }}