Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR from hotfix/issue-55 to main #64

Merged
merged 6 commits into from
Nov 26, 2022
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions backend/output/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class ResultSerializer(serializers.ModelSerializer):
required=False,
read_only=True,
)
code_description = serializers.CharField(required=False, allow_blank=True)
functionality_result = FunctionalityResultSerializer(read_only=True)
efficiency_result = EfficiencyResultSerializer(read_only=True)
plagiarism_result = PlagiarismResultSerializer(read_only=True)
Expand Down
11 changes: 11 additions & 0 deletions backend/output/test_utils_code_explain.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.test import TestCase
from output.utils_code_explain import run
from output.utils_execution import SUPPORT_LANGUAGE


class Test(TestCase):
Expand All @@ -18,6 +19,16 @@ def solution():
print(ret)
return ret
''',
language='PytHon',
)

self.assertIsNotNone(ret)

def test_run_not_supported_language(self):
languages = list(SUPPORT_LANGUAGE)
languages.remove('python')
languages.append('dummy-data')

for language in languages:
ret = run(raw_code='dummy-code', language=language)
self.assertEqual(ret, str())
23 changes: 19 additions & 4 deletions backend/output/test_utils_execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@ def test_run_unsupported_language(self):
language = 'golang'
run(SERVER_CODE_DIR, language, '', '')

def test_run_when_timeout(self):
raw_code = '''
import time

def solution():
time.sleep(15)
'''
raw_input = '''
3
'''

response = run(SERVER_CODE_DIR, 'python', raw_code, raw_input)

self.assertNotEqual(response.get('exit_status'), 0)

def test_run_python(self):
raw_code = '''
def solution():
Expand All @@ -57,7 +72,7 @@ def solution():
response = run(SERVER_CODE_DIR, 'python', raw_code, raw_input)

self.assertEqual(response.get('exit_status'), 0)
self.assertEqual(response.get('output'), '10.2\n')
self.assertEqual(response.get('output'), '10.2')

def test_run_javascript(self):
raw_code = '''
Expand Down Expand Up @@ -88,7 +103,7 @@ def test_run_javascript(self):
response = run(SERVER_CODE_DIR, 'javascript', raw_code, raw_input)

self.assertEqual(response.get('exit_status'), 0)
self.assertEqual(response.get('output'), '10.2\n')
self.assertEqual(response.get('output'), '10.2')

def test_run_c(self):
raw_code = '''
Expand All @@ -115,7 +130,7 @@ def test_run_c(self):
response = run(SERVER_CODE_DIR, 'c', raw_code, raw_input)

self.assertEqual(response.get('exit_status'), 0)
self.assertEqual(response.get('output'), '10.2\n')
self.assertEqual(response.get('output'), '10.2')

def test_run_cpp(self):
raw_code = '''
Expand Down Expand Up @@ -144,4 +159,4 @@ def test_run_cpp(self):
response = run(SERVER_CODE_DIR, 'cpp', raw_code, raw_input)

self.assertEqual(response.get('exit_status'), 0)
self.assertEqual(response.get('output'), '10.2\n')
self.assertEqual(response.get('output'), '10.2')
5 changes: 3 additions & 2 deletions backend/output/test_utils_functionality.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def solution():
ret += num

print(ret)
print(1.0)
return ret
'''

