Browse Source

BGC-50 @fixed test sur les fichiers importés + ajout test unitaire d'upload

raphael 3 years ago
parent
commit
4dcb7e0cae

+ 0
- 2
Controller/LearningSpace/JupyterVirtualClassroomController.php View File

@@ -112,8 +112,6 @@ class JupyterVirtualClassroomController extends LearningSpaceController
112 112
 	 */
113 113
 	public function sendStudentJupyterNotebook(Request $request,$jupyterVirtualClassroomId,PhoenixServices $service)
114 114
 	{
115
-		ignore_user_abort(true);
116
-		set_time_limit(0);
117 115
 		// uniquement ajax
118 116
 		/*if (!$request->isXmlHttpRequest())
119 117
 		{

+ 26
- 0
Entity/Contraints/JupyterVirtualClassroomConstraint.php View File

@@ -0,0 +1,26 @@
1
+<?php
2
+namespace Logipro\Bundle\PhoenixJupyterBundle\Entity\Contraints;
3
+
4
+use Symfony\Component\Validator\Constraint;
5
+
6
+class JupyterVirtualClassroomConstraint extends Constraint
7
+{
8
+	/**
9
+	 * The validator must be defined as a service with this name.
10
+	 *
11
+	 * @return string
12
+	 */
13
+	public function validatedBy()
14
+	{
15
+		return 'Logipro\Bundle\PhoenixJupyterBundle\Entity\Contraints\JupyterVirtualClassroomValidator';
16
+	}
17
+
18
+	/**
19
+     * {@inheritdoc}
20
+     */
21
+    public function getTargets()
22
+    {
23
+        return self::CLASS_CONSTRAINT;
24
+    }
25
+}
26
+?>

+ 41
- 0
Entity/Contraints/JupyterVirtualClassroomValidator.php View File

@@ -0,0 +1,41 @@
1
+<?php
2
+namespace Logipro\Bundle\PhoenixJupyterBundle\Entity\Contraints;
3
+
4
+use Symfony\Component\Validator\Constraint;
5
+
6
+use Symfony\Component\Validator\ConstraintValidator;
7
+
8
+class JupyterVirtualClassroomValidator extends ConstraintValidator
9
+{
10
+	private $settingsManager = null;
11
+	private $translator = null;
12
+
13
+	public function __construct()
14
+	{
15
+	}
16
+
17
+	public function validate($jupyterVirtualClassroom, Constraint $constraint)
18
+	{
19
+		if ($jupyterVirtualClassroom->getTrainer() && is_null($jupyterVirtualClassroom->getUrl()) ||
20
+		is_null($jupyterVirtualClassroom->getTrainer()) && $jupyterVirtualClassroom->getUrl())
21
+		{
22
+			$this->context->buildViolation($constraint->message)
23
+			->atPath('trainer')
24
+			->setParameter('{{ value }}', $erroMsg)
25
+			->addViolation();
26
+		}
27
+
28
+		// test les champs
29
+
30
+		/*
31
+		$erroMsg = self::renderError($this->translator,$this->settingsManager,$password);
32
+		if ($erroMsg != "")
33
+		{
34
+			$this->context->buildViolation($constraint->message)
35
+			->atPath('password')
36
+			->setParameter('{{ value }}', $erroMsg)
37
+			->addViolation();
38
+		}
39
+		*/
40
+	}
41
+}

+ 6
- 1
Entity/JupyterVirtualClassroom.php View File

@@ -9,6 +9,7 @@ use Logipro\Phoenix\Entity\SequenceItem\ActivityInterface;
9 9
 
10 10
 use Symfony\Component\Validator\Constraints as Assert;
11 11
 use Symfony\Component\Validator\Mapping\ClassMetadata;
12
+use Logipro\Bundle\PhoenixJupyterBundle\Entity\Contraints\JupyterVirtualClassroomConstraint;
12 13
 
13 14
 class JupyterVirtualClassroom extends SequenceItem
14 15
 implements ActivityInterface
