Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2011-01-23 14:42:29 +0300
committerCampbell Barton <ideasman42@gmail.com>2011-01-23 14:42:29 +0300
commitd75216ba1c0fbaae1f2fe20741f23b9c35816eca (patch)
treea3fe06755315972a3101cd75efaafdcb5c4d334b /source/tests
parent552b36733bb2015aa64933bf3c57f1ad90c87b5a (diff)
- fix problem with cmake, windows 'RelWithDebInfo' target, was giving error: "ImportError: No module named _socket" because of copying wrong files over.
- move test -> tests, this name is used elsewhere in lib/tests. - change interface code not to loop on a float value (clang warning), harmless, but with extreme cases an eternal loop would still be possible though unlikely.
Diffstat (limited to 'source/tests')
-rw-r--r--source/tests/CMakeLists.txt253
-rw-r--r--source/tests/bl_test.py195
-rw-r--r--source/tests/pep8.py101
-rw-r--r--source/tests/rna_array.py297
-rw-r--r--source/tests/rna_info_dump.py131
5 files changed, 977 insertions, 0 deletions
diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt
new file mode 100644
index 00000000000..f0771f5fa0f
--- /dev/null
+++ b/source/tests/CMakeLists.txt
@@ -0,0 +1,253 @@
+# -*- mode: cmake; indent-tabs-mode: t; -*-
+# $Id: CMakeLists.txt 34198 2011-01-09 15:12:08Z campbellbarton $
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+# --env-system-scripts allows to run without WITH_INSTALL
+
+# Use '--write-blend=/tmp/test.blend' to view output
+
+
+set(TEST_SRC_DIR ${CMAKE_SOURCE_DIR}/../lib/tests)
+set(TEST_OUT_DIR ${CMAKE_BINARY_DIR}/tests)
+
+#~ if(NOT IS_DIRECTORY ${TEST_SRC_DIR})
+#~ message(FATAL_ERROR "CMake test directory not found!")
+#~ endif()
+
+# all calls to blender use this
+set(GENERIC_ARGS --background --factory-startup --env-system-scripts ${CMAKE_SOURCE_DIR}/release/scripts)
+
+
+# OBJ Import tests
+add_test(import_obj_cube ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_scene.obj\(filepath='${TEST_SRC_DIR}/io_tests/obj/cube.obj'\)
+ --md5=4d090508b812b5e08168aa2614746bda --md5_method=SCENE
+)
+
+add_test(import_obj_nurbs_cyclic ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_scene.obj\(filepath='${TEST_SRC_DIR}/io_tests/obj/nurbs_cyclic.obj'\)
+ --md5=9e0da7b65b4c4f818a203d56af2d3a4b --md5_method=SCENE
+ --write-blend=/root/foo99.blend
+)
+
+add_test(import_obj_makehuman ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_scene.obj\(filepath='${TEST_SRC_DIR}/io_tests/obj/makehuman.obj'\)
+ --md5=e0829dc078b0789e1d81f1071235bc4f --md5_method=SCENE
+)
+
+# OBJ Export tests
+add_test(export_obj_cube ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ ${TEST_SRC_DIR}/io_tests/blend_geometry/all_quads.blend
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.export_scene.obj\(filepath='${TEST_OUT_DIR}/export_obj_cube.obj',use_selection=False\)
+ --md5_source=${TEST_OUT_DIR}/export_obj_cube.obj
+ --md5_source=${TEST_OUT_DIR}/export_obj_cube.mtl
+ --md5=70bdc394c2726203ad26c085176e3484 --md5_method=FILE
+)
+
+add_test(export_obj_nurbs ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ ${TEST_SRC_DIR}/io_tests/blend_geometry/nurbs.blend
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.export_scene.obj\(filepath='${TEST_OUT_DIR}/export_obj_nurbs.obj',use_selection=False,use_nurbs=True\)
+ --md5_source=${TEST_OUT_DIR}/export_obj_nurbs.obj
+ --md5_source=${TEST_OUT_DIR}/export_obj_nurbs.mtl
+ --md5=a733ae4fa4a591ea9b0912da3af042de --md5_method=FILE
+)
+
+add_test(export_obj_all_objects ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ ${TEST_SRC_DIR}/io_tests/blend_scene/all_objects.blend
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.export_scene.obj\(filepath='${TEST_OUT_DIR}/export_obj_all_objects.obj',use_selection=False,use_nurbs=True\)
+ --md5_source=${TEST_OUT_DIR}/export_obj_all_objects.obj
+ --md5_source=${TEST_OUT_DIR}/export_obj_all_objects.mtl
+ --md5=6e033a6a9c923d7aa3613b36e373f55b --md5_method=FILE
+)
+
+
+
+# PLY Import tests
+add_test(import_ply_cube ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_mesh.ply\(filepath='${TEST_SRC_DIR}/io_tests/ply/cube_ascii.ply'\)
+ --md5=527134343c27fc0ea73115b85fbfd3ac --md5_method=SCENE
+)
+
+add_test(import_ply_bunny ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_mesh.ply\(filepath='${TEST_SRC_DIR}/io_tests/ply/bunny2.ply'\)
+ --md5=6ea5b8533400a17accf928b8fd024eaa --md5_method=SCENE
+)
+
+add_test(import_ply_small_holes ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_mesh.ply\(filepath='${TEST_SRC_DIR}/io_tests/ply/many_small_holes.ply'\)
+ --md5=c3093e26ecae5b6d59fbbcf2a0d0b39f --md5_method=SCENE
+)
+
+# PLY Export tests (TODO)
+
+
+
+# STL Import tests
+add_test(import_stl_cube ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_mesh.stl\(filepath='${TEST_SRC_DIR}/io_tests/stl/cube.stl'\)
+ --md5=8ceb5bb7e1cb5f4342fa1669988c66b4 --md5_method=SCENE
+)
+
+add_test(import_stl_conrod ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_mesh.stl\(filepath='${TEST_SRC_DIR}/io_tests/stl/conrod.stl'\)
+ --md5=690a4b8eb9002dcd8631c5a575ea7348 --md5_method=SCENE
+)
+
+add_test(import_stl_knot_max_simplified ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_mesh.stl\(filepath='${TEST_SRC_DIR}/io_tests/stl/knot_max_simplified.stl'\)
+ --md5=baf82803f45a84ec4ddbad9cef57dd3e --md5_method=SCENE
+)
+
+# STL Export tests (TODO)
+
+
+
+# X3D Import
+add_test(import_x3d_cube ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_scene.x3d\(filepath='${TEST_SRC_DIR}/io_tests/x3d/color_cube.x3d'\)
+ --md5=c80538e272812c9d765d43df269d8a9b --md5_method=SCENE
+)
+
+add_test(import_x3d_teapot ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_scene.x3d\(filepath='${TEST_SRC_DIR}/io_tests/x3d/teapot.x3d'\)
+ --md5=fa19713ff71d4b3893dcbe0ab3a73955 --md5_method=SCENE
+ --write-blend=/root/foo99.blend
+)
+
+add_test(import_x3d_suzanne_material ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_scene.x3d\(filepath='${TEST_SRC_DIR}/io_tests/x3d/suzanne_material.x3d'\)
+ --md5=52a59dcf731904ac49953dd82c020ae5 --md5_method=SCENE
+)
+
+# X3D Export
+add_test(export_x3d_cube ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ ${TEST_SRC_DIR}/io_tests/blend_geometry/all_quads.blend
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.export_scene.x3d\(filepath='${TEST_OUT_DIR}/export_x3d_cube.x3d',use_selection=False\)
+ --md5_source=${TEST_OUT_DIR}/export_x3d_cube.x3d
+ --md5=560ba3762a6604669994f661235ef93c --md5_method=FILE
+)
+
+add_test(export_x3d_nurbs ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ ${TEST_SRC_DIR}/io_tests/blend_geometry/nurbs.blend
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.export_scene.x3d\(filepath='${TEST_OUT_DIR}/export_x3d_nurbs.x3d',use_selection=False\)
+ --md5_source=${TEST_OUT_DIR}/export_x3d_nurbs.x3d
+ --md5=078c0ca5a08f123cd2cdac48afb54853 --md5_method=FILE
+)
+
+add_test(export_x3d_all_objects ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ ${TEST_SRC_DIR}/io_tests/blend_scene/all_objects.blend
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.export_scene.x3d\(filepath='${TEST_OUT_DIR}/export_x3d_all_objects.x3d',use_selection=False\)
+ --md5_source=${TEST_OUT_DIR}/export_x3d_all_objects.x3d
+ --md5=b4bddb55efd8e34af673ffb42bf4c372 --md5_method=FILE
+)
+
+
+
+# 3DS Import
+add_test(import_3ds_cube ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_scene.autodesk_3ds\(filepath='${TEST_SRC_DIR}/io_tests/3ds/cube.3ds'\)
+ --md5=cb5a45c35a343c3f5beca2a918472951 --md5_method=SCENE
+)
+
+add_test(import_3ds_hierarchy_lara ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_scene.autodesk_3ds\(filepath='${TEST_SRC_DIR}/io_tests/3ds/hierarchy_lara.3ds'\)
+ --md5=2e9812099b26ad607fdcf4c7be918c71 --md5_method=SCENE
+ --write-blend=/root/foo99.blend
+)
+
+add_test(import_3ds_hierarchy_greek_trireme ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.import_scene.autodesk_3ds\(filepath='${TEST_SRC_DIR}/io_tests/3ds/hierarchy_greek_trireme.3ds'\)
+ --md5=d05b922d7be20356d8409d1f768a3a9a --md5_method=SCENE
+)
+
+# 3DS Export
+add_test(export_3ds_cube ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ ${TEST_SRC_DIR}/io_tests/blend_geometry/all_quads.blend
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.export_scene.autodesk_3ds\(filepath='${TEST_OUT_DIR}/export_3ds_cube.3ds',use_selection=False\)
+ --md5_source=${TEST_OUT_DIR}/export_3ds_cube.3ds
+ --md5=0df6cfb130052d01e31ef77d391d4cc0 --md5_method=FILE
+)
+
+add_test(export_3ds_nurbs ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ ${TEST_SRC_DIR}/io_tests/blend_geometry/nurbs.blend
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.export_scene.autodesk_3ds\(filepath='${TEST_OUT_DIR}/export_3ds_nurbs.3ds',use_selection=False\)
+ --md5_source=${TEST_OUT_DIR}/export_3ds_nurbs.3ds
+ --md5=ba1a6d43346fee3bcadc7e30e3c95935 --md5_method=FILE
+)
+
+add_test(export_3ds_all_objects ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ ${TEST_SRC_DIR}/io_tests/blend_scene/all_objects.blend
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.export_scene.autodesk_3ds\(filepath='${TEST_OUT_DIR}/export_3ds_all_objects.3ds',use_selection=False\)
+ --md5_source=${TEST_OUT_DIR}/export_3ds_all_objects.3ds
+ --md5=1523ca2e31cf7d781c7de1e17bd14520 --md5_method=FILE
+)
+
+
+
+# FBX Export
+# 'use_metadata=False' for reliable md5's
+add_test(export_fbx_cube ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ ${TEST_SRC_DIR}/io_tests/blend_geometry/all_quads.blend
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.export_scene.fbx\(filepath='${TEST_OUT_DIR}/export_fbx_cube.fbx',use_selection=False,use_metadata=False\)
+ --md5_source=${TEST_OUT_DIR}/export_fbx_cube.fbx
+ --md5=ce937e605e493958464d62e6de4a2f9f --md5_method=FILE
+)
+
+add_test(export_fbx_nurbs ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ ${TEST_SRC_DIR}/io_tests/blend_geometry/nurbs.blend
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.export_scene.fbx\(filepath='${TEST_OUT_DIR}/export_fbx_nurbs.fbx',use_selection=False,use_metadata=False\)
+ --md5_source=${TEST_OUT_DIR}/export_fbx_nurbs.fbx
+ --md5=e02f0147afba2a4ce1ae110567ac3531 --md5_method=FILE
+)
+
+add_test(export_fbx_all_objects ${EXECUTABLE_OUTPUT_PATH}/blender ${GENERIC_ARGS}
+ ${TEST_SRC_DIR}/io_tests/blend_scene/all_objects.blend
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
+ --run={'FINISHED'}&bpy.ops.export_scene.fbx\(filepath='${TEST_OUT_DIR}/export_fbx_all_objects.fbx',use_selection=False,use_metadata=False\)
+ --md5_source=${TEST_OUT_DIR}/export_fbx_all_objects.fbx
+ --md5=c29a3aa600d2e432e4a521cc1e513ba8 --md5_method=FILE
+)
diff --git a/source/tests/bl_test.py b/source/tests/bl_test.py
new file mode 100644
index 00000000000..86c5cf81e79
--- /dev/null
+++ b/source/tests/bl_test.py
@@ -0,0 +1,195 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+import sys
+import os
+
+
+# may split this out into a new file
+def replace_bpy_app_version():
+ """ So MD5's are pradictable from output which uses blenders versions.
+ """
+
+ import bpy
+
+ app = bpy.app
+ app_fake = type(bpy)("bpy.app")
+
+ for attr in dir(app):
+ if not attr.startswith("_"):
+ setattr(app_fake, attr, getattr(app, attr))
+
+ app_fake.version = 0, 0, 0
+ app_fake.version_string = "0.00 (sub 0)"
+ bpy.app = app_fake
+
+
+def clear_startup_blend():
+ import bpy
+
+ for scene in bpy.data.scenes:
+ for obj in scene.objects:
+ scene.objects.unlink(obj)
+
+
+def blend_to_md5():
+ import bpy
+ scene = bpy.context.scene
+ ROUND = 4
+
+ def matrix2str(matrix):
+ return "".join([str(round(axis, ROUND)) for vector in matrix for axis in vector]).encode('ASCII')
+
+ def coords2str(seq, attr):
+ return "".join([str(round(axis, ROUND)) for vertex in seq for axis in getattr(vertex, attr)]).encode('ASCII')
+
+ import hashlib
+
+ md5 = hashlib.new("md5")
+ md5_update = md5.update
+
+ for obj in scene.objects:
+ md5_update(matrix2str(obj.matrix_world))
+ data = obj.data
+
+ if type(data) == bpy.types.Mesh:
+ md5_update(coords2str(data.vertices, "co"))
+ elif type(data) == bpy.types.Curve:
+ for spline in data.splines:
+ md5_update(coords2str(spline.bezier_points, "co"))
+ md5_update(coords2str(spline.points, "co"))
+
+ return md5.hexdigest()
+
+
+def main():
+ argv = sys.argv
+ print(" args:", " ".join(argv))
+ argv = argv[argv.index("--") + 1:]
+
+ def arg_extract(arg, optional=True, array=False):
+ arg += "="
+ if array:
+ value = []
+ else:
+ value = None
+
+ i = 0
+ while i < len(argv):
+ if argv[i].startswith(arg):
+ item = argv[i][len(arg):]
+ del argv[i]
+ i -= 1
+
+ if array:
+ value.append(item)
+ else:
+ value = item
+ break
+
+ i += 1
+
+ if (not value) and (not optional):
+ print(" '%s' not set" % arg)
+ sys.exit(1)
+
+ return value
+
+ run = arg_extract("--run", optional=False)
+ md5 = arg_extract("--md5", optional=False)
+ md5_method = arg_extract("--md5_method", optional=False) # 'SCENE' / 'FILE'
+
+ # only when md5_method is 'FILE'
+ md5_source = arg_extract("--md5_source", optional=True, array=True)
+
+ # save blend file, for testing
+ write_blend = arg_extract("--write-blend", optional=True)
+
+ # ensure files are written anew
+ for f in md5_source:
+ if os.path.exists(f):
+ os.remove(f)
+
+ import bpy
+
+ replace_bpy_app_version()
+ if not bpy.data.filepath:
+ clear_startup_blend()
+
+ print(" Running: '%s'" % run)
+ print(" MD5: '%s'!" % md5)
+
+ try:
+ result = eval(run)
+ except:
+ import traceback
+ traceback.print_exc()
+ sys.exit(1)
+
+ if write_blend is not None:
+ print(" Writing Blend: %s" % write_blend)
+ bpy.ops.wm.save_mainfile(filepath=write_blend, check_existing=False)
+
+ print(" Result: '%s'" % str(result))
+ if not result:
+ print(" Running: %s -> False" % run)
+ sys.exit(1)
+
+ if md5_method == 'SCENE':
+ md5_new = blend_to_md5()
+ elif md5_method == 'FILE':
+ if not md5_source:
+ print(" Missing --md5_source argument")
+ sys.exit(1)
+
+ for f in md5_source:
+ if not os.path.exists(f):
+ print(" Missing --md5_source=%r argument does not point to a file")
+ sys.exit(1)
+
+ import hashlib
+
+ md5_instance = hashlib.new("md5")
+ md5_update = md5_instance.update
+
+ for f in md5_source:
+ md5_update(open(f, "rb").read())
+
+ md5_new = md5_instance.hexdigest()
+
+ else:
+ print(" Invalid --md5_method=%s argument is not a valid source")
+ sys.exit(1)
+
+ if md5 != md5_new:
+ print(" Running: %s\n MD5 Recieved: %s\n MD5 Expected: %s" % (run, md5_new, md5))
+ sys.exit(1)
+
+ print(" Success: %s" % run)
+
+
+if __name__ == "__main__":
+ # So a python error exits(1)
+ try:
+ main()
+ except:
+ import traceback
+ traceback.print_exc()
+ sys.exit(1)
diff --git a/source/tests/pep8.py b/source/tests/pep8.py
new file mode 100644
index 00000000000..3ccd7dd79b6
--- /dev/null
+++ b/source/tests/pep8.py
@@ -0,0 +1,101 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+import os
+
+# depends on pep8, pyflakes, pylint
+# for ubuntu
+#
+# sudo apt-get install pylint pyflakes
+#
+# sudo apt-get install python-setuptools python-pip
+# sudo pip install pep8
+#
+# in debian install pylint pyflakes pep8 with apt-get/aptitude/etc
+#
+# on *nix run
+# python release/test/pep8.py > pep8_error.txt 2>&1
+
+# how many lines to read into the file, pep8 comment
+# should be directly after the licence header, ~20 in most cases
+PEP8_SEEK_COMMENT = 40
+SKIP_PREFIX = "./tools", "./config", "./scons", "./extern"
+
+
+def file_list_py(path):
+ for dirpath, dirnames, filenames in os.walk(path):
+ for filename in filenames:
+ if filename.endswith(".py"):
+ yield os.path.join(dirpath, filename)
+
+
+def is_pep8(path):
+ print(path)
+ f = open(path, 'r', encoding="utf8")
+ for i in range(PEP8_SEEK_COMMENT):
+ line = f.readline()
+ if line.startswith("# <pep8"):
+ if line.startswith("# <pep8 compliant>"):
+ return 1
+ elif line.startswith("# <pep8-80 compliant>"):
+ return 2
+ f.close()
+ return 0
+
+
+def main():
+ files = []
+ files_skip = []
+ for f in file_list_py("."):
+ if [None for prefix in SKIP_PREFIX if f.startswith(prefix)]:
+ continue
+
+ pep8_type = is_pep8(f)
+
+ if pep8_type:
+ # so we can batch them for each tool.
+ files.append((os.path.abspath(f), pep8_type))
+ else:
+ files_skip.append(f)
+
+ print("\nSkipping...")
+ for f in files_skip:
+ print(" %s" % f)
+
+ # pyflakes
+ print("\n\n\n# running pep8...")
+ for f, pep8_type in files:
+ if pep8_type == 1:
+ # E501:80 line length
+ os.system("pep8 --repeat --ignore=E501 '%s'" % (f))
+ else:
+ os.system("pep8 --repeat '%s'" % (f))
+
+ print("\n\n\n# running pyflakes...")
+ for f, pep8_type in files:
+ os.system("pyflakes '%s'" % f)
+
+ print("\n\n\n# running pylint...")
+ for f, pep8_type in files:
+ # let pep8 complain about line length
+ os.system("pylint --reports=n --max-line-length=1000 '%s'" % f)
+
+if __name__ == "__main__":
+ main()
diff --git a/source/tests/rna_array.py b/source/tests/rna_array.py
new file mode 100644
index 00000000000..06b4735cc0d
--- /dev/null
+++ b/source/tests/rna_array.py
@@ -0,0 +1,297 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+import unittest
+import random
+
+test= bpy.data.test
+
+# farr - 1-dimensional array of float
+# fdarr - dynamic 1-dimensional array of float
+# fmarr - 3-dimensional ([3][4][5]) array of float
+# fdmarr - dynamic 3-dimensional (ditto size) array of float
+
+# same as above for other types except that the first letter is "i" for int and "b" for bool
+
+class TestArray(unittest.TestCase):
+ # test that assignment works by: assign -> test value
+ # - rvalue = list of float
+ # - rvalue = list of numbers
+ # test.object
+ # bpy.data.test.farr[3], iarr[3], barr[...], fmarr, imarr, bmarr
+
+ def setUp(self):
+ test.farr= (1.0, 2.0, 3.0)
+ test.iarr= (7, 8, 9)
+ test.barr= (False, True, False)
+
+ # test access
+ # test slice access, negative indices
+ def test_access(self):
+ rvals= ([1.0, 2.0, 3.0], [7, 8, 9], [False, True, False])
+ for arr, rval in zip((test.farr, test.iarr, test.barr), rvals):
+ self.assertEqual(prop_to_list(arr), rval)
+ self.assertEqual(arr[0:3], rval)
+ self.assertEqual(arr[1:2], rval[1:2])
+ self.assertEqual(arr[-1], arr[2])
+ self.assertEqual(arr[-2], arr[1])
+ self.assertEqual(arr[-3], arr[0])
+
+ # fail when index out of bounds
+ def test_access_fail(self):
+ for arr in (test.farr, test.iarr, test.barr):
+ self.assertRaises(IndexError, lambda : arr[4])
+
+ # test assignment of a whole array
+ def test_assign_array(self):
+ # should accept int as float
+ test.farr= (1, 2, 3)
+
+ # fail when: unexpected no. of items, invalid item type
+ def test_assign_array_fail(self):
+ def assign_empty_list(arr):
+ setattr(test, arr, ())
+
+ for arr in ("farr", "iarr", "barr"):
+ self.assertRaises(ValueError, assign_empty_list, arr)
+
+ def assign_invalid_float():
+ test.farr= (1.0, 2.0, "3.0")
+
+ def assign_invalid_int():
+ test.iarr= ("1", 2, 3)
+
+ def assign_invalid_bool():
+ test.barr= (True, 0.123, False)
+
+ for func in [assign_invalid_float, assign_invalid_int, assign_invalid_bool]:
+ self.assertRaises(TypeError, func)
+
+ # shouldn't accept float as int
+ def assign_float_as_int():
+ test.iarr= (1, 2, 3.0)
+ self.assertRaises(TypeError, assign_float_as_int)
+
+ # non-dynamic arrays cannot change size
+ def assign_different_size(arr, val):
+ setattr(test, arr, val)
+ for arr, val in zip(("iarr", "farr", "barr"), ((1, 2), (1.0, 2.0), (True, False))):
+ self.assertRaises(ValueError, assign_different_size, arr, val)
+
+ # test assignment of specific items
+ def test_assign_item(self):
+ for arr, rand_func in zip((test.farr, test.iarr, test.barr), (rand_float, rand_int, rand_bool)):
+ for i in range(len(arr)):
+ val= rand_func()
+ arr[i]= val
+
+ self.assertEqual(arr[i], val)
+
+ # float prop should accept also int
+ for i in range(len(test.farr)):
+ val= rand_int()
+ test.farr[i]= val
+ self.assertEqual(test.farr[i], float(val))
+
+ #
+
+ def test_assign_item_fail(self):
+ def assign_bad_index(arr):
+ arr[4] = 1.0
+
+ def assign_bad_type(arr):
+ arr[1]= "123"
+
+ for arr in [test.farr, test.iarr, test.barr]:
+ self.assertRaises(IndexError, assign_bad_index, arr)
+
+ # not testing bool because bool allows not only (True|False)
+ for arr in [test.farr, test.iarr]:
+ self.assertRaises(TypeError, assign_bad_type, arr)
+
+ def test_dynamic_assign_array(self):
+ # test various lengths here
+ for arr, rand_func in zip(("fdarr", "idarr", "bdarr"), (rand_float, rand_int, rand_bool)):
+ for length in range(1, 64):
+ rval= make_random_array(length, rand_func)
+ setattr(test, arr, rval)
+ self.assertEqual(prop_to_list(getattr(test, arr)), rval)
+
+ def test_dynamic_assign_array_fail(self):
+ # could also test too big length here
+
+ def assign_empty_list(arr):
+ setattr(test, arr, ())
+
+ for arr in ("fdarr", "idarr", "bdarr"):
+ self.assertRaises(ValueError, assign_empty_list, arr)
+
+
+class TestMArray(unittest.TestCase):
+ def setUp(self):
+ # reset dynamic array sizes
+ for arr, func in zip(("fdmarr", "idmarr", "bdmarr"), (rand_float, rand_int, rand_bool)):
+ setattr(test, arr, make_random_3d_array((3, 4, 5), func))
+
+ # test assignment
+ def test_assign_array(self):
+ for arr, func in zip(("fmarr", "imarr", "bmarr"), (rand_float, rand_int, rand_bool)):
+ # assignment of [3][4][5]
+ rval= make_random_3d_array((3, 4, 5), func)
+ setattr(test, arr, rval)
+ self.assertEqual(prop_to_list(getattr(test, arr)), rval)
+
+ # test assignment of [2][4][5], [1][4][5] should work on dynamic arrays
+
+ def test_assign_array_fail(self):
+ def assign_empty_array():
+ test.fmarr= ()
+ self.assertRaises(ValueError, assign_empty_array)
+
+ def assign_invalid_size(arr, rval):
+ setattr(test, arr, rval)
+
+ # assignment of 3,4,4 or 3,3,5 should raise ex
+ for arr, func in zip(("fmarr", "imarr", "bmarr"), (rand_float, rand_int, rand_bool)):
+ rval= make_random_3d_array((3, 4, 4), func)
+ self.assertRaises(ValueError, assign_invalid_size, arr, rval)
+
+ rval= make_random_3d_array((3, 3, 5), func)
+ self.assertRaises(ValueError, assign_invalid_size, arr, rval)
+
+ rval= make_random_3d_array((3, 3, 3), func)
+ self.assertRaises(ValueError, assign_invalid_size, arr, rval)
+
+ def test_assign_item(self):
+ # arr[i] = x
+ for arr, func in zip(("fmarr", "imarr", "bmarr", "fdmarr", "idmarr", "bdmarr"), (rand_float, rand_int, rand_bool) * 2):
+ rval= make_random_2d_array((4, 5), func)
+
+ for i in range(3):
+ getattr(test, arr)[i]= rval
+ self.assertEqual(prop_to_list(getattr(test, arr)[i]), rval)
+
+ # arr[i][j] = x
+ for arr, func in zip(("fmarr", "imarr", "bmarr", "fdmarr", "idmarr", "bdmarr"), (rand_float, rand_int, rand_bool) * 2):
+
+ arr= getattr(test, arr)
+ rval= make_random_array(5, func)
+
+ for i in range(3):
+ for j in range(4):
+ arr[i][j]= rval
+ self.assertEqual(prop_to_list(arr[i][j]), rval)
+
+
+ def test_assign_item_fail(self):
+ def assign_wrong_size(arr, i, rval):
+ getattr(test, arr)[i]= rval
+
+ # assign wrong size at level 2
+ for arr, func in zip(("fmarr", "imarr", "bmarr"), (rand_float, rand_int, rand_bool)):
+ rval1= make_random_2d_array((3, 5), func)
+ rval2= make_random_2d_array((4, 3), func)
+
+ for i in range(3):
+ self.assertRaises(ValueError, assign_wrong_size, arr, i, rval1)
+ self.assertRaises(ValueError, assign_wrong_size, arr, i, rval2)
+
+ def test_dynamic_assign_array(self):
+ for arr, func in zip(("fdmarr", "idmarr", "bdmarr"), (rand_float, rand_int, rand_bool)):
+ # assignment of [3][4][5]
+ rval= make_random_3d_array((3, 4, 5), func)
+ setattr(test, arr, rval)
+ self.assertEqual(prop_to_list(getattr(test, arr)), rval)
+
+ # [2][4][5]
+ rval= make_random_3d_array((2, 4, 5), func)
+ setattr(test, arr, rval)
+ self.assertEqual(prop_to_list(getattr(test, arr)), rval)
+
+ # [1][4][5]
+ rval= make_random_3d_array((1, 4, 5), func)
+ setattr(test, arr, rval)
+ self.assertEqual(prop_to_list(getattr(test, arr)), rval)
+
+
+ # test access
+ def test_access(self):
+ pass
+
+ # test slice access, negative indices
+ def test_access_fail(self):
+ pass
+
+random.seed()
+
+def rand_int():
+ return random.randint(-1000, 1000)
+
+def rand_float():
+ return float(rand_int())
+
+def rand_bool():
+ return bool(random.randint(0, 1))
+
+def make_random_array(len, rand_func):
+ arr= []
+ for i in range(len):
+ arr.append(rand_func())
+
+ return arr
+
+def make_random_2d_array(dimsize, rand_func):
+ marr= []
+ for i in range(dimsize[0]):
+ marr.append([])
+
+ for j in range(dimsize[1]):
+ marr[-1].append(rand_func())
+
+ return marr
+
+def make_random_3d_array(dimsize, rand_func):
+ marr= []
+ for i in range(dimsize[0]):
+ marr.append([])
+
+ for j in range(dimsize[1]):
+ marr[-1].append([])
+
+ for k in range(dimsize[2]):
+ marr[-1][-1].append(rand_func())
+
+ return marr
+
+def prop_to_list(prop):
+ ret= []
+
+ for x in prop:
+ if type(x) not in (bool, int, float):
+ ret.append(prop_to_list(x))
+ else:
+ ret.append(x)
+
+ return ret
+
+def suite():
+ return unittest.TestSuite([unittest.TestLoader().loadTestsFromTestCase(TestArray), unittest.TestLoader().loadTestsFromTestCase(TestMArray)])
+
+if __name__ == "__main__":
+ unittest.TextTestRunner(verbosity=2).run(suite())
+
diff --git a/source/tests/rna_info_dump.py b/source/tests/rna_info_dump.py
new file mode 100644
index 00000000000..62c1248d733
--- /dev/null
+++ b/source/tests/rna_info_dump.py
@@ -0,0 +1,131 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+# Used for generating API diff's between releases
+# ./blender.bin --background --python release/test/rna_info_dump.py
+
+import bpy
+
+
+def api_dump(use_properties=True, use_functions=True):
+
+ def prop_type(prop):
+ if prop.type == "pointer":
+ return prop.fixed_type.identifier
+ else:
+ return prop.type
+
+ def func_to_str(struct_id_str, func_id, func):
+
+ args = []
+ for prop in func.args:
+ data_str = "%s %s" % (prop_type(prop), prop.identifier)
+ if prop.array_length:
+ data_str += "[%d]" % prop.array_length
+ if not prop.is_required:
+ data_str += "=%s" % prop.default_str
+ args.append(data_str)
+
+ data_str = "%s.%s(%s)" % (struct_id_str, func_id, ", ".join(args))
+ if func.return_values:
+ return_args = ", ".join(prop_type(arg) for arg in func.return_values)
+ if len(func.return_values) > 1:
+ data_str += " --> (%s)" % return_args
+ else:
+ data_str += " --> %s" % return_args
+ return data_str
+
+ def prop_to_str(struct_id_str, prop_id, prop):
+
+ prop_str = " <-- %s" % prop_type(prop)
+ if prop.array_length:
+ prop_str += "[%d]" % prop.array_length
+
+ data_str = "%s.%s %s" % (struct_id_str, prop_id, prop_str)
+ return data_str
+
+ def struct_full_id(v):
+ struct_id_str = v.identifier # "".join(sid for sid in struct_id if struct_id)
+
+ for base in v.get_bases():
+ struct_id_str = base.identifier + "|" + struct_id_str
+
+ return struct_id_str
+
+ def dump_funcs():
+ data = []
+ for struct_id, v in sorted(struct.items()):
+ struct_id_str = struct_full_id(v)
+
+ funcs = [(func.identifier, func) for func in v.functions]
+
+ for func_id, func in funcs:
+ data.append(func_to_str(struct_id_str, func_id, func))
+
+ for prop in v.properties:
+ if prop.collection_type:
+ funcs = [(prop.identifier + "." + func.identifier, func) for func in prop.collection_type.functions]
+ for func_id, func in funcs:
+ data.append(func_to_str(struct_id_str, func_id, func))
+ data.sort()
+ data.append("# * functions *")
+ return data
+
+ def dump_props():
+ data = []
+ for struct_id, v in sorted(struct.items()):
+ struct_id_str = struct_full_id(v)
+
+ props = [(prop.identifier, prop) for prop in v.properties]
+
+ for prop_id, prop in props:
+ data.append(prop_to_str(struct_id_str, prop_id, prop))
+
+ for prop in v.properties:
+ if prop.collection_type:
+ props = [(prop.identifier + "." + prop_sub.identifier, prop_sub) for prop_sub in prop.collection_type.properties]
+ for prop_sub_id, prop_sub in props:
+ data.append(prop_to_str(struct_id_str, prop_sub_id, prop_sub))
+ data.sort()
+ data.insert(0, "# * properties *")
+ return data
+
+ import rna_info
+ struct = rna_info.BuildRNAInfo()[0]
+ data = []
+
+ if use_functions:
+ data.extend(dump_funcs())
+
+ if use_properties:
+ data.extend(dump_props())
+
+ if bpy.app.background:
+ import sys
+ sys.stderr.write("\n".join(data))
+ sys.stderr.write("\n\nEOF\n")
+ else:
+ text = bpy.data.texts.new(name="api.py")
+ text.from_string(data)
+
+ print("END")
+
+if __name__ == "__main__":
+ api_dump()