Skip to content

Commit

Permalink
Fix segfault detection + refactor tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rw-bsi committed Nov 11, 2024
1 parent dff17f9 commit e26d758
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 149 deletions.
4 changes: 4 additions & 0 deletions backend/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ test-tasks:
. $(VIRTUAL_ENV)/bin/activate && \
MEDIA_ROOT=./apps/ifc_validation/fixtures python3 manage.py test apps.ifc_validation.tests_tasks --settings apps.ifc_validation.test_settings --debug-mode --verbosity 3

test-parse-info-tasks:
. $(VIRTUAL_ENV)/bin/activate && \
MEDIA_ROOT=./apps/ifc_validation/fixtures python3 manage.py test apps.ifc_validation.tests.tests_parse_info_task --settings apps.ifc_validation.test_settings --debug-mode --verbosity 3

clean:
rm -rf .dev
rm -rf django_db.sqlite3
Expand Down
2 changes: 1 addition & 1 deletion backend/apps/ifc_validation/checks/ifc_gherkin_rules
Submodule ifc_gherkin_rules updated 0 files
9 changes: 6 additions & 3 deletions backend/apps/ifc_validation/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,16 +330,19 @@ def parse_info_subtask(self, prev_result, id, file_name, *args, **kwargs):

task.mark_as_initiated()

# try to open IFC file (catch segfaults)
# try to open IFC file (only catch segfaults)
SEGFAULT_PROCESS_RETURNCODE = -11
try:
code = "import ifcopenshell; ifcopenshell.open('" + file_path + "')"
check_program = [sys.executable, '-c', code, file_path]
logger.debug(f'Command for {self.__qualname__}: {" ".join(check_program)}')
subprocess.run(check_program, check=True)

except subprocess.CalledProcessError as err:
task.mark_as_failed(err)
raise

if err.returncode == SEGFAULT_PROCESS_RETURNCODE:
task.mark_as_failed(err)
raise

# retrieve IFC info
try:
Expand Down
167 changes: 167 additions & 0 deletions backend/apps/ifc_validation/tests/tests_parse_info_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import datetime

from django.test import TestCase
from django.contrib.auth.models import User

from apps.ifc_validation_models.models import *
from apps.ifc_validation_models.decorators import requires_django_user_context

from ..tasks import parse_info_subtask

class ParseInfoTasksTestCase(TestCase):

@classmethod
def setUpTestData(cls):

"""
Creates a SYSTEM user in the (in-memory) test database.
Runs once for the whole test case.
"""

user = User.objects.create(id=1, username='SYSTEM', is_active=True)
user.save()

@requires_django_user_context
def test_parse_info_task_valid_file_does_not_create_validation_outcome(self):

request = ValidationRequest.objects.create(
file_name='valid_file.ifc',
file='valid_file.ifc',
size=280
)
request.mark_as_initiated()

parse_info_subtask(
prev_result={'is_valid': True, 'reason': 'test'},
id=request.id,
file_name=request.file_name
)

outcomes = ValidationOutcome.objects.all()
self.assertIsNotNone(outcomes)
self.assertEqual(len(outcomes), 0)

@requires_django_user_context
def test_parse_info_task_invalid_version_does_not_create_validation_outcome(self):

request = ValidationRequest.objects.create(
file_name='invalid_version.ifc',
file='invalid_version.ifc',
size=281
)
request.mark_as_initiated()

parse_info_subtask(
prev_result={'is_valid': True, 'reason': 'test'},
id=request.id,
file_name=request.file_name
)

outcomes = ValidationOutcome.objects.all()
self.assertIsNotNone(outcomes)
self.assertEqual(len(outcomes), 0)

@requires_django_user_context
def test_parse_info_task_correctly_parses_properties(self):

request = ValidationRequest.objects.create(
file_name='wall-with-opening-and-window.ifc',
file='wall-with-opening-and-window.ifc',
size=1
)
request.mark_as_initiated()

parse_info_subtask(
prev_result={'is_valid': True, 'reason': 'test'},
id=request.id,
file_name=request.file_name
)

model = Model.objects.all().first()
self.assertIsNotNone(model)
self.assertEqual(model.mvd, 'CoordinationView')
self.assertEqual(model.schema, 'IFC4')
self.assertEqual(model.number_of_elements, 2)
self.assertEqual(model.number_of_geometries, 4)
self.assertEqual(model.number_of_properties, 19)

@requires_django_user_context
def test_parse_info_task_correctly_parses_date(self):

request = ValidationRequest.objects.create(
file_name='pass_reverse_comment.ifc',
file='pass_reverse_comment.ifc',
size=1
)
request.mark_as_initiated()

parse_info_subtask(
prev_result={'is_valid': True, 'reason': 'test'},
id=request.id,
file_name=request.file_name
)

model = Model.objects.all().first()
self.assertIsNotNone(model)
self.assertEqual(model.date, datetime.datetime(2022, 5, 4, 8, 8, 30, tzinfo=datetime.timezone.utc))

@requires_django_user_context
def test_parse_info_task_correctly_parses_date_with_timezone(self):

request = ValidationRequest.objects.create(
file_name='valid_file_with_tz.ifc',
file='valid_file_with_tz.ifc',
size=1
)
request.mark_as_initiated()

parse_info_subtask(
prev_result={'is_valid': True, 'reason': 'test'},
id=request.id,
file_name=request.file_name
)

model = Model.objects.all().first()
self.assertIsNotNone(model)
self.assertEqual(model.date, datetime.datetime(2023, 12, 16, 16, 20, 00, tzinfo=datetime.timezone.utc))

@requires_django_user_context
def test_parse_info_task_correctly_parses_authoring_tool(self):

