This repository has been archived by the owner on Sep 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #109 from SELab-2/simple_tests
Simple tests
- Loading branch information
Showing
19 changed files
with
1,185 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
backend/domain/simple_submission_checks/constraints/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from domain.simple_submission_checks.constraints.directory_constraint import DirectoryConstraint | ||
from domain.simple_submission_checks.constraints.only_present_constraint import OnlyPresentConstraint | ||
|
||
DirectoryConstraint.update_forward_refs() | ||
OnlyPresentConstraint.update_forward_refs() |
59 changes: 59 additions & 0 deletions
59
backend/domain/simple_submission_checks/constraints/constraint_result.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
from __future__ import annotations | ||
|
||
from enum import Enum | ||
|
||
from pydantic import BaseModel | ||
|
||
|
||
class ConstraintType(Enum): | ||
FILE = "FILE" | ||
NOT_PRESENT = "NOT_PRESENT" | ||
DIRECTORY = "DIRECTORY" | ||
ONLY_PRESENT = "ONLY_PRESENT" | ||
ZIP = "ZIP" | ||
SUBMISSION = "SUBMISSION" | ||
|
||
|
||
class ConstraintResult(BaseModel): | ||
type: ConstraintType | ||
name: str | ||
is_ok: bool | ||
sub_constraint_results: list = [] | ||
|
||
def __str__(self, level: int = 0): | ||
status = "\u2714 [OK] " if self.is_ok else "\u2718 [FAIL]" | ||
ret = f"{'\t' * level}{status} {self.type.name}: {self.name}" | ||
if self.sub_constraint_results: | ||
sub_results_str = "\n".join(sub_result.__str__(level + 1) for sub_result in self.sub_constraint_results) | ||
ret += "\n" + sub_results_str | ||
return ret | ||
|
||
|
||
class FileConstraintResult(ConstraintResult): | ||
type: ConstraintType = ConstraintType.FILE | ||
|
||
|
||
class NotPresentConstraintResult(ConstraintResult): | ||
type: ConstraintType = ConstraintType.NOT_PRESENT | ||
|
||
|
||
class DirectoryConstraintResult(ConstraintResult): | ||
type: ConstraintType = ConstraintType.DIRECTORY | ||
sub_constraint_results: list[ConstraintResult] | ||
|
||
|
||
class OnlyPresentConstraintResult(ConstraintResult): | ||
type: ConstraintType = ConstraintType.ONLY_PRESENT | ||
sub_constraint_results: list[ConstraintResult] | ||
should_be_in_but_are_not: list[str] | ||
should_not_be_in_but_are: list[str] | ||
|
||
|
||
class ZipConstraintResult(ConstraintResult): | ||
type: ConstraintType = ConstraintType.ZIP | ||
sub_constraint_results: list[ConstraintResult] | ||
|
||
|
||
class SubmissionConstraintResult(ConstraintResult): | ||
type: ConstraintType = ConstraintType.SUBMISSION | ||
sub_constraint_results: list[ConstraintResult] |
31 changes: 31 additions & 0 deletions
31
backend/domain/simple_submission_checks/constraints/directory_constraint.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
from __future__ import annotations | ||
|
||
from pathlib import Path | ||
from typing import TYPE_CHECKING, Literal | ||
|
||
from pydantic import BaseModel | ||
|
||
from domain.simple_submission_checks.constraints.constraint_result import ( | ||
ConstraintResult, | ||
DirectoryConstraintResult, | ||
) | ||
from domain.simple_submission_checks.constraints.file_constraint import FileConstraint | ||
from domain.simple_submission_checks.constraints.not_present_constraint import NotPresentConstraint | ||
|
||
if TYPE_CHECKING: | ||
from domain.simple_submission_checks.constraints.only_present_constraint import OnlyPresentConstraint | ||
|
||
|
||
class DirectoryConstraint(BaseModel): | ||
type: Literal["directory_constraint"] = "directory_constraint" | ||
name: str | ||
sub_constraints: list[FileConstraint | NotPresentConstraint | OnlyPresentConstraint | DirectoryConstraint] | ||
|
||
def validate_constraint(self, path: Path) -> ConstraintResult: | ||
dir_path = path/self.name | ||
if not Path.is_dir(dir_path): | ||
return DirectoryConstraintResult(name=self.name, is_ok=False, sub_constraint_results=[]) | ||
|
||
sub_results: list[ConstraintResult] | ||
sub_results = [constraint.validate_constraint(dir_path) for constraint in self.sub_constraints] | ||
return DirectoryConstraintResult(name=self.name, is_ok=True, sub_constraint_results=sub_results) |
21 changes: 21 additions & 0 deletions
21
backend/domain/simple_submission_checks/constraints/file_constraint.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import os | ||
from pathlib import Path | ||
from typing import Literal | ||
|
||
from pydantic import BaseModel | ||
|
||
from domain.simple_submission_checks.constraints.constraint_result import FileConstraintResult | ||
|
||
|
||
class FileConstraint(BaseModel): | ||
type: Literal["file_constraint"] = "file_constraint" | ||
sub_constraints: list = [] | ||
name: str | ||
|
||
def validate_constraint(self, path: Path) -> FileConstraintResult: | ||
directory = os.listdir(path) | ||
|
||
if self.name not in directory: | ||
return FileConstraintResult(name=self.name, is_ok=False, sub_constraint_results=[]) | ||
|
||
return FileConstraintResult(name=self.name, is_ok=True, sub_constraint_results=[]) |
21 changes: 21 additions & 0 deletions
21
backend/domain/simple_submission_checks/constraints/not_present_constraint.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import os | ||
from pathlib import Path | ||
from typing import Literal | ||
|
||
from pydantic import BaseModel | ||
|
||
from domain.simple_submission_checks.constraints.constraint_result import ConstraintResult, NotPresentConstraintResult | ||
|
||
|
||
class NotPresentConstraint(BaseModel): | ||
type: Literal["not_present_constraint"] = "not_present_constraint" | ||
sub_constraints: list = [] | ||
name: str | ||
|
||
def validate_constraint(self, path: Path) -> ConstraintResult: | ||
directory = os.listdir(path) | ||
|
||
if self.name in directory: | ||
return NotPresentConstraintResult(name=self.name, is_ok=False, sub_constraint_results=[]) | ||
|
||
return NotPresentConstraintResult(name=self.name, is_ok=True, sub_constraint_results=[]) |
59 changes: 59 additions & 0 deletions
59
backend/domain/simple_submission_checks/constraints/only_present_constraint.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
from __future__ import annotations | ||
|
||
import os | ||
from pathlib import Path | ||
from typing import Literal | ||
|
||
from pydantic import BaseModel | ||
|
||
from domain.simple_submission_checks.constraints.constraint_result import ( | ||
ConstraintResult, | ||
DirectoryConstraintResult, | ||
OnlyPresentConstraintResult, | ||
) | ||
from domain.simple_submission_checks.constraints.directory_constraint import DirectoryConstraint | ||
from domain.simple_submission_checks.constraints.file_constraint import FileConstraint | ||
|
||
|
||
class OnlyPresentConstraint(BaseModel): | ||
type: Literal["only_present_directory_constraint"] = "only_present_directory_constraint" | ||
name: str | ||
# NotPresentConstraint is not possible | ||
sub_constraints: list[OnlyPresentConstraint | DirectoryConstraint | FileConstraint] | ||
|
||
def validate_constraint(self, path: Path) -> ConstraintResult: | ||
dir_path = path / self.name | ||
if not Path.is_dir(dir_path): | ||
return DirectoryConstraintResult( | ||
name=self.name, | ||
is_ok=False, | ||
sub_constraint_results=[], | ||
) | ||
|
||
# Only the files specified should be present | ||
names_sub_constraints = {sub_constraint.name for sub_constraint in self.sub_constraints} # Specified files. | ||
names_of_folder = set(os.listdir(dir_path)) # present files. | ||
|
||
if names_sub_constraints != names_of_folder: # Contents should match exactly. | ||
return OnlyPresentConstraintResult( | ||
name=self.name, | ||
is_ok=False, | ||
should_be_in_but_are_not=list(names_sub_constraints - names_of_folder), | ||
should_not_be_in_but_are=list(names_of_folder - names_sub_constraints), | ||
sub_constraint_results=[], | ||
) | ||
|
||
sub_results: list[ConstraintResult] | ||
sub_results = [constraint.validate_constraint(dir_path) for constraint in self.sub_constraints] | ||
|
||
return OnlyPresentConstraintResult( | ||
name=self.name, | ||
is_ok=True, | ||
should_be_in_but_are_not=[], | ||
should_not_be_in_but_are=[], | ||
sub_constraint_results=sub_results, | ||
) | ||
|
||
|
||
# Needed to enable self-referencing model | ||
OnlyPresentConstraint.model_rebuild() |
16 changes: 16 additions & 0 deletions
16
backend/domain/simple_submission_checks/constraints/submission_constraint.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
from pathlib import Path | ||
from typing import Literal | ||
|
||
from pydantic import BaseModel | ||
|
||
from domain.simple_submission_checks.constraints.constraint_result import ConstraintResult | ||
from domain.simple_submission_checks.constraints.file_constraint import FileConstraint | ||
from domain.simple_submission_checks.constraints.zip_constraint import ZipConstraint | ||
|
||
|
||
class SubmissionConstraint(BaseModel): | ||
type: Literal["submission_constraint"] = "submission_constraint" | ||
root_constraint: ZipConstraint | FileConstraint # Submission can be a file or a zip. | ||
|
||
def validate_constraint(self, path: Path) -> ConstraintResult: | ||
return self.root_constraint.validate_constraint(path) |
37 changes: 37 additions & 0 deletions
37
backend/domain/simple_submission_checks/constraints/zip_constraint.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import os | ||
import tempfile | ||
import zipfile | ||
from pathlib import Path | ||
from typing import Literal | ||
|
||
from pydantic import BaseModel | ||
|
||
from domain.simple_submission_checks.constraints.constraint_result import ConstraintResult, ZipConstraintResult | ||
from domain.simple_submission_checks.constraints.directory_constraint import DirectoryConstraint | ||
from domain.simple_submission_checks.constraints.file_constraint import FileConstraint | ||
from domain.simple_submission_checks.constraints.not_present_constraint import NotPresentConstraint | ||
from domain.simple_submission_checks.constraints.only_present_constraint import OnlyPresentConstraint | ||
|
||
|
||
class ZipConstraint(BaseModel): | ||
type: Literal["zip_constraint"] = "zip_constraint" | ||
name: str | ||
sub_constraints: list[DirectoryConstraint | FileConstraint | NotPresentConstraint | OnlyPresentConstraint] | ||
|
||
def validate_constraint(self, path: Path) -> ConstraintResult: | ||
directory = os.listdir(path) | ||
|
||
# Check if file is present. | ||
if self.name not in directory: | ||
return ZipConstraintResult(name=self.name, is_ok=False, sub_constraint_results=[]) | ||
|
||
# Check if file is a zip file. | ||
zip_path = path / self.name | ||
if not zipfile.is_zipfile(zip_path): | ||
return ZipConstraintResult(name=self.name, is_ok=False) | ||
|
||
# Extract file into a Temp directory and validate sub constraints. | ||
with tempfile.TemporaryDirectory() as tmp_dir, zipfile.ZipFile(zip_path, "r") as zip_ref: | ||
zip_ref.extractall(tmp_dir) | ||
sub_constraints = [constraint.validate_constraint(Path(tmp_dir)) for constraint in self.sub_constraints] | ||
return ZipConstraintResult(name=self.name, is_ok=True, sub_constraint_results=sub_constraints) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.