Expand All @@ -52,13 +53,13 @@ def setUp(self) -> None:
assignment=assignment,
is_hidden=False,
input='3\n1 2 3',
output='6.0'
output='6.00000\n1.000000'
)
testcase_2 = Testcase.objects.create(
assignment=assignment,
is_hidden=True,
input='3\n1.1 2.2 3.3',
output='6.6',
output='6.60000',
)
repo = Repo.objects.create(
assignment=assignment,
Expand Down
16 changes: 16 additions & 0 deletions backend/output/test_utils_plagiarism.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from repo.models import Repo
from output.models import Result
from output.utils_plagiarism import run
from output.utils_execution import SUPPORT_LANGUAGE


class Test(TestCase):
Expand Down Expand Up @@ -80,3 +81,18 @@ def test_generate_plagiarism_result(self):
self.assertEqual(type(plswork.get("similarity_score")), float)
finally:
os.remove(filename)

def test_run_not_supported_language(self):
languages = list(SUPPORT_LANGUAGE)
languages.remove('python')
languages.append('dummy-data')

for language in languages:
ret = run(
result_id=99,
full_filename='dummy-name',
test_dir='dummy-dir-1',
ref_dir='dummy-dir-2',
language=language
)
self.assertIsNone(ret)
10 changes: 10 additions & 0 deletions backend/output/test_utils_readability.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from repo.models import Repo
from output.models import Result
from output.utils_readability import run
from output.utils_execution import SUPPORT_LANGUAGE


class Test(TestCase):
Expand Down Expand Up @@ -77,3 +78,12 @@ def test_readability(self):
self.assertEqual(type(ret.get('mypy_score')), int)
finally:
os.remove(filename)

def test_not_supported_language(self):
languages = list(SUPPORT_LANGUAGE)
languages.remove('python')
languages.append('dummy-data')

for language in languages:
ret = run(result_id=99, full_filename='dummy-name', language=language)
self.assertIsNone(ret)
58 changes: 58 additions & 0 deletions backend/output/test_views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from datetime import timedelta
from unittest.mock import patch
from django.test import TestCase
from django.utils import timezone
from rest_framework.test import APIClient
from authentication.models import User
from lecture.models import Lecture
Expand Down Expand Up @@ -214,6 +217,7 @@ def setUp(self) -> None:
assignment = Assignment.objects.create(
name=self.mock_assignment_name,
lecture=lecture,
deadline=timezone.now() + timedelta(days=1),
)
testcase_1 = Testcase.objects.create(
assignment=assignment,
Expand Down Expand Up @@ -302,6 +306,44 @@ def solution():
self.assertIsNotNone(ret.get('plagiarism_result'))
self.assertIsNotNone(ret.get('readability_result'))

def test_results_create_not_python(self):
student = User.objects.get(oauth_id=self.mock_student_oauth_id)
repo = Repo.objects.first()
data = {
'repo_id': repo.id,
'language': 'cpp',
'code': '''
#include <iostream>

using namespace std;

void solution() {
int size = 0;
cin >> size;

float ret = 0;
while (size--) {
float num = 0;
cin >> num;
ret += num;
}

cout << ret << \'\\n\';
}
''',
}

client = APIClient()
client.force_authenticate(user=student)
response = client.post('/outputs/results/', data=data, format='json')
ret = response.data

self.assertIsNotNone(ret.get('id'))
self.assertIsNotNone(ret.get('functionality_result'))
self.assertIsNone(ret.get('efficiency_result'))
self.assertIsNone(ret.get('plagiarism_result'))
self.assertIsNone(ret.get('readability_result'))

def test_results_create_when_code_is_not_executable(self):
student = User.objects.get(oauth_id=self.mock_student_oauth_id)
repo = Repo.objects.first()
Expand Down Expand Up @@ -376,6 +418,22 @@ def test_result_create_without_auth(self):

self.assertEqual(response.status_code, 401)

@patch('django.utils.timezone.now', return_value=timezone.now() + timedelta(weeks=1))
def test_results_create_when_deadline_exceed(self, mock_now):
student = User.objects.get(oauth_id=self.mock_student_oauth_id)
repo = Repo.objects.first()
data = {
'repo_id': repo.id,
'language': 'python',
'code': 'dummy-code',
}

client = APIClient()
client.force_authenticate(user=student)
response = client.post('/outputs/results/', data=data, format='json')

self.assertEqual(response.status_code, 400)

def test_results_create_when_exceed_possible_attempts(self):
student = User.objects.get(oauth_id=self.mock_student_oauth_id)
repo = Repo.objects.first()
Expand Down
42 changes: 42 additions & 0 deletions backend/output/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import os
import re
import unittest

from uuid import uuid4
from backend.exceptions import InternalServerError
Expand Down Expand Up @@ -26,3 +28,43 @@ def delete_files(full_filenames: [str]):
for full_filename in full_filenames:
if os.path.isfile(full_filename):
os.remove(full_filename)


def string_compare_considered_type(s1: str = '', s2: str = ''):
try:
unittest.TestCase().assertEqual(
decompose_string_by_number(s1),
decompose_string_by_number(s2),
)
return True
except Exception:
return False


def decompose_string_by_number(s: str = ''):
try:
items = re.split(r'[,\s]+', s)
for idx, item in enumerate(items):
items[idx] = type_cast_if_number(item)
return items
except Exception:
return s


def type_cast_if_number(s: str = ''):
try:
return int(s)
except Exception:
pass

try:
return float(s)
except Exception:
pass

try:
return complex(s)
except Exception:
pass

return s
5 changes: 5 additions & 0 deletions backend/output/utils_code_explain.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from openai import Completion

DESCRIPTION_SUPPORT_LANGUAGE = ['python']

ENGINE = 'davinci'
STOP = ["\"\"\""]
TOP_P = 1.0
Expand All @@ -9,6 +11,9 @@


def run(raw_code: str, language: str = 'python'):
if language.lower() not in DESCRIPTION_SUPPORT_LANGUAGE:
return str()

return execute_codex(raw_code)


Expand Down
7 changes: 6 additions & 1 deletion backend/output/utils_efficiency.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@
from output.serializers import EfficiencyResultSerializer
from memory_profiler import memory_usage

EFFICIENCY_SUPPORT_LANGUAGE = ['python']

LOC_FIELD = 'loc_score'
CONTROL_FLOW_COMPLEXITY_FIELD = 'control_flow_complexity_score'
RESERVATION_WORDS_FIELD = 'reservation_words_score'
DATA_FLOW_COMPLEXITY_FIELD = 'data_flow_complexity_score'


def run(result_id: int, full_filename: str):
def run(result_id: int, full_filename: str, language: str = 'python'):
if language.lower() not in EFFICIENCY_SUPPORT_LANGUAGE:
return

multimetric_output = execute_multimetric(full_filename=full_filename)
mem_output = execute_memory_profiler(full_filename=full_filename)

Expand Down
Loading