request = ValidationRequest.objects.create(
file_name='pass_reverse_comment.ifc',
file='pass_reverse_comment.ifc',
size=1
)
request.mark_as_initiated()

parse_info_subtask(
prev_result={'is_valid': True, 'reason': 'test'},
id=request.id,
file_name=request.file_name
)

model = Model.objects.all().first()
self.assertIsNotNone(model)
self.assertEquals('IfcOpenShell-0.7.0', model.produced_by.name)
self.assertEquals('0.7.0', model.produced_by.version)

@requires_django_user_context
def test_parse_info_task_correctly_parses_missing_authoring_tool(self):

request = ValidationRequest.objects.create(
file_name='valid_file.ifc',
file='valid_file.ifc',
size=1
)
request.mark_as_initiated()

parse_info_subtask(
prev_result={'is_valid': True, 'reason': 'test'},
id=request.id,
file_name=request.file_name
)

model = Model.objects.all().first()
self.assertIsNotNone(model)
self.assertIsNone(model.produced_by)
145 changes: 0 additions & 145 deletions backend/apps/ifc_validation/tests_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,151 +71,6 @@ def test_syntax_validation_task_creates_error_validation_outcome(self):
self.assertEqual(outcomes.first().outcome_code, ValidationOutcome.ValidationOutcomeCode.SYNTAX_ERROR)
self.assertTrue('On line 1 column 1' in outcomes.first().observed)

@requires_django_user_context
def test_parse_info_task_does_not_create_validation_outcome(self):

request = ValidationRequest.objects.create(
file_name='valid_file.ifc',
file='valid_file.ifc',
size=280
)
request.mark_as_initiated()

parse_info_subtask(
prev_result={'is_valid': True, 'reason': 'test'},
id=request.id,
file_name=request.file_name
)

outcomes = ValidationOutcome.objects.all()
self.assertIsNotNone(outcomes)
self.assertEqual(len(outcomes), 0)

@requires_django_user_context
def test_parse_info_task_does_not_create_validation_outcome_2(self):

request = ValidationRequest.objects.create(
file_name='invalid_version.ifc',
file='invalid_version.ifc',
size=281
)
request.mark_as_initiated()

parse_info_subtask(
prev_result={'is_valid': True, 'reason': 'test'},
id=request.id,
file_name=request.file_name
)

outcomes = ValidationOutcome.objects.all()
self.assertIsNotNone(outcomes)
self.assertEqual(len(outcomes), 0)

@requires_django_user_context
def test_parse_info_task_parses_properties(self):

request = ValidationRequest.objects.create(
file_name='wall-with-opening-and-window.ifc',
file='wall-with-opening-and-window.ifc',
size=1
)
request.mark_as_initiated()

parse_info_subtask(
prev_result={'is_valid': True, 'reason': 'test'},
id=request.id,
file_name=request.file_name
)

model = Model.objects.all().first()
self.assertIsNotNone(model)
self.assertEqual(model.mvd, 'CoordinationView')
self.assertEqual(model.schema, 'IFC4')
self.assertEqual(model.number_of_elements, 2)
self.assertEqual(model.number_of_geometries, 4)
self.assertEqual(model.number_of_properties, 19)

@requires_django_user_context
def test_parse_info_task_parses_date(self):

request = ValidationRequest.objects.create(
file_name='pass_reverse_comment.ifc',
file='pass_reverse_comment.ifc',
size=1
)
request.mark_as_initiated()

parse_info_subtask(
prev_result={'is_valid': True, 'reason': 'test'},
id=request.id,
file_name=request.file_name
)

model = Model.objects.all().first()
self.assertIsNotNone(model)
self.assertEqual(model.date, datetime.datetime(2022, 5, 4, 8, 8, 30, tzinfo=datetime.timezone.utc))

@requires_django_user_context
def test_parse_info_task_parses_date_with_timezone(self):

request = ValidationRequest.objects.create(
file_name='valid_file_with_tz.ifc',
file='valid_file_with_tz.ifc',
size=1
)
request.mark_as_initiated()

parse_info_subtask(
prev_result={'is_valid': True, 'reason': 'test'},
id=request.id,
file_name=request.file_name
)

model = Model.objects.all().first()
self.assertIsNotNone(model)
self.assertEqual(model.date, datetime.datetime(2023, 12, 16, 16, 20, 00, tzinfo=datetime.timezone.utc))

@requires_django_user_context
def test_parse_info_task_parses_authoring_tool(self):

request = ValidationRequest.objects.create(
file_name='pass_reverse_comment.ifc',
file='pass_reverse_comment.ifc',
size=1
)
request.mark_as_initiated()

parse_info_subtask(
prev_result={'is_valid': True, 'reason': 'test'},
id=request.id,
file_name=request.file_name
)

model = Model.objects.all().first()
self.assertIsNotNone(model)
self.assertEquals('IfcOpenShell-0.7.0', model.produced_by.name)
self.assertEquals('0.7.0', model.produced_by.version)

@requires_django_user_context
def test_parse_info_task_parses_no_authoring_tool(self):

request = ValidationRequest.objects.create(
file_name='valid_file.ifc',
file='valid_file.ifc',
size=1
)
request.mark_as_initiated()

parse_info_subtask(
prev_result={'is_valid': True, 'reason': 'test'},
id=request.id,
file_name=request.file_name
)

model = Model.objects.all().first()
self.assertIsNotNone(model)
self.assertIsNone(model.produced_by)

@requires_django_user_context
def test_schema_validation_task_creates_passed_validation_outcome(self):

Expand Down

0 comments on commit e26d758

Please sign in to comment.