@@ -199,9 +200,13 @@ implements ActivityInterface
199 200
 	{
200 201
 		parent::loadValidatorMetadata($metadata);
201 202
 
203
+		$metadata->addConstraint(new JupyterVirtualClassroomConstraint(array(
204
+        )));
205
+
202 206
 		// au moins trois lettres
203 207
 		$metadata->addPropertyConstraint('title', new Assert\Regex([
204
-            'pattern' => '/[a-zA-Z]{3,}/',
208
+			'pattern' => '/[a-zA-Z]{3,}/',
209
+			'message' => 'Le titre doit avoir au moins trois lettres'
205 210
 		]));
206 211
 	}
207 212
 

+ 2
- 0
EntityListener/JupyterEventListener.php View File

@@ -28,6 +28,8 @@ class JupyterEventListener
28 28
 		$jupyterVirtualClassroom = $args->getEntity();
29 29
 		if (is_a($jupyterVirtualClassroom,JupyterVirtualClassroom::class))
30 30
 		{
31
+			ignore_user_abort(true);
32
+			
31 33
 			$trainer = $jupyterVirtualClassroom->getTrainer();
32 34
 
33 35
 			$manager = $args->getEntityManager();

+ 2
- 0
EntityListener/JupyterVirtualClassroomListener.php View File

@@ -26,6 +26,8 @@ class JupyterVirtualClassroomListener
26 26
 	{
27 27
 		if ($this->layer)
28 28
 		{
29
+			ignore_user_abort(true);
30
+			
29 31
 			// supprime le notebook du formateur
30 32
 			$manager = $args->getEntityManager();
31 33
 			$tokenRepository = $manager->getRepository(JupyterToken::class);

+ 15
- 11
Services/PhoenixServices.php View File

@@ -20,6 +20,7 @@ use Logipro\Bundle\PhoenixJupyterBundle\Form\JupyterUpdateType;
20 20
 use Logipro\Phoenix\Entity\Person\Person;
21 21
 use Logipro\Bundle\PhoenixJupyterBundle\Entity\JupyterClassroomRegistration;
22 22
 use Logipro\Bundle\PhoenixJupyterBundle\Services\ApiLayer\ApiLayerService;
23
+use Logipro\Bundle\PhoenixJupyterBundle\Services\Uploader\NotebookUploader;
23 24
 
24 25
 class PhoenixServices extends Services
25 26
 {
@@ -27,11 +28,19 @@ class PhoenixServices extends Services
27 28
 	private $isAvalaible;
28 29
 	private $layoutPath = '@LogiproPhoenixJupyter/back-office/';
29 30
 
30
-	public function __construct(FormFactoryInterface $formFactory,EntityManagerInterface $manager,RouterInterface $router,ApiLayerService $layer)
31
+	public function __construct
32
+	(
33
+		FormFactoryInterface $formFactory,
34
+		EntityManagerInterface $manager,
35
+		RouterInterface $router,
36
+		ApiLayerService $layer,
37
+		NotebookUploader $uploader
38
+	)
31 39
 	{
32 40
 		parent::__construct($formFactory,$manager,$router);
33 41
 
34 42
 		$this->layer = $layer;
43
+		$this->uploader = $uploader;
35 44
 	}
36 45
 
37 46
     /**
@@ -81,6 +90,8 @@ class PhoenixServices extends Services
81 90
      */
82 91
     private function createTrainerJupyterServer(JupyterVirtualClassroom $jupyter,$fromurl = null,$notebookContent = null,$useUrl = true) : string
83 92
 	{
93
+		ignore_user_abort(true);
94
+
84 95
 		// recherche le token du formateur
85 96
 		$trainer = $jupyter->getTrainer();
86 97
 		$repository = $this->getRepository(JupyterToken::class);
@@ -370,17 +381,10 @@ class PhoenixServices extends Services
370 381
 		$uploadedFile = $form['notebook']->getData();
371 382
 		if ($uploadedFile)
372 383
 		{
373
-			$reader = $uploadedFile->openFile();
374
-			if ($uploadedFile && $reader->getSize() > 0)
375
-			{
376
-				$upload = $reader->fread($reader->getSize());
377
-				if ($upload == "")
378
-				{
379
-					$upload = null;
380
-				}
381
-			}
384
+			$upload = $this->uploader->upload($uploadedFile);
382 385
 		}
383
-
386
+		
387
+		
384 388
 		// calcul si le formateur a changé
385 389
 		$currentTrainer = $sequenceItem->getTrainer();
386 390
 		$trainerChanged = $oldTrainer != $currentTrainer;

+ 52
- 0
Services/Uploader/NotebookUploader.php View File

@@ -0,0 +1,52 @@
1
+<?
2
+namespace Logipro\Bundle\PhoenixJupyterBundle\Services\Uploader;
3
+
4
+use Symfony\Component\HttpFoundation\File\UploadedFile;
5
+
6
+class NotebookUploader
7
+{
8
+    public function upload(UploadedFile $uploadedFile)
9
+    {
10
+		// cas d'upload
11
+		if ($uploadedFile)
12
+		{
13
+			$reader = $uploadedFile->openFile();
14
+			// test la taille du fichier
15
+			$size = $reader->getSize();
16
+
17
+			if ($size > max(1,(int)$_SERVER['JUPYTER_UPLOAD_SIZE_MO']) * 1024  * 1024 || $reader->getSize() == 0)
18
+			{
19
+				// erreur
20
+				throw new \Exception("Taille incorrecte");
21
+			}
22
+
23
+			// test l'extension du fichier
24
+			if (!preg_match('/\.ipynb$/',$uploadedFile->getClientOriginalName()))
25
+			{
26
+				// erreur
27
+				throw new \Exception("Extension incorrecte");
28
+			}
29
+
30
+			// test si c'est bien un fichier json
31
+			try
32
+			{
33
+				$upload = $reader->fread($size);
34
+				if ($upload == "")
35
+				{
36
+					throw new \Exception("Notebook invalide");
37
+				}
38
+				// provoque une exception si le fichier est pas en json
39
+				$result = json_decode($upload);
40
+				if (is_null($result))
41
+				{
42
+					throw new \Exception("Notebook invalide");
43
+				}
44
+			}
45
+			catch (\Exception $exp)
46
+			{
47
+				throw new \Exception("Notebook invalide");
48
+			}
49
+		}
50
+        return $upload;
51
+    }
52
+}

+ 4
- 2
Tests/Services/PhoenixServicesTest.php View File

@@ -6,9 +6,9 @@ use PHPUnit\Framework\TestCase;
6 6
 use Symfony\Component\Form\FormFactoryInterface;
7 7
 use Doctrine\ORM\EntityManagerInterface;
8 8
 use Symfony\Component\Routing\RouterInterface;
9
-use Logipro\Bundle\PhoenixJupyterBundle\Repository\JupyterVirtualClassroomRepository;
10 9
 use Logipro\Phoenix\Entity\Person\Person;
11 10
 use Logipro\Bundle\PhoenixJupyterBundle\Services\ApiLayer\ApiLayerService;
11
+use Logipro\Bundle\PhoenixJupyterBundle\Services\Uploader\NotebookUploader;
12 12
 
13 13
 class PhoenixServicesTest extends TestCase
14 14
 {
@@ -37,7 +37,9 @@ class PhoenixServicesTest extends TestCase
37 37
                 ->willReturn(true);
38 38
 		}
39 39
 		
40
-		$service = new PhoenixServicesMock($formFactory,$entityManager,$router,$layerMock);
40
+		$uploaderMock = $this->createMock(NotebookUploader::class);
41
+
42
+		$service = new PhoenixServicesMock($formFactory,$entityManager,$router,$layerMock,$uploaderMock);
41 43
 		return $service;
42 44
 	}
43 45
 

+ 102
- 0
Tests/Services/Uploader/NotebookUploaderTest.php View File

@@ -0,0 +1,102 @@
1
+<?
2
+namespace Logipro\Bundle\PhoenixJupyterBundle\Tests\Services\Uploader;
3
+
4
+use PHPUnit\Framework\TestCase;
5
+
6
+use Symfony\Component\HttpFoundation\File\UploadedFile;
7
+use Logipro\Bundle\PhoenixJupyterBundle\Services\Uploader\NotebookUploader;
8
+
9
+class NotebookUploaderTest extends TestCase
10
+{
11
+	/**
12
+	 * initialise la classe d'upload
13
+	 *
14
+	 * @param integer $size
15
+	 * @param string $name
16
+	 * @param string $content
17
+	 * 
18
+	 * @return UploadedFile
19
+	 */
20
+	private function getUploadedFile($size = 1024,$name = 'undefined.ipynb',$content = '') : UploadedFile
21
+	{
22
+		$reader = $this->getMockBuilder(SplFileObjectMock::class)
23
+			->disableOriginalClone()
24
+			->disableArgumentCloning()
25
+			->disallowMockingUnknownTypes()
26
+			->getMock();
27
+		$reader->method('getSize')->willReturn($size);
28
+		$reader->method('fread')->willReturn($content);
29
+		
30
+		$mock = $this->createMock(UploadedFile::class);
31
+		$mock->method('openFile')->willReturn($reader);
32
+		$mock->method('getClientOriginalName')->willReturn($name);
33
+		
34
+		return $mock;
35
+	}
36
+
37
+	/**
38
+	 * @expectedException \Exception
39
+     */
40
+    public function testuploadSizeMin()
41
+    {
42
+		$uploadedFile = $this->getUploadedFile(0);
43
+
44
+		$uploader = new NotebookUploader();
45
+		$uploader->upload($uploadedFile);
46
+	}
47
+	
48
+	/**
49
+     * @expectedException \Exception
50
+     */
51
+    public function testuploadSizeMax()
52
+    {
53
+		$uploadedFile = $this->getUploadedFile(100000000000000000);
54
+
55
+		$uploader = new NotebookUploader();
56
+		$uploader->upload($uploadedFile);
57
+	}
58
+	
59
+	/**
60
+     * @expectedException \Exception
61
+     */
62
+    public function testuploadExtensionFail()
63
+    {
64
+		$uploadedFile = $this->getUploadedFile(1024,'undefined');
65
+
66
+		$uploader = new NotebookUploader();
67
+		$uploader->upload($uploadedFile);
68
+	}
69
+
70
+	/**
71
+     * @expectedException \Exception
72
+     */
73
+    public function testuploadExtensionTxtFail()
74
+    {
75
+		$uploadedFile = $this->getUploadedFile(1024,'undefined.txt');
76
+
77
+		$uploader = new NotebookUploader();
78
+		$uploader->upload($uploadedFile);
79
+	}
80
+	
81
+	/**
82
+     * @expectedException \Exception
83
+     */
84
+    public function testuploadExtensionJsonEmpty()
85
+    {
86
+		$uploadedFile = $this->getUploadedFile(1024,'undefined.ipynb','');
87
+
88
+		$uploader = new NotebookUploader();
89
+		$uploader->upload($uploadedFile);
90
+	}
91
+
92
+	/**
93
+     * @expectedException \Exception
94
+     */
95
+    public function testuploadExtensionJsonFail()
96
+    {
97
+		$uploadedFile = $this->getUploadedFile(1024,'undefined.ipynb','{"undefined":"unde"');
98
+
99
+		$uploader = new NotebookUploader();
100
+		$uploader->upload($uploadedFile);
101
+	}
102
+}

+ 14
- 0
Tests/Services/Uploader/SplFileObjectMock.php View File

@@ -0,0 +1,14 @@
1
+<?php
2
+namespace Logipro\Bundle\PhoenixJupyterBundle\Tests\Services\Uploader;
3
+
4
+
5
+class SplFileObjectMock 
6
+extends \SplFileObject
7
+{
8
+    public function __construct()
9
+    {
10
+        parent::__construct(__FILE__);
11
+    }
12
+
13
+
14
+}

+ 2
- 1
composer.json View File

@@ -38,7 +38,8 @@
38 38
         "symfony/dom-crawler": "^4.1",
39 39
         "symfony/phpunit-bridge": "^4.1",
40 40
         "symfony/var-dumper": "^4.1",
41
-        "symfony/console": "^4.2"
41
+        "symfony/console": "^4.2",
42
+        "sensio/framework-extra-bundle": "^5.4"
42 43
     },
43 44
     "autoload": {
44 45
         "psr-4": {

Loading…
Cancel
Save