diff options
Diffstat (limited to 'tests/python')
-rw-r--r-- | tests/python/CMakeLists.txt | 6 | ||||
-rw-r--r-- | tests/python/bl_load_addons.py | 25 | ||||
-rw-r--r-- | tests/python/bl_rna_defaults.py | 117 | ||||
-rw-r--r-- | tests/python/bl_rna_manual_reference.py (renamed from tests/python/bl_rna_wiki_reference.py) | 51 | ||||
-rw-r--r-- | tests/python/bl_rst_completeness.py | 2 | ||||
-rw-r--r-- | tests/python/bl_run_operators.py | 10 | ||||
-rw-r--r-- | tests/python/pep8.py | 13 | ||||
-rw-r--r-- | tests/python/rst_to_doctree_mini.py | 21 |
8 files changed, 213 insertions, 32 deletions
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index fd47bba4182..81438d357e4 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -395,6 +395,12 @@ if(WITH_CYCLES) -testdir "${TEST_SRC_DIR}/cycles/ctests/reports" -idiff "${OPENIMAGEIO_IDIFF}" ) + add_test(cycles_render_test + ${CMAKE_CURRENT_LIST_DIR}/cycles_render_tests.py + -blender "${TEST_BLENDER_EXE_BARE}" + -testdir "${TEST_SRC_DIR}/cycles/ctests/render" + -idiff "${OPENIMAGEIO_IDIFF}" + ) add_test(cycles_shaders_test ${CMAKE_CURRENT_LIST_DIR}/cycles_render_tests.py -blender "${TEST_BLENDER_EXE_BARE}" diff --git a/tests/python/bl_load_addons.py b/tests/python/bl_load_addons.py index 227edf4164d..6bb0eaecd3d 100644 --- a/tests/python/bl_load_addons.py +++ b/tests/python/bl_load_addons.py @@ -34,11 +34,29 @@ import imp BLACKLIST_DIRS = ( os.path.join(bpy.utils.resource_path('USER'), "scripts"), ) + tuple(addon_utils.paths()[1:]) +BLACKLIST_ADDONS = set() + + +def _init_addon_blacklist(): + + # in case we built without cycles + if not bpy.app.build_options.cycles: + BLACKLIST_ADDONS.add("cycles") + + # in case we built without freestyle + if not bpy.app.build_options.freestyle: + BLACKLIST_ADDONS.add("render_freestyle_svg") + + # netrender has known problems re-registering + BLACKLIST_ADDONS.add("netrender") def addon_modules_sorted(): modules = addon_utils.modules({}) - modules[:] = [mod for mod in modules if not mod.__file__.startswith(BLACKLIST_DIRS)] + modules[:] = [ + mod for mod in modules + if not (mod.__file__.startswith(BLACKLIST_DIRS)) + if not (mod.__name__ in BLACKLIST_ADDONS)] modules.sort(key=lambda mod: mod.__name__) return modules @@ -64,7 +82,7 @@ def test_load_addons(): mod_name = mod.__name__ print("\tenabling:", mod_name) addon_utils.enable(mod_name, default_set=True) - if mod_name not in addons: + if (mod_name not in addons) and (mod_name not in BLACKLIST_ADDONS): addons_fail.append(mod_name) if addons_fail: @@ -106,6 +124,9 @@ def reload_addons(do_reload=True, do_reverse=True): def main(): + + _init_addon_blacklist() + # first load addons, print a list of all addons that fail test_load_addons() diff --git a/tests/python/bl_rna_defaults.py b/tests/python/bl_rna_defaults.py new file mode 100644 index 00000000000..1d6f82b06c2 --- /dev/null +++ b/tests/python/bl_rna_defaults.py @@ -0,0 +1,117 @@ +# Apache License, Version 2.0 + +# ./blender.bin --background -noaudio --factory-startup --python tests/python/bl_rna_defaults.py + +import bpy + +DUMMY_NAME = "Untitled" +DUMMY_PATH = __file__ +GLOBALS = { + "error_num": 0, + } + + +def validate_defaults(test_id, o): + + def warning(prop_id, val_real, val_default): + print("Error %s: '%s.%s' is:%r, expected:%r" % + (test_id, o.__class__.__name__, prop_id, val_real, val_default)) + GLOBALS["error_num"] += 1 + + properties = type(o).bl_rna.properties.items() + for prop_id, prop in properties: + if prop_id == "rna_type": + continue + prop_type = prop.type + if prop_type in {'STRING', 'COLLECTION'}: + continue + + if prop_type == 'POINTER': + # traverse down pointers if they're set + val_real = getattr(o, prop_id) + if (val_real is not None) and (not isinstance(val_real, bpy.types.ID)): + validate_defaults("%s.%s" % (test_id, prop_id), val_real) + elif prop_type in {'INT', 'BOOL'}: + array_length = prop.array_length + if array_length == 0: + val_real = getattr(o, prop_id) + val_default = prop.default + if val_real != val_default: + warning(prop_id, val_real, val_default) + else: + pass # TODO, array defaults + elif prop_type == 'FLOAT': + array_length = prop.array_length + if array_length == 0: + val_real = getattr(o, prop_id) + val_default = prop.default + if val_real != val_default: + warning(prop_id, val_real, val_default) + else: + pass # TODO, array defaults + elif prop_type == 'ENUM': + val_real = getattr(o, prop_id) + if prop.is_enum_flag: + val_default = prop.default_flag + else: + val_default = prop.default + if val_real != val_default: + warning(prop_id, val_real, val_default) + + # print(prop_id, prop_type) + + +def _test_id_gen(data_attr, args_create=(DUMMY_NAME,), create_method="new"): + def test_gen(test_id): + id_collection = getattr(bpy.data, data_attr) + create_fn = getattr(id_collection, create_method) + o = create_fn(*args_create) + o.user_clear() + validate_defaults(test_id, o) + id_collection.remove(o) + return test_gen + + +test_Action = _test_id_gen("actions") +test_Armature = _test_id_gen("armatures") +test_Camera = _test_id_gen("cameras") +test_Group = _test_id_gen("groups") +test_Lattice = _test_id_gen("lattices") +test_LineStyle = _test_id_gen("linestyles") +test_Mask = _test_id_gen("masks") +test_Material = _test_id_gen("materials") +test_Mesh = _test_id_gen("meshes") +test_MetaBall = _test_id_gen("metaballs") +test_MovieClip = _test_id_gen("movieclips", args_create=(DUMMY_PATH,), create_method="load") +test_Object = _test_id_gen("objects", args_create=(DUMMY_NAME, None)) +test_Palette = _test_id_gen("palettes") +test_Particle = _test_id_gen("particles") +test_Scene = _test_id_gen("scenes") +test_Sound = _test_id_gen("sounds", args_create=(DUMMY_PATH,), create_method="load") +test_Speaker = _test_id_gen("speakers") +test_Text = _test_id_gen("texts") +test_VectorFont = _test_id_gen("fonts", args_create=("<builtin>",), create_method="load") +test_World = _test_id_gen("worlds") + +ns = globals() +for t in bpy.data.curves.bl_rna.functions["new"].parameters["type"].enum_items.keys(): + ns["test_Curve_%s" % t] = _test_id_gen("curves", args_create=(DUMMY_NAME, t)) +for t in bpy.data.lamps.bl_rna.functions["new"].parameters["type"].enum_items.keys(): + ns["test_Lamp_%s" % t] = _test_id_gen("lamps", args_create=(DUMMY_NAME, t)) +# types are a dynamic enum, have to hard-code. +for t in "ShaderNodeTree", "CompositorNodeTree", "TextureNodeTree": + ns["test_NodeGroup_%s" % t] = _test_id_gen("node_groups", args_create=(DUMMY_NAME, t)) +for t in bpy.data.textures.bl_rna.functions["new"].parameters["type"].enum_items.keys(): + ns["test_Texture_%s" % t] = _test_id_gen("textures", args_create=(DUMMY_NAME, t)) +del ns + + +def main(): + for fn_id, fn_val in sorted(globals().items()): + if fn_id.startswith("test_") and callable(fn_val): + fn_val(fn_id) + + print("Error (total): %d" % GLOBALS["error_num"]) + +if __name__ == "__main__": + main() diff --git a/tests/python/bl_rna_wiki_reference.py b/tests/python/bl_rna_manual_reference.py index 5781c53c045..c67b6c1532b 100644 --- a/tests/python/bl_rna_wiki_reference.py +++ b/tests/python/bl_rna_manual_reference.py @@ -18,8 +18,8 @@ # <pep8 compliant> -# Use for validating our wiki interlinking. -# ./blender.bin --background -noaudio --python tests/python/bl_rna_wiki_reference.py +# Use for validating our manual interlinking. +# ./blender.bin --background -noaudio --python tests/python/bl_rna_manual_reference.py # # 1) test_data() -- ensure the data we have is correct format # 2) test_lookup_coverage() -- ensure that we have lookups for _every_ RNA path @@ -31,10 +31,10 @@ import bpy def test_data(): - import rna_wiki_reference + import rna_manual_reference - assert(isinstance(rna_wiki_reference.url_manual_mapping, tuple)) - for i, value in enumerate(rna_wiki_reference.url_manual_mapping): + assert(isinstance(rna_manual_reference.url_manual_mapping, tuple)) + for i, value in enumerate(rna_manual_reference.url_manual_mapping): try: assert(len(value) == 2) assert(isinstance(value[0], str)) @@ -92,14 +92,19 @@ def test_language_coverage(): def test_urls(): + import os import sys - import rna_wiki_reference + import rna_manual_reference import urllib.error from urllib.request import urlopen - prefix = rna_wiki_reference.url_manual_prefix - urls = {suffix for (rna_id, suffix) in rna_wiki_reference.url_manual_mapping} + # avoid URL lookups if possible + LOCAL_PREFIX = os.environ.get("LOCAL_PREFIX") + if LOCAL_PREFIX is None: + prefix = rna_manual_reference.url_manual_prefix + + urls = {suffix for (rna_id, suffix) in rna_manual_reference.url_manual_mapping} urls_len = "%d" % len(urls) print("") @@ -113,16 +118,26 @@ def test_urls(): urls_fail = [] - for url in sorted(urls): - url_full = prefix + url - print(" %s ... " % url_full, end="") - sys.stdout.flush() - try: - urlopen(url_full) - print(color_green + "OK" + color_normal) - except urllib.error.HTTPError: - print(color_red + "FAIL!" + color_normal) - urls_fail.append(url) + if LOCAL_PREFIX: + for url in sorted(urls): + url_full = os.path.join(LOCAL_PREFIX, url.partition("#")[0]) + print(" %s ... " % url_full, end="") + if os.path.exists(url_full): + print(color_green + "OK" + color_normal) + else: + print(color_red + "FAIL!" + color_normal) + urls_fail.append(url) + else: + for url in sorted(urls): + url_full = prefix + url + print(" %s ... " % url_full, end="") + sys.stdout.flush() + try: + urlopen(url_full) + print(color_green + "OK" + color_normal) + except urllib.error.HTTPError: + print(color_red + "FAIL!" + color_normal) + urls_fail.append(url) if urls_fail: urls_len = "%d" % len(urls_fail) diff --git a/tests/python/bl_rst_completeness.py b/tests/python/bl_rst_completeness.py index d0ba2c552cf..d8dfac66d13 100644 --- a/tests/python/bl_rst_completeness.py +++ b/tests/python/bl_rst_completeness.py @@ -62,7 +62,7 @@ def is_directive_pydata(filepath, directive): return True elif directive.type in {"module", "note", "warning", "code-block", "hlist", "seealso"}: return False - elif directive.type in {"literalinclude"}: # TODO + elif directive.type == "literalinclude": # TODO return False else: print(directive_to_str(filepath, directive), end=" ") diff --git a/tests/python/bl_run_operators.py b/tests/python/bl_run_operators.py index f7fafe833aa..f3c553cf3ef 100644 --- a/tests/python/bl_run_operators.py +++ b/tests/python/bl_run_operators.py @@ -34,6 +34,10 @@ RANDOM_SEED = [1] # so we can redo crashes RANDOM_RESET = 0.1 # 10% chance of resetting on each new operator RANDOM_MULTIPLY = 10 +STATE = { + "counter": 0, + } + op_blacklist = ( "script.reload", @@ -75,6 +79,7 @@ op_blacklist = ( "wm.properties_context_change", "wm.operator_cheat_sheet", "wm.interface_theme_*", + "wm.previews_ensure", # slow - but harmless "wm.appconfig_*", # just annoying - but harmless "wm.keyitem_add", # just annoying - but harmless "wm.keyconfig_activate", # just annoying - but harmless @@ -158,7 +163,7 @@ if USE_ATTRSET: if issubclass(cls, skip_classes): continue - ## to support skip-save we cant get all props + # # to support skip-save we cant get all props # properties = cls.bl_rna.properties.keys() properties = [] for prop_id, prop in cls.bl_rna.properties.items(): @@ -248,7 +253,8 @@ def run_ops(operators, setup_func=None, reset=True): # first invoke for op_id, op in operators: if op.poll(): - print(" operator:", op_id) + print(" operator: %4d, %s" % (STATE["counter"], op_id)) + STATE["counter"] += 1 sys.stdout.flush() # in case of crash # disable will get blender in a bad state and crash easy! diff --git a/tests/python/pep8.py b/tests/python/pep8.py index 551e2a87e9b..0d6db729767 100644 --- a/tests/python/pep8.py +++ b/tests/python/pep8.py @@ -117,7 +117,18 @@ def main(): # these are very picky and often hard to follow # while keeping common script formatting. - ignore = "E122", "E123", "E124", "E125", "E126", "E127", "E128" + ignore = ( + "E122", + "E123", + "E124", + "E125", + "E126", + "E127", + "E128", + # "imports not at top of file." + # prefer to load as needed (lazy load addons etc). + "E402", + ) for f, pep8_type in files: diff --git a/tests/python/rst_to_doctree_mini.py b/tests/python/rst_to_doctree_mini.py index 6a885a108f8..dfc6cd57db6 100644 --- a/tests/python/rst_to_doctree_mini.py +++ b/tests/python/rst_to_doctree_mini.py @@ -28,13 +28,14 @@ import collections -Directive = collections.namedtuple('Directive', - ("type", - "value", - "value_strip", - "line", - "indent", - "members")) +Directive = collections.namedtuple( + "Directive", + ("type", + "value", + "value_strip", + "line", + "indent", + "members")) def parse_rst_py(filepath): @@ -80,7 +81,7 @@ def parse_rst_py(filepath): return tree[0] -if __name__ == "__main__": +def main(): # not intended use, but may as well print rst files passed as a test. import sys for arg in sys.argv: @@ -88,3 +89,7 @@ if __name__ == "__main__": items = parse_rst_py(arg) for i in items: print(i) + + +if __name__ == "__main__": + main() |