Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
10c1a90
set version to 2026.0.0-rc1
Irakus Feb 23, 2026
0c1a95c
[CI/CD] Update DLSPS updates workflow to handle RC versions (#1072)
dmytroye Feb 23, 2026
f7f8090
ITEP-87641 Added OpenAPI validation to tests (#1071)
Irakus Feb 23, 2026
d2c9a3a
Refactor camera bounds visibility tests (#1075)
sbelhaik Feb 24, 2026
e7dd3a5
[DLStreamer] Update to 2026.0.0-ubuntu24-rc1 (#1078)
scenescapecicd Feb 24, 2026
ed6ecb4
pgserver healthcheck + ui log location + move broken tests (#1080)
dpitulax Feb 24, 2026
8488fd6
[DOCS] Mapping Service - pre-publish reorganisation and microservices…
wiwaszko-intel Feb 25, 2026
a185b62
Restore out-of-box tests (#1082)
dpitulax Feb 25, 2026
15a5367
rework api - new footers, add fixtures
dpitulax Feb 25, 2026
389f0c1
Merge branch 'main' into dpitulax-api_tests_rework
dpitulax Feb 25, 2026
f414174
restore old secrets
dpitulax Feb 26, 2026
15454e4
Merge branch 'main' into dpitulax-api_tests_rework
dpitulax Feb 27, 2026
9c90758
Merge branch 'main' into dpitulax-api_tests_rework
dpitulax Feb 27, 2026
97ea879
Merge branch 'main' into dpitulax-api_tests_rework
dpitulax Mar 3, 2026
8ecf091
Merge branch 'main' into dpitulax-api_tests_rework
Irakus Mar 10, 2026
e5e90b1
Merge branch 'main' into dpitulax-api_tests_rework
Irakus Mar 11, 2026
68b7429
Merge branch 'main' into dpitulax-api_tests_rework
Irakus Mar 11, 2026
a869a45
Merge branch 'main' into dpitulax-api_tests_rework
dpitulax Mar 12, 2026
28b3f59
Merge branch 'main' into dpitulax-api_tests_rework
Irakus Mar 16, 2026
d866603
Merge branch 'main' into dpitulax-api_tests_rework
Irakus Mar 17, 2026
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
6 changes: 5 additions & 1 deletion controller/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import pytest
import sys
from pathlib import Path
import numpy as np

# Add controller/src to path FIRST so controller module imports work correctly
controller_src = Path(__file__).resolve().parents[1] / 'src'
Expand All @@ -19,6 +18,11 @@

from controller.controller_mode import ControllerMode

def pytest_report_teststatus(report, config):
if report.when == "call":
# Disable default "PASSED"
return report.outcome, "", ""

def pytest_addoption(parser):
parser.addoption("--user", required=True, help="user to log into REST server")
parser.addoption("--password", required=True, help="password to log into REST server")
Expand Down
3 changes: 2 additions & 1 deletion controller/tests/tc_scene_import_json.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python3

# SPDX-FileCopyrightText: (C) 2025 Intel Corporation
# SPDX-FileCopyrightText: (C) 2025-2026 Intel Corporation
# SPDX-License-Identifier: Apache-2.0

import os
Expand Down Expand Up @@ -86,6 +86,7 @@ def runTest(self):

finally:
self.pubsub.loopStop()
self.recordTestResult()

return self.exitCode

Expand Down
55 changes: 51 additions & 4 deletions manager/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
#!/usr/bin/env python3

# SPDX-FileCopyrightText: (C) 2022 - 2026 Intel Corporation
# SPDX-License-Identifier: Apache-2.0

import os
import pytest
import sys
from pathlib import Path
import numpy as np
from scene_common.rest_client import RESTClient

repo_root=Path(__file__).resolve().parents[2]
sys.path.insert(0, str(repo_root))

from tests.common_test_utils import record_test_result

def pytest_report_teststatus(report, config):
if report.when == "call":
# Disable default "PASSED"
return report.outcome, "", ""

def pytest_addoption(parser):
parser.addoption("--user", required=True, help="user to log into REST server")
parser.addoption("--password", required=True, help="password to log into REST server")
Expand All @@ -29,7 +35,7 @@ def pytest_addoption(parser):
parser.addoption("--scene_name", default="Demo",
help="name of scene to test against")

@pytest.fixture
@pytest.fixture(scope="session")
def params(request):
return {
'user': request.config.getoption('--user'),
Expand All @@ -50,4 +56,45 @@ def params(request):
@pytest.hookimpl(tryfirst=True)
def pytest_configure(config):
file_name = Path(config.option.file_or_dir[0]).stem
config.option.htmlpath = os.getcwd() + '/tests/functional/reports/test_reports/' + file_name + ".html"
config.option.htmlpath = os.getcwd() + '/tests/reports/test_reports/' + file_name + ".html"
# Register marker for test names
config.addinivalue_line("markers", "test_name(name): sets the XML test name attribute")

@pytest.fixture(scope="session")
def rest(params):
client = RESTClient(params['resturl'], rootcert=params['rootcert'])
assert client.authenticate(params['user'], params['password'])
return client

@pytest.fixture
def scene_uid(rest, params):
name = params['scene_name']
res = rest.getScenes({'name': name})
scenes = res.get('results', []) if isinstance(res, dict) else []
assert scenes, f"Scene '{name}' not found"
return scenes[0]['uid']

@pytest.fixture(autouse=True)
def record_test_name(request, record_xml_attribute):
"""Record test name from marker if provided; otherwise do nothing."""
marker = request.node.get_closest_marker("test_name")
if marker and marker.args:
record_xml_attribute("name", marker.args[0])

@pytest.fixture
def result_recorder(request):
"""Provides .success(); records exit code with test name on teardown."""
marker = request.node.get_closest_marker("test_name")
test_name = (marker.args[0] if marker and marker.args
else getattr(request.node.module, "TEST_NAME", request.node.name))

class Result:
exit_code = 1
def success(self):
self.exit_code = 0

r = Result()
try:
yield r
finally:
record_test_result(test_name, r.exit_code)
5 changes: 5 additions & 0 deletions manager/tests/pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@
addopts = -v --capture sys -rF -rP --user=admin --tb=short
junit_suite_name = functional
pythonpath = /home/scenescape/SceneScape/tools:/home/scenescape/SceneScape/controller

log_cli = true
log_cli_level = INFO
log_format = %(asctime)s %(levelname)s %(name)s:%(filename)s:%(lineno)d %(message)s
log_date_format = %Y-%m-%d %H:%M:%S
64 changes: 25 additions & 39 deletions manager/tests/tc_add_delete_3d_object_api.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,33 @@
#!/usr/bin/env python3

# SPDX-FileCopyrightText: (C) 2025 Intel Corporation
# SPDX-FileCopyrightText: (C) 2025-2026 Intel Corporation
# SPDX-License-Identifier: Apache-2.0

from tests.functional import FunctionalTest
from http import HTTPStatus
from scene_common.rest_client import RESTClient
import logging

TEST_NAME = "NEX-T10428-API"

class AddDelete3DObjectTest(FunctionalTest):
def __init__(self, testName, request, recordXMLAttribute):
super().__init__(testName, request, recordXMLAttribute)
self.rest = RESTClient(self.params['resturl'], rootcert=self.params['rootcert'])
assert self.rest.authenticate(self.params['user'], self.params['password'])


def runTest(self):
object_name = "3D Object"
file_path = "/workspace/tests/ui/test_media/box.glb"

# Create a 3d asset
with open(file_path, "rb") as f:
asset_data = {
"name": object_name,
"model_3d": f
}
res = self.rest.createAsset(asset_data)
assert res.statusCode in (HTTPStatus.OK, HTTPStatus.CREATED), f"Failed to create asset: {res.errors}"
asset_uid = res['uid']
assert asset_uid, "Asset UID not returned"

print("3D object (asset) created successfully.")

# Delete the asset
res = self.rest.deleteAsset(asset_uid)
assert res.statusCode == HTTPStatus.OK, f"Failed to delete asset: {res.errors}"

print("3D object (asset) deleted successfully.")
return True


def test_add_delete_3d_object_api(request, record_xml_attribute):
test = AddDelete3DObjectTest(TEST_NAME, request, record_xml_attribute)
assert test.runTest()
return
def test_add_delete_3d_object_api(rest, result_recorder):
object_name = "3D Object"
file_path = "/workspace/tests/ui/test_media/box.glb"

# Create a 3d asset
with open(file_path, "rb") as f:
asset_data = {
"name": object_name,
"model_3d": f
}
res = rest.createAsset(asset_data)
assert res.statusCode in (HTTPStatus.OK, HTTPStatus.CREATED), f"Failed to create asset: {res.errors}"
asset_uid = res['uid']
assert asset_uid, "Asset UID not returned"

logging.info("3D object (asset) created successfully.")

# Delete the asset
res = rest.deleteAsset(asset_uid)
assert res.statusCode == HTTPStatus.OK, f"Failed to delete asset: {res.errors}"
logging.info("3D object (asset) deleted successfully.")

result_recorder.success()
122 changes: 55 additions & 67 deletions manager/tests/tc_api_large_strings.py
Original file line number Diff line number Diff line change
@@ -1,74 +1,62 @@
#!/usr/bin/env python3

# SPDX-FileCopyrightText: (C) 2024 - 2025 Intel Corporation
# SPDX-FileCopyrightText: (C) 2024 - 2026 Intel Corporation
# SPDX-License-Identifier: Apache-2.0

from tests.functional import FunctionalTest
from scene_common.rest_client import RESTClient
import os
import random
import string
import logging

TEST_NAME = 'NEX-T10583'

class APIStrings(FunctionalTest):
def __init__(self, testName, request, recordXMLAttribute):
super().__init__(testName, request, recordXMLAttribute)
self.sceneName = self.params['scene']
self.sceneID = None
self.rest = RESTClient(self.params['resturl'], rootcert=self.params['rootcert'])
res = self.rest.authenticate(self.params['user'], self.params['password'])
assert res, (res.errors)
return

def generate_string(self, length=256):
characters = string.ascii_letters + string.digits + string.punctuation
return ''.join(random.choice(characters) for _ in range(length))

def runApiStrings(self):
self.exitCode = 1
self.getScene()
random_string = self.generate_string()
res = self.rest.authenticate(self.params['user'], random_string)
assert res.errors['password'] == ['Ensure this field has no more than 150 characters.']
res = self.rest.authenticate(random_string, self.params['user'])
# Removed print statement to avoid exposing sensitive information.
assert res.errors['username'] == ['Ensure this field has no more than 150 characters.']
res = self.rest.authenticate('admin123', 'admin123')
print(res.errors['non_field_errors'])
assert res.errors['non_field_errors'] == ['Incorrect Username/Password. ']
assert res.statusCode == 400
res = self.rest.authenticate(self.params['user'], self.params['password'])
res = self.rest.createTripwire({"name": random_string, "scene": self.sceneID})
print(res.errors['name'])
assert res.errors['name'] == ['Ensure this field has no more than 150 characters.']
res = self.rest.createRegion({"name": random_string, "scene": self.sceneID})
print(res.errors['name'])
assert res.errors['name'] == ['Ensure this field has no more than 150 characters.']
res = self.rest.createSensor({"name": random_string, "scene": self.sceneID})
print(res.errors['name'])
assert res.errors['name'] == ['Ensure this field has no more than 150 characters.']
res = self.rest.createCamera({"name": random_string, "scene": self.sceneID})
print(res.errors['name'])
assert res.errors['name'] == ['Ensure this field has no more than 150 characters.']
res = self.rest.createScene({"name": random_string})
print(res.errors['name'])
assert res.errors['name'] == ['Ensure this field has no more than 150 characters.']
res = self.rest.createSensor({"sensor_id": random_string, "scene": self.sceneID})
print(res.errors['sensor_id'])
assert res.errors['sensor_id'] == ['Ensure this field has no more than 20 characters.']
self.exitCode = 0
self.recordTestResult()
return

def test_api_strings(request, record_xml_attribute):
test = APIStrings(TEST_NAME, request, record_xml_attribute)
test.runApiStrings()
assert test.exitCode == 0
return

def main():
return test_api_strings(None, None)

if __name__ == '__main__':
os._exit(main() or 0)
TEST_NAME = "NEX-T10583"

def _generate_string(length: int = 256) -> str:
# Generate a random string of specified length to trigger max-length validation.
characters = string.ascii_letters + string.digits + string.punctuation
return "".join(random.choice(characters) for _ in range(length))

def test_api_strings(rest, result_recorder, scene_uid, params):
random_string = _generate_string(256)

# Authentication length validations
res = rest.authenticate(params["user"], random_string)
assert res.errors["password"] == ["Ensure this field has no more than 150 characters."]

res = rest.authenticate(random_string, params["user"])
assert res.errors["username"] == ["Ensure this field has no more than 150 characters."]

# Negative auth with bad creds
res = rest.authenticate("admin123", "admin123")
logging.info(res.errors["non_field_errors"])
assert res.errors["non_field_errors"] == ["Incorrect Username/Password. "]
assert res.statusCode == 400

# Re-auth with valid creds for subsequent API calls
assert rest.authenticate(params["user"], params["password"]), "Re-authentication failed"

# Overlong name validation across entities
res = rest.createTripwire({"name": random_string, "scene": scene_uid})
logging.info(res.errors["name"])
assert res.errors["name"] == ["Ensure this field has no more than 150 characters."]

res = rest.createRegion({"name": random_string, "scene": scene_uid})
logging.info(res.errors["name"])
assert res.errors["name"] == ["Ensure this field has no more than 150 characters."]

res = rest.createSensor({"name": random_string, "scene": scene_uid})
logging.info(res.errors["name"])
assert res.errors["name"] == ["Ensure this field has no more than 150 characters."]

res = rest.createCamera({"name": random_string, "scene": scene_uid})
logging.info(res.errors["name"])
assert res.errors["name"] == ["Ensure this field has no more than 150 characters."]

res = rest.createScene({"name": random_string})
logging.info(res.errors["name"])
assert res.errors["name"] == ["Ensure this field has no more than 150 characters."]

# Overlong sensor_id validation
res = rest.createSensor({"sensor_id": random_string, "scene": scene_uid})
logging.info(res.errors["sensor_id"])
assert res.errors["sensor_id"] == ["Ensure this field has no more than 20 characters."]

result_recorder.success()
Loading
Loading