This is an automated email from the ASF dual-hosted git repository.

yasithdev pushed a commit to branch feat/generic-experiment-launcher
in repository https://gitbox.apache.org/repos/asf/airavata-portals.git

commit 237b4fe7aaa72a1b578953bf27f0117ebcdfc598
Author: yasithdev <[email protected]>
AuthorDate: Fri Apr 24 21:29:11 2026 -0400

    fix(launcher): tighten ExperimentDraftSerializer.validate_inputs + add 
reject tests
---
 .../django_airavata/apps/api/launcher_serializers.py      |  6 +++++-
 .../apps/api/tests/test_launcher_serializers.py           | 15 ++++++++++++++-
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git 
a/airavata-django-portal/django_airavata/apps/api/launcher_serializers.py 
b/airavata-django-portal/django_airavata/apps/api/launcher_serializers.py
index af186fc4d..268e17e55 100644
--- a/airavata-django-portal/django_airavata/apps/api/launcher_serializers.py
+++ b/airavata-django-portal/django_airavata/apps/api/launcher_serializers.py
@@ -35,10 +35,14 @@ class ExperimentDraftSerializer(serializers.Serializer):
     runtime = RuntimeSerializer()
 
     def validate_inputs(self, value):
-        # Each input is either a scalar (str/int/float/bool) or a {storage_id, 
path} object.
+        scalar_types = (str, int, float, bool)
         for name, v in value.items():
             if isinstance(v, dict):
                 StorageRefSerializer(data=v).is_valid(raise_exception=True)
+            elif not isinstance(v, scalar_types):
+                raise serializers.ValidationError(
+                    {name: "input must be a scalar (str/int/float/bool) or a 
{storage_id, path} object"}
+                )
         return value
 
 
diff --git 
a/airavata-django-portal/django_airavata/apps/api/tests/test_launcher_serializers.py
 
b/airavata-django-portal/django_airavata/apps/api/tests/test_launcher_serializers.py
index b1101d277..d7a616a2a 100644
--- 
a/airavata-django-portal/django_airavata/apps/api/tests/test_launcher_serializers.py
+++ 
b/airavata-django-portal/django_airavata/apps/api/tests/test_launcher_serializers.py
@@ -3,11 +3,12 @@ from pathlib import Path
 from unittest import TestCase
 
 import jsonschema
+from django.conf import settings
 
 from django_airavata.apps.api import launcher_serializers
 
 
-CONTRACTS = Path(__file__).resolve().parents[4] / "tests" / "contracts"
+CONTRACTS = Path(settings.BASE_DIR) / "tests" / "contracts"
 
 
 class ExperimentDraftSerializerTest(TestCase):
@@ -52,6 +53,18 @@ class ExperimentDraftSerializerTest(TestCase):
         serializer = launcher_serializers.ExperimentDraftSerializer(data=draft)
         self.assertFalse(serializer.is_valid())
 
+    def test_serializer_rejects_malformed_file_input(self):
+        draft = self._valid_draft()
+        draft["inputs"]["sim_dir"] = {"storage_id": "my-home"}  # missing 
'path'
+        serializer = launcher_serializers.ExperimentDraftSerializer(data=draft)
+        self.assertFalse(serializer.is_valid())
+
+    def test_serializer_rejects_non_scalar_non_dict_input(self):
+        draft = self._valid_draft()
+        draft["inputs"]["steps"] = [1, 2, 3]  # neither scalar nor 
{storage_id, path}
+        serializer = launcher_serializers.ExperimentDraftSerializer(data=draft)
+        self.assertFalse(serializer.is_valid())
+
 
 class PreviewResponseSchemaTest(TestCase):
     def test_valid_response(self):

Reply via email to