Add Chromium-only Blender WebEngine parity work
This commit is contained in:
5
blender-5.2.0/tests/python/assets/CMakeLists.txt
Normal file
5
blender-5.2.0/tests/python/assets/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
# SPDX-FileCopyrightText: 2025 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
add_subdirectory(remote_library)
|
||||
@@ -0,0 +1,22 @@
|
||||
# SPDX-FileCopyrightText: 2025 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
add_blender_test(
|
||||
assets_remote_library_listing_asset_catalogs_test
|
||||
--python ${CMAKE_CURRENT_LIST_DIR}/listing_asset_catalogs_test.py
|
||||
--
|
||||
--outdir "${TEST_OUT_DIR}/assets"
|
||||
)
|
||||
|
||||
add_blender_test(
|
||||
assets_remote_library_listing_downloader_test
|
||||
--python ${CMAKE_CURRENT_LIST_DIR}/listing_downloader_test.py
|
||||
--
|
||||
--outdir "${TEST_OUT_DIR}/assets"
|
||||
)
|
||||
|
||||
add_blender_test(
|
||||
assets_remote_library_listing_generator_test
|
||||
--python ${CMAKE_CURRENT_LIST_DIR}/listing_generator_test.py
|
||||
)
|
||||
@@ -0,0 +1,98 @@
|
||||
# SPDX-FileCopyrightText: 2026 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from _bpy_internal.assets.remote_library import listing_asset_catalogs
|
||||
from _bpy_internal.assets.remote_library import blender_asset_library_openapi as api_models
|
||||
|
||||
"""
|
||||
blender -b --factory-startup -P tests/python/assets/remote_library/listing_asset_catalogs_test.py -- --outdir=/tmp
|
||||
"""
|
||||
|
||||
# CLI argument, will be set to its actual value in main() below.
|
||||
arg_outdir: Path
|
||||
|
||||
|
||||
class ListingDownloaderTest(unittest.TestCase):
|
||||
cats_path: Path
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls) -> None:
|
||||
arg_outdir.mkdir(parents=True, exist_ok=True)
|
||||
cls.cats_path = arg_outdir / "test_catalogs.cats.txt"
|
||||
|
||||
def tearDown(self) -> None:
|
||||
self.cats_path.unlink(missing_ok=True)
|
||||
|
||||
def test_write_sanitized_cats(self) -> None:
|
||||
catalogs = [
|
||||
api_models.CatalogV1(
|
||||
path="Cats/Laksa",
|
||||
uuids=["cdf49402-6814-5c20-a026-9f3211d8a615"],
|
||||
simple_name="cats-laksa",
|
||||
),
|
||||
api_models.CatalogV1(
|
||||
path="Cats/Quercus\nwith\nnewlines",
|
||||
uuids=["2143dfac-9e81-5a31-99f2-befa8ff26ac2"],
|
||||
simple_name="cats-quercus",
|
||||
),
|
||||
api_models.CatalogV1(
|
||||
path="Cats/Raymond\n: Pawducer",
|
||||
uuids=["db847984-cb61-5197-87b5-39134a2e758c"],
|
||||
simple_name="cats-raymond",
|
||||
),
|
||||
api_models.CatalogV1(
|
||||
path="Cats/Muesli: Huntress",
|
||||
uuids=["d7ce44c8-d1df-5055-bae4-8a6ed03b8329"],
|
||||
simple_name="cats-muesli",
|
||||
),
|
||||
]
|
||||
asset_library_meta = api_models.AssetLibraryMeta(
|
||||
api_versions={},
|
||||
contact=api_models.Contact(name="Unit the Tester"),
|
||||
name="Cats of\nAmsterdam",
|
||||
)
|
||||
|
||||
listing_asset_catalogs.write(catalogs, self.cats_path, asset_library_meta)
|
||||
|
||||
# Check the file is as expected.
|
||||
file_lines = self.cats_path.read_text().splitlines()
|
||||
|
||||
# The line numbers are determined by listing_asset_catalogs._ASSET_CATS_HEADER.
|
||||
header_num_lines = len(listing_asset_catalogs._ASSET_CATS_HEADER.splitlines())
|
||||
self.assertIn("Cats of Amsterdam", file_lines[header_num_lines - 3])
|
||||
|
||||
# The catalogs should be ordered by path, and sanitized.
|
||||
written_cats = file_lines[header_num_lines + 1:]
|
||||
expect_cats = [
|
||||
"cdf49402-6814-5c20-a026-9f3211d8a615:Cats/Laksa:cats-laksa",
|
||||
"d7ce44c8-d1df-5055-bae4-8a6ed03b8329:Cats/Muesli Huntress:cats-muesli",
|
||||
"2143dfac-9e81-5a31-99f2-befa8ff26ac2:Cats/Quercus with newlines:cats-quercus",
|
||||
"db847984-cb61-5197-87b5-39134a2e758c:Cats/Raymond Pawducer:cats-raymond",
|
||||
]
|
||||
self.assertEqual(expect_cats, written_cats)
|
||||
|
||||
|
||||
def main():
|
||||
global arg_outdir
|
||||
import argparse
|
||||
|
||||
argv = [sys.argv[0]]
|
||||
if '--' in sys.argv:
|
||||
argv += sys.argv[sys.argv.index('--') + 1:]
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--outdir', required=True, type=Path)
|
||||
args, remaining = parser.parse_known_args(argv)
|
||||
|
||||
arg_outdir = args.outdir
|
||||
|
||||
unittest.main(argv=remaining)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,302 @@
|
||||
# SPDX-FileCopyrightText: 2026 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import shutil
|
||||
import sys
|
||||
import unittest
|
||||
from pathlib import Path, PurePath, PurePosixPath, PureWindowsPath
|
||||
from typing import override
|
||||
|
||||
from _bpy_internal.assets.remote_library import json_parsing, listing_downloader
|
||||
from _bpy_internal.assets.remote_library import blender_asset_library_openapi as api_models
|
||||
|
||||
import bpy
|
||||
|
||||
"""
|
||||
blender -b --factory-startup -P tests/python/assets/remote_library/listing_downloader_test.py -- --outdir=/tmp
|
||||
"""
|
||||
|
||||
# CLI argument, will be set to its actual value in main() below.
|
||||
arg_outdir: Path
|
||||
|
||||
|
||||
class ListingDownloaderTest(unittest.TestCase):
|
||||
json_path: Path
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls) -> None:
|
||||
arg_outdir.mkdir(parents=True, exist_ok=True)
|
||||
cls.json_path = arg_outdir / "asset_page.json"
|
||||
|
||||
def tearDown(self) -> None:
|
||||
self.json_path.unlink(missing_ok=True)
|
||||
|
||||
def test_sanitize_asset_page__bad_paths(self) -> None:
|
||||
# These paths should be handled identically, independent of the current platform.
|
||||
self._test_sanitize_asset_page_with_specific_bad_path(r"C:\temp\kubus.blend", "temp/kubus.blend")
|
||||
self.assertTrue(self.json_path.exists(), "JSON file should have been rewritten")
|
||||
self._test_sanitize_asset_page_with_specific_bad_path(r"C:/temp/kubus.blend", "temp/kubus.blend")
|
||||
self.assertTrue(self.json_path.exists(), "JSON file should have been rewritten")
|
||||
self._test_sanitize_asset_page_with_specific_bad_path("/temp/kubus.blend", "temp/kubus.blend")
|
||||
self.assertTrue(self.json_path.exists(), "JSON file should have been rewritten")
|
||||
self._test_sanitize_asset_page_with_specific_bad_path("//temp/kubus.blend", "temp/kubus.blend")
|
||||
self.assertTrue(self.json_path.exists(), "JSON file should have been rewritten")
|
||||
self._test_sanitize_asset_page_with_specific_bad_path(r"\\NAS\share\temp\kubus.blend", "temp/kubus.blend")
|
||||
self.assertTrue(self.json_path.exists(), "JSON file should have been rewritten")
|
||||
self._test_sanitize_asset_page_with_specific_bad_path("/temp/kubus.blend", "temp/kubus.blend")
|
||||
self.assertTrue(self.json_path.exists(), "JSON file should have been rewritten")
|
||||
self._test_sanitize_asset_page_with_specific_bad_path(r"\temp\kubus.blend", "temp/kubus.blend")
|
||||
self.assertTrue(self.json_path.exists(), "JSON file should have been rewritten")
|
||||
self._test_sanitize_asset_page_with_specific_bad_path(
|
||||
r"//NAS/share/temp/kubus.blend", "NAS/share/temp/kubus.blend")
|
||||
self.assertTrue(self.json_path.exists(), "JSON file should have been rewritten")
|
||||
self._test_sanitize_asset_page_with_specific_bad_path(
|
||||
r"//localhost\C$\Windows\System32\kubus.blend", "Windows/System32/kubus.blend")
|
||||
self._test_sanitize_asset_page_with_specific_bad_path(
|
||||
r"//localhost/C$/Windows/System32/kubus.blend", "localhost/C$/Windows/System32/kubus.blend")
|
||||
self.assertTrue(self.json_path.exists(), "JSON file should have been rewritten")
|
||||
|
||||
# Relative path that attempts to break out of the asset library.
|
||||
self._test_sanitize_asset_page_with_specific_bad_path(
|
||||
"sneaky/path/../../../temp/kubus.blend", "temp/kubus.blend")
|
||||
self.assertTrue(self.json_path.exists(), "JSON file should have been rewritten")
|
||||
|
||||
def test_sanitize_asset_page__all_ok(self) -> None:
|
||||
# Construct an incorrect asset page, with bad counts and an absolute path to a file.
|
||||
blend_path = "temp/kubus.blend"
|
||||
|
||||
asset_page = api_models.AssetLibraryIndexPageV1(
|
||||
# Set correct asset & file counts.
|
||||
asset_count=1,
|
||||
file_count=1,
|
||||
|
||||
assets=[
|
||||
api_models.AssetV1(
|
||||
name="Kubus",
|
||||
id_type="OBJECT",
|
||||
files=[blend_path],
|
||||
thumbnail=api_models.URLWithHash(url="thumbs/kubus.webp", hash="12345"),
|
||||
meta=None,
|
||||
bl_versions=api_models.AssetBlenderVersionsV1(min="2.0"),
|
||||
),
|
||||
],
|
||||
files=[
|
||||
api_models.FileV1(
|
||||
# Absolute path, should get corrected.
|
||||
path=blend_path,
|
||||
size_in_bytes=328051946337,
|
||||
hash="CAT:51756572637573",
|
||||
blender_version="5.2",
|
||||
url=None,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
Downloader = listing_downloader.RemoteAssetListingDownloader
|
||||
dl = Downloader(
|
||||
remote_url="http://localhost/",
|
||||
local_path="/tmp/does-not-matter-we-do-not-write",
|
||||
on_update_callback=lambda downloader: None,
|
||||
on_done_callback=lambda downloader: None,
|
||||
on_metafiles_done_callback=None,
|
||||
on_page_done_callback=None,
|
||||
)
|
||||
self.json_path.unlink(missing_ok=True)
|
||||
dl._sanitize_asset_page(asset_page, self.json_path)
|
||||
|
||||
# Check that the counts have been kept the same.
|
||||
self.assertEqual(1, asset_page.asset_count)
|
||||
self.assertEqual(1, asset_page.file_count)
|
||||
|
||||
# Check that the file paths are also kept the same.
|
||||
self.assertEqual(blend_path, asset_page.files[0].path, "In-memory file entry should have been sanitized")
|
||||
self.assertEqual(
|
||||
[blend_path],
|
||||
asset_page.assets[0].files,
|
||||
"In-memory file reference of asset entry should have been sanitized")
|
||||
|
||||
# Check that the JSON file does not exist, because rewriting was not necessary.
|
||||
self.assertFalse(self.json_path.exists(), "JSON file should NOT have been rewritten")
|
||||
|
||||
def _test_sanitize_asset_page_with_specific_bad_path(self, bad_path: str, sanitized_path: str) -> None:
|
||||
# Construct an incorrect asset page, with bad counts and an absolute path to a file.
|
||||
asset_page = api_models.AssetLibraryIndexPageV1(
|
||||
# Set incorrect asset & file counts. These should get corrected.
|
||||
asset_count=47,
|
||||
file_count=327,
|
||||
|
||||
assets=[
|
||||
api_models.AssetV1(
|
||||
name="Kubus",
|
||||
id_type="OBJECT",
|
||||
files=[bad_path],
|
||||
thumbnail=api_models.URLWithHash(url="thumbs/kubus.webp", hash="12345"),
|
||||
meta=None,
|
||||
bl_versions=api_models.AssetBlenderVersionsV1(min="2.0"),
|
||||
),
|
||||
],
|
||||
files=[
|
||||
api_models.FileV1(
|
||||
# Absolute path, should get corrected.
|
||||
path=bad_path,
|
||||
size_in_bytes=328051946337,
|
||||
hash="CAT:51756572637573",
|
||||
blender_version="5.2",
|
||||
url=None,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
Downloader = listing_downloader.RemoteAssetListingDownloader
|
||||
dl = Downloader(
|
||||
remote_url="http://localhost/",
|
||||
local_path="/tmp/does-not-matter-we-do-not-write",
|
||||
on_update_callback=lambda downloader: None,
|
||||
on_done_callback=lambda downloader: None,
|
||||
on_metafiles_done_callback=None,
|
||||
on_page_done_callback=None,
|
||||
)
|
||||
self.json_path.unlink(missing_ok=True)
|
||||
dl._sanitize_asset_page(asset_page, self.json_path)
|
||||
|
||||
# Check that the counts have been sanitized.
|
||||
self.assertEqual(1, asset_page.asset_count)
|
||||
self.assertEqual(1, asset_page.file_count)
|
||||
|
||||
# Check that the absolute file path has been sanitized.
|
||||
# Both the Windows and the POSIX version of bad_path should sanitize to this path.
|
||||
self.assertEqual(sanitized_path, asset_page.files[0].path, "In-memory file entry should have been sanitized")
|
||||
self.assertEqual([sanitized_path], asset_page.assets[0].files,
|
||||
"In-memory file reference of asset entry should have been sanitized")
|
||||
|
||||
# Check that the JSON file has been updated, so that when Blender later reads it, it's been sanitized.
|
||||
parser = json_parsing.ValidatingParser()
|
||||
json_payload = self.json_path.read_bytes()
|
||||
from_file = parser.parse_and_validate(api_models.AssetLibraryIndexPageV1, json_payload)
|
||||
|
||||
# Check that the counts have been sanitized.
|
||||
self.assertEqual(1, from_file.asset_count)
|
||||
self.assertEqual(1, from_file.file_count)
|
||||
|
||||
# Check that the absolute file path has been sanitized.
|
||||
# Both the Windows and the POSIX version of bad_path should sanitize to this path.
|
||||
self.assertEqual(sanitized_path, from_file.files[0].path, "File entry should have been sanitized")
|
||||
self.assertEqual([sanitized_path], from_file.assets[0].files,
|
||||
"File reference of asset entry should have been sanitized")
|
||||
|
||||
|
||||
class PathGuessingTest(unittest.TestCase):
|
||||
def test_str_to_path_multiplatform(self) -> None:
|
||||
str_to_path = listing_downloader._str_to_path_multiplatform
|
||||
self.assertEqual(PureWindowsPath(r'C:\Program Files\Blender'), str_to_path(r'C:\Program Files/Blender'))
|
||||
self.assertEqual(PureWindowsPath(r'C:\Program Files\Blender'), str_to_path(r'C:/Program Files/Blender'))
|
||||
self.assertEqual(PureWindowsPath(r'\\NAS\share\flamenco\file.blend'),
|
||||
str_to_path(r'\\NAS\share\flamenco\file.blend'))
|
||||
self.assertEqual(PurePosixPath('/Program Files/Blender'), str_to_path('/Program Files/Blender'))
|
||||
self.assertEqual(PurePath('file.blend'), str_to_path('file.blend'))
|
||||
|
||||
|
||||
class SanitizePathFromURLTest(unittest.TestCase):
|
||||
def test_sanitize_path_from_url(self) -> None:
|
||||
_sanitize_path_from_url = listing_downloader._sanitize_path_from_url
|
||||
self.assertEqual(
|
||||
PurePosixPath('normal/path/as/expected.blend'),
|
||||
_sanitize_path_from_url('/normal/path/as/expected.blend'),
|
||||
)
|
||||
self.assertEqual(
|
||||
PurePosixPath('normal/path/as/expected.blend'),
|
||||
_sanitize_path_from_url(PurePosixPath('/normal/path/as/expected.blend')),
|
||||
)
|
||||
self.assertEqual(
|
||||
PurePosixPath('.'),
|
||||
_sanitize_path_from_url(PurePosixPath('')),
|
||||
)
|
||||
self.assertEqual(
|
||||
PurePosixPath('path/filename.blend'),
|
||||
_sanitize_path_from_url(PurePosixPath('/path/sub/../filename.blend')),
|
||||
)
|
||||
self.assertEqual(
|
||||
PurePosixPath('path/filename.blend'),
|
||||
_sanitize_path_from_url('/path/sub%2F%2E%2e/filename.blend'),
|
||||
)
|
||||
self.assertEqual(
|
||||
PurePosixPath('path/filename.blend'),
|
||||
_sanitize_path_from_url('path/filename.blend'),
|
||||
)
|
||||
self.assertEqual(
|
||||
PurePosixPath('longer/filename.blend'),
|
||||
_sanitize_path_from_url(PurePosixPath('/longer/faster/path/../../filename.blend')),
|
||||
)
|
||||
self.assertEqual(
|
||||
PurePosixPath('filename.blend'),
|
||||
_sanitize_path_from_url(PurePosixPath('/faster/path/../../filename.blend')),
|
||||
)
|
||||
self.assertEqual(
|
||||
PurePosixPath('filename.blend'),
|
||||
_sanitize_path_from_url('/faster/path/../../filename.blend'),
|
||||
)
|
||||
self.assertEqual(
|
||||
PurePosixPath('etc/passwd'),
|
||||
_sanitize_path_from_url(PurePosixPath('/../../../../../etc/passwd')),
|
||||
)
|
||||
|
||||
|
||||
class RemoteAssetListingLocatorTest(unittest.TestCase):
|
||||
asset_lib_path: Path
|
||||
|
||||
@override
|
||||
def setUp(self) -> None:
|
||||
arg_outdir.mkdir(parents=True, exist_ok=True)
|
||||
self.asset_lib_path = arg_outdir / "test_asset_library"
|
||||
|
||||
@override
|
||||
def tearDown(self) -> None:
|
||||
if self.asset_lib_path.exists():
|
||||
shutil.rmtree(self.asset_lib_path)
|
||||
|
||||
def test_is_system_path(self) -> None:
|
||||
locator = listing_downloader.RemoteAssetListingLocator('https://example.com/', self.asset_lib_path)
|
||||
|
||||
self.assertFalse(locator.is_system_path(Path()))
|
||||
self.assertFalse(locator.is_system_path(arg_outdir))
|
||||
self.assertFalse(locator.is_system_path(self.asset_lib_path))
|
||||
self.assertFalse(locator.is_system_path(self.asset_lib_path / "valid-download.blend"))
|
||||
|
||||
self.assertTrue(locator.is_system_path(self.asset_lib_path / "_asset-library-meta.json"))
|
||||
self.assertTrue(locator.is_system_path(self.asset_lib_path / "_v1/asset-index.json"))
|
||||
self.assertTrue(locator.is_system_path(self.asset_lib_path / "_v1/assets-00000.json"))
|
||||
self.assertTrue(locator.is_system_path(self.asset_lib_path / "_v1/file-that-is-not-used.toml"))
|
||||
self.assertTrue(locator.is_system_path(self.asset_lib_path / "_listing_backup"))
|
||||
self.assertTrue(locator.is_system_path(self.asset_lib_path / "_listing_backup/whatever.txt"))
|
||||
|
||||
# Check the file hash path. It's a special case, because it's constructed from various parts and thus uses
|
||||
# pattern matching.
|
||||
self.assertTrue(locator.is_system_path(self.asset_lib_path / "_file_hashes_v1.sqlite"))
|
||||
self.assertTrue(locator.is_system_path(self.asset_lib_path / "_FILE_hashes_v2.SqLiTe"))
|
||||
self.assertFalse(locator.is_system_path(self.asset_lib_path / "harmless_file_hashes_v1.sqlite"))
|
||||
|
||||
# Test some sneaky indirection. This is why the resolve() function is called in is_listing_path().
|
||||
self.assertTrue(locator.is_system_path(self.asset_lib_path / "../.." /
|
||||
self.asset_lib_path.parts[-2] / self.asset_lib_path.parts[-1] / "_v1"))
|
||||
|
||||
|
||||
def main():
|
||||
global arg_outdir
|
||||
import argparse
|
||||
|
||||
argv = [sys.argv[0]]
|
||||
if '--' in sys.argv:
|
||||
argv += sys.argv[sys.argv.index('--') + 1:]
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--outdir', required=True, type=Path)
|
||||
args, remaining = parser.parse_known_args(argv)
|
||||
|
||||
arg_outdir = args.outdir
|
||||
|
||||
unittest.main(argv=remaining)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,145 @@
|
||||
# SPDX-FileCopyrightText: 2025 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from _bpy_internal.assets.remote_library import json_parsing, hashing
|
||||
from _bpy_internal.assets.remote_library import blender_asset_library_openapi as api_models
|
||||
from _bpy_internal.assets.remote_library import cli_listing_generator_asset_finder as asset_finder
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
"""
|
||||
blender -b --factory-startup --python tests/python/assets/remote_library/listing_generator_test.py
|
||||
"""
|
||||
|
||||
|
||||
class CustomPropertiesTest(unittest.TestCase):
|
||||
cube: bpy.types.Object
|
||||
|
||||
def setUp(self) -> None:
|
||||
bpy.ops.wm.read_homefile(use_factory_startup=True)
|
||||
|
||||
self.cube = bpy.data.objects['Cube']
|
||||
self.cube.asset_mark()
|
||||
self.maxDiff = 100000
|
||||
|
||||
def test_empty_metadata(self) -> None:
|
||||
del self.cube.asset_data["dimensions"]
|
||||
meta = asset_finder._get_asset_meta(self.cube.asset_data)
|
||||
self.assertIsNone(meta)
|
||||
|
||||
def test_plain_properties(self) -> None:
|
||||
asset_data = self.cube.asset_data
|
||||
|
||||
asset_data["barcode"] = "155366" # Integer-like, should be stored as string.
|
||||
asset_data["location"] = "café" # Non-ASCII string.
|
||||
asset_data["size"] = 32.7 # FLOAT
|
||||
asset_data["count"] = 47 # INT
|
||||
asset_data["amazing"] = True # BOOL
|
||||
|
||||
meta = asset_finder._get_asset_meta(asset_data)
|
||||
|
||||
Types = api_models.CustomPropertyTypeV1
|
||||
Prop = api_models.CustomPropertyV1
|
||||
# autopep8: off
|
||||
expected_props = [
|
||||
Prop(name='dimensions', type=Types.IDP_ARRAY, value=[2.0, 2.0, 2.0], itemtype=Types.IDP_FLOAT),
|
||||
Prop(name='barcode', type=Types.IDP_STRING, value='155366'),
|
||||
Prop(name='location', type=Types.IDP_STRING, value='café'),
|
||||
Prop(name='size', type=Types.IDP_FLOAT, value=32.7),
|
||||
Prop(name='count', type=Types.IDP_INT, value=47),
|
||||
Prop(name='amazing', type=Types.IDP_BOOL, value=True),
|
||||
]
|
||||
# autopep8: on
|
||||
|
||||
assert meta is not None
|
||||
self.assertEqual(expected_props, meta.properties)
|
||||
|
||||
def test_array_properties(self) -> None:
|
||||
asset_data = self.cube.asset_data
|
||||
|
||||
asset_data["agents"] = ["007", "47", "327"]
|
||||
asset_data["locations"] = ["Hokkaido", "Santa Fortuna", "Sapienza"]
|
||||
asset_data["boundingbox"] = [-3.0, -4.0, -0.1, 1, 2, 3]
|
||||
|
||||
meta = asset_finder._get_asset_meta(asset_data)
|
||||
|
||||
Types = api_models.CustomPropertyTypeV1
|
||||
Prop = api_models.CustomPropertyV1
|
||||
# autopep8: off
|
||||
expected_prop = [
|
||||
Prop(name='dimensions', type=Types.IDP_ARRAY, value=[2.0, 2.0, 2.0], itemtype=Types.IDP_FLOAT),
|
||||
Prop(name='agents', type=Types.IDP_ARRAY, value=["007", "47", "327"], itemtype=Types.IDP_STRING),
|
||||
Prop(name='locations', type=Types.IDP_ARRAY, value=["Hokkaido", "Santa Fortuna", "Sapienza"], itemtype=Types.IDP_STRING),
|
||||
Prop(name='boundingbox', type=Types.IDP_ARRAY, value=[-3.0, -4.0, -0.1, 1.0, 2.0, 3.0], itemtype=Types.IDP_FLOAT),
|
||||
]
|
||||
# autopep8: on
|
||||
|
||||
assert meta is not None
|
||||
self.assertEqual(expected_prop, meta.properties)
|
||||
|
||||
def test_serialize_to_json(self) -> None:
|
||||
meta = asset_finder._get_asset_meta(self.cube.asset_data)
|
||||
|
||||
# The asset metadata should be convertable to JSON.
|
||||
parser = json_parsing.ValidatingParser()
|
||||
as_json = parser.dumps(meta)
|
||||
self.assertIsNotNone(as_json)
|
||||
|
||||
# The JSON should also be deserializable as well, and produce the same data.
|
||||
roundtripped = parser.parse_and_validate(api_models.AssetMetadataV1, as_json)
|
||||
self.assertEqual(meta, roundtripped)
|
||||
|
||||
|
||||
class HashingTest(unittest.TestCase):
|
||||
def test_url_function(self) -> None:
|
||||
# No hash.
|
||||
url_with_hash = api_models.URLWithHash(
|
||||
url="http://localhost:8080/_v1/asset-index.json",
|
||||
hash=""
|
||||
)
|
||||
self.assertEqual("http://localhost:8080/_v1/asset-index.json", hashing.url(url_with_hash))
|
||||
|
||||
# Hash without type, and to-be-quoted characters.
|
||||
url_with_hash.hash = "this is a weird häsh"
|
||||
self.assertEqual(
|
||||
"http://localhost:8080/_v1/asset-index.json?hash=this%20is%20a%20weird%20h%C3%A4sh",
|
||||
hashing.url(url_with_hash))
|
||||
|
||||
# Hash with a type prefix, should be stripped.
|
||||
url_with_hash.hash = "sha1:2cafc9d388fb8c2d0b6ca9780d6b75963587916d"
|
||||
self.assertEqual(
|
||||
"http://localhost:8080/_v1/asset-index.json?hash=2cafc9d388fb8c2d0b6ca9780d6b75963587916d",
|
||||
hashing.url(url_with_hash))
|
||||
|
||||
# Existing query string, should be correctly appended to.
|
||||
url_with_hash.url = "http://localhost:8080/_v1/asset-index.json?auth=none"
|
||||
self.assertEqual(
|
||||
"http://localhost:8080/_v1/asset-index.json?auth=none&hash=2cafc9d388fb8c2d0b6ca9780d6b75963587916d",
|
||||
hashing.url(url_with_hash))
|
||||
|
||||
# Using a tuple instead of an URLWithHash object.
|
||||
self.assertEqual(
|
||||
"http://localhost:8080/_v1/asset-index.json?auth=none&hash=2cafc9d388fb8c2d0b6ca9780d6b75963587916d",
|
||||
hashing.url((
|
||||
"http://localhost:8080/_v1/asset-index.json?auth=none",
|
||||
"sha1:2cafc9d388fb8c2d0b6ca9780d6b75963587916d"
|
||||
)))
|
||||
|
||||
|
||||
def main():
|
||||
global args
|
||||
|
||||
argv = [sys.argv[0]]
|
||||
if '--' in sys.argv:
|
||||
argv += sys.argv[sys.argv.index('--') + 1:]
|
||||
|
||||
unittest.main(argv=argv)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user