diff options
Diffstat (limited to 'tests')
16 files changed, 743 insertions, 522 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7db0874..20d4dc4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,6 @@ # instructions - see ../doc/testing.txt -# set(DEBUG_OSCD 1) # print debug info during cmake +#set(DEBUG_OSCD 1) # print debug info during cmake cmake_minimum_required(VERSION 2.8) if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3) @@ -15,8 +15,15 @@ include(CMakeParseArguments.cmake) # Detect Lion and force gcc IF (APPLE) EXECUTE_PROCESS(COMMAND sw_vers -productVersion OUTPUT_VARIABLE MACOSX_VERSION) - IF (NOT ${MACOSX_VERSION} VERSION_LESS "10.8.0") - message("Detected Mountain Lion (10.8) or later") + IF (NOT ${MACOSX_VERSION} VERSION_LESS "10.9.0") + message("Detected Maverick (10.9) or later") + set(CMAKE_C_COMPILER "clang") + set(CMAKE_CXX_COMPILER "clang++") + # Somehow, since we build dependencies for 10.7, we need to also build executables + # for 10.7. This used to not be necessary, but since 10.9 it apparently is.. + SET(CMAKE_OSX_DEPLOYMENT_TARGET 10.7 CACHE STRING "Deployment target") + ELSEIF (NOT ${MACOSX_VERSION} VERSION_LESS "10.8.0") + message("Detected Mountain Lion (10.8)") set(CMAKE_C_COMPILER "clang") set(CMAKE_CXX_COMPILER "clang++") ELSEIF (NOT ${MACOSX_VERSION} VERSION_LESS "10.7.0") @@ -359,10 +366,10 @@ if (NOT $ENV{CGALDIR} STREQUAL "") elseif (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "") if (EXISTS "$ENV{OPENSCAD_LIBRARIES}/lib/CGAL") set(CGAL_DIR "$ENV{OPENSCAD_LIBRARIES}/lib/CGAL") - set(CMAKE_MODULE_PATH "${CGAL_DIR}") + set(CMAKE_MODULE_PATH "${CGAL_DIR}" ${CMAKE_MODULE_PATH}) elseif (EXISTS "$ENV{OPENSCAD_LIBRARIES}/include/CGAL") set(CGAL_DIR "$ENV{OPENSCAD_LIBRARIES}") - set(CMAKE_MODULE_PATH "${CGAL_DIR}") + set(CMAKE_MODULE_PATH "${CGAL_DIR}" ${CMAKE_MODULE_PATH}) endif() endif() message(STATUS "CGAL_DIR: " ${CGAL_DIR}) @@ -376,12 +383,40 @@ if("${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}" VERSION_LESS 3.6) message(FATAL_ERROR "CGAL >= 3.6 required") endif() inclusion(CGAL_DIR CGAL_INCLUDE_DIRS) +#Remove bad BOOST libraries from CGAL 3rd party dependencies when they don't exist (such as on 64-bit Ubuntu 13.10). +#Libs of concern are /usr/lib/libboost_thread.so;/usr/lib/libboost_system.so; +#Confirmed bug in CGAL @ https://bugs.launchpad.net/ubuntu/+source/cgal/+bug/1242111 +string(FIND "${CGAL_3RD_PARTY_LIBRARIES}" "/usr/lib/libboost_system.so" FIND_POSITION ) +if(NOT "-1" STREQUAL ${FIND_POSITION} ) + if(NOT EXISTS "/usr/lib/libboost_system.so") + MESSAGE( STATUS "CGAL_3RD_PARTY_LIBRARIES:Removing non-existent /usr/lib/libboost_system.so" ) + string(REPLACE "/usr/lib/libboost_system.so" "" CGAL_3RD_PARTY_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES}) + endif() +endif() +string(FIND "${CGAL_3RD_PARTY_LIBRARIES}" "/usr/lib/libboost_thread.so" FIND_POSITION ) +if(NOT "-1" STREQUAL ${FIND_POSITION} ) + if(NOT EXISTS "/usr/lib/libboost_thread.so") + MESSAGE( STATUS "CGAL_3RD_PARTY_LIBRARIES:Removing non-existent /usr/lib/libboost_thread.so" ) + string(REPLACE "/usr/lib/libboost_thread.so" "" CGAL_3RD_PARTY_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES}) + endif() +endif() if(${CMAKE_CXX_COMPILER} MATCHES ".*clang.*" AND NOT ${CGAL_CXX_FLAGS_INIT} STREQUAL "" ) string(REPLACE "-frounding-math" "" CGAL_CXX_FLAGS_INIT ${CGAL_CXX_FLAGS_INIT}) string(REPLACE "--param=ssp-buffer-size=4" "" CGAL_CXX_FLAGS_INIT ${CGAL_CXX_FLAGS_INIT}) endif() +if (NOT $ENV{OPENSCAD_LIBRARIES} STREQUAL "") + # Force pkg-config to look _only_ in the local library folder + # in case OPENSCAD_LIBRARIES is set. + set(ENV{PKG_CONFIG_PATH} "$ENV{OPENSCAD_LIBRARIES}/lib/pkgconfig") + set(ENV{PKG_CONFIG_LIBDIR} "$ENV{OPENSCAD_LIBRARIES}/lib/pkgconfig") +endif() + +find_package(GLIB2 2.2.0 REQUIRED) +add_definitions(${GLIB2_DEFINITIONS}) +inclusion(GLIB2_DIR GLIB2_INCLUDE_DIRS) + # Imagemagick if (SKIP_IMAGEMAGICK) @@ -553,8 +588,8 @@ set(OFFSCREEN_SOURCES ../src/OpenCSGRenderer.cc) add_library(tests-core STATIC ${CORE_SOURCES}) -target_link_libraries(tests-core ${OPENGL_LIBRARIES}) -set(TESTS-CORE-LIBRARIES ${OPENGL_LIBRARIES} ${Boost_LIBRARIES}) +target_link_libraries(tests-core ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} ) +set(TESTS-CORE-LIBRARIES ${OPENGL_LIBRARIES} ${GLIB2_LIBRARIES} ${Boost_LIBRARIES} ) add_library(tests-common STATIC ${COMMON_SOURCES}) target_link_libraries(tests-common tests-core) @@ -574,7 +609,7 @@ set(TESTS-NOCGAL-LIBRARIES ${TESTS-CORE-LIBRARIES}) # modulecachetest # add_executable(modulecachetest modulecachetest.cc) -target_link_libraries(modulecachetest tests-nocgal ${TESTS-NOCGAL-LIBRARIES} ${Boost_LIBRARIES}) +target_link_libraries(modulecachetest tests-nocgal ${TESTS-NOCGAL-LIBRARIES}) # # csgtexttest @@ -594,7 +629,7 @@ target_link_libraries(cgalcachetest tests-cgal ${TESTS-CGAL-LIBRARIES} ${GLEW_LI # add_executable(openscad_nogui ../src/openscad.cc) set_target_properties(openscad_nogui PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -DEIGEN_DONT_ALIGN -DENABLE_CGAL -DENABLE_OPENCSG ${CGAL_CXX_FLAGS_INIT}") -target_link_libraries(openscad_nogui tests-offscreen tests-cgal tests-nocgal ${TESTS-CORE-LIBRARIES} ${TESTS-CGAL-LIBRARIES} ${GLEW_LIBRARY} ${Boost_LIBRARIES} ${OPENCSG_LIBRARY} ${COCOA_LIBRARY} ) +target_link_libraries(openscad_nogui tests-offscreen tests-cgal tests-nocgal ${TESTS-CORE-LIBRARIES} ${TESTS-CGAL-LIBRARIES} ${GLEW_LIBRARY} ${OPENCSG_LIBRARY} ${COCOA_LIBRARY} ) # # GUI binary tests @@ -774,8 +809,10 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES} ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/dim-all.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/string-test.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/string-indexing.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/string-unicode.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/vector-values.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/search-tests.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/search-tests-unicode.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests2.scad @@ -795,13 +832,15 @@ list(APPEND DUMPTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/escape-test ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allexpressions.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allfunctions.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allmodules.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/nonplanar_polyhedron.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/nonplanar_polyhedron.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/stl-cgal-convert_to_Polyhedron-crash.scad) list(APPEND CGALPNGTEST_FILES ${FEATURES_FILES} ${SCAD_DXF_FILES} ${EXAMPLE_FILES}) list(APPEND CGALPNGTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/include-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/use-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/transform-nan-inf-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/nonplanar_polyhedron.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/stl-cgal-convert_to_Polyhedron-crash.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles-test.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles_dir/localfiles-compatibility-test.scad) @@ -824,6 +863,10 @@ disable_tests(openscad-csgpng_child-background) disable_tests(opencsgtest_example006 cgalpngtest_example006) disable_tests(openscad-csgpng_example006 openscad-cgalpng_example006) +# NefPolyhedron->Polyhedron conversion failures. No images for OpenCSG/Thrown +disable_tests(opencsgtest_stl-cgal-convert_to_Polyhedron-crash) +disable_tests(throwntogethertest_stl-cgal-convert_to_Polyhedron-crash) + # These tests only makes sense in OpenCSG mode disable_tests(cgalpngtest_child-background cgalpngtest_highlight-and-background-modifier @@ -893,6 +936,14 @@ string(REPLACE __header__ "Generated by cmake from ${CMAKE_CURRENT_SOURCE_DIR}/C string(REPLACE __cmake_system_name__ ${CMAKE_SYSTEM_NAME} TMP ${TMP}) string(REPLACE __openscad_binpath__ ${OPENSCAD_BINPATH} TMP ${TMP}) +set(OPENSCAD_UPLOAD_TESTS $ENV{OPENSCAD_UPLOAD_TESTS}) +if (OPENSCAD_UPLOAD_TESTS) + set(UPLOADARG "--upload") +endif() +if (UPLOADARG) + string(REPLACE __openscad_upload_tests__ ${UPLOADARG} TMP ${TMP}) +endif() + if (MINGW_CROSS_ENV_DIR) string(REPLACE __wine__ wine TMP ${TMP}) else() diff --git a/tests/CTestCustom.template b/tests/CTestCustom.template index 3f82d73..a01f2b5 100644 --- a/tests/CTestCustom.template +++ b/tests/CTestCustom.template @@ -63,7 +63,12 @@ endif() message("running '__openscad_binpath__ --info' to generate sysinfo.txt") execute_process(COMMAND __wine__ __openscad_binpath__ --info OUTPUT_FILE sysinfo.txt) -set(CTEST_CUSTOM_POST_TEST ${CTEST_CUSTOM_POST_TEST} "__cmake_current_binary_dir__/test_pretty_print") + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_LESS 2.8.12) + set(CTEST_CUSTOM_POST_TEST ${CTEST_CUSTOM_POST_TEST} "__cmake_current_binary_dir__/test_pretty_print") +else() + set(CTEST_CUSTOM_POST_TEST ${CTEST_CUSTOM_POST_TEST} "__python__ __cmake_current_source_dir__/test_pretty_print.py --builddir=__cmake_current_binary_dir__ __openscad_upload_tests__") +endif() if ( ${debug_openscad_template} ) foreach(post_test ${CTEST_CUSTOM_POST_TEST} ) diff --git a/tests/FindGLIB2.cmake b/tests/FindGLIB2.cmake new file mode 100644 index 0000000..9164c39 --- /dev/null +++ b/tests/FindGLIB2.cmake @@ -0,0 +1,28 @@ +find_package(PkgConfig REQUIRED) + +pkg_search_module(GLIB2 REQUIRED glib-2.0) +#message("GLIB2_LIBRARIES ${GLIB2_LIBRARIES}") +message("GLIB2_LIBRARY_DIRS ${GLIB2_LIBRARY_DIRS}") +#message("GLIB2_LDFLAGS ${GLIB2_LDFLAGS}") +#message("GLIB2_LDFLAGS_OTHER ${GLIB2_LDFLAGS_OTHER}") +message("GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS}") +#message("GLIB2_CFLAGS ${GLIB2_CFLAGS}") +#message("GLIB2_CFLAGS_OTHER ${GLIB2_CFLAGS_OTHER}") +message("GLIB2_LIBDIR ${GLIB2_LIBDIR}") + +set(GLIB2_DEFINITIONS ${GLIB2_CFLAGS_OTHER}) +#message("GLIB2_DEFINITIONS ${GLIB2_DEFINITIONS}") + +set(GLIB2_LIBRARY_NAMES ${GLIB2_LIBRARIES}) +set(GLIB2_LIBRARIES "") +foreach(GLIB2_LIB ${GLIB2_LIBRARY_NAMES}) +# message("lib: ${GLIB2_LIB}") + set(TMP TMP-NOTFOUND) + find_library(TMP NAMES ${GLIB2_LIB} + PATHS ${GLIB2_LIBRARY_DIRS} + PATHS ${GLIB2_LIBDIR} + NO_DEFAULT_PATH) +# message("TMP: ${TMP}") + list(APPEND GLIB2_LIBRARIES "${TMP}") +endforeach() +message("GLIB2_LIBRARIES: ${GLIB2_LIBRARIES}") diff --git a/tests/regression/cgalpngtest/polyhedron-tests-expected.png b/tests/regression/cgalpngtest/polyhedron-tests-expected.png Binary files differindex c80990f..322160d 100644 --- a/tests/regression/cgalpngtest/polyhedron-tests-expected.png +++ b/tests/regression/cgalpngtest/polyhedron-tests-expected.png diff --git a/tests/regression/cgalpngtest/rotate_extrude-tests-expected.png b/tests/regression/cgalpngtest/rotate_extrude-tests-expected.png Binary files differindex 1488c85..d198344 100644 --- a/tests/regression/cgalpngtest/rotate_extrude-tests-expected.png +++ b/tests/regression/cgalpngtest/rotate_extrude-tests-expected.png diff --git a/tests/regression/cgalpngtest/stl-cgal-convert_to_Polyhedron-crash-expected.png b/tests/regression/cgalpngtest/stl-cgal-convert_to_Polyhedron-crash-expected.png Binary files differnew file mode 100644 index 0000000..318cbaa --- /dev/null +++ b/tests/regression/cgalpngtest/stl-cgal-convert_to_Polyhedron-crash-expected.png diff --git a/tests/regression/dumptest/polyhedron-tests-expected.csg b/tests/regression/dumptest/polyhedron-tests-expected.csg index 1bb36d9..dabdf94 100644 --- a/tests/regression/dumptest/polyhedron-tests-expected.csg +++ b/tests/regression/dumptest/polyhedron-tests-expected.csg @@ -7,6 +7,9 @@ group() { multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], faces = [[0, 2, 4], [0, 5, 2], [0, 4, 3], [0, 3, 5], [1, 4, 2], [1, 2, 5], [1, 3, 4], [1, 5, 3]], convexity = 1); } + multmatrix([[1, 0, 0, 6], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + polyhedron(points = [[-0.8, -0.8, -0.8], [0, 0, -0.8], [0.8, -0.8, -0.8], [0.8, 0.8, -0.8], [-0.8, 0.8, -0.8], [-0.8, -0.8, 0.8], [0, 0, 0.8], [0.8, -0.8, 0.8], [0.8, 0.8, 0.8], [-0.8, 0.8, 0.8]], triangles = [[0, 1, 2, 3, 4], [5, 6, 1, 0], [6, 7, 2, 1], [7, 8, 3, 2], [8, 9, 4, 3], [9, 5, 0, 4], [9, 8, 7, 6, 5]], convexity = 2); + } } multmatrix([[1, 0, 0, 0], [0, 1, 0, 2], [0, 0, 1, 0], [0, 0, 0, 1]]) { difference() { @@ -18,8 +21,11 @@ group() { multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], faces = [[0, 2, 4], [0, 5, 2], [0, 4, 3], [0, 3, 5], [1, 4, 2], [1, 2, 5], [1, 3, 4], [1, 5, 3]], convexity = 1); } + multmatrix([[1, 0, 0, 6], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + polyhedron(points = [[-0.8, -0.8, -0.8], [0, 0, -0.8], [0.8, -0.8, -0.8], [0.8, 0.8, -0.8], [-0.8, 0.8, -0.8], [-0.8, -0.8, 0.8], [0, 0, 0.8], [0.8, -0.8, 0.8], [0.8, 0.8, 0.8], [-0.8, 0.8, 0.8]], triangles = [[0, 1, 2, 3, 4], [5, 6, 1, 0], [6, 7, 2, 1], [7, 8, 3, 2], [8, 9, 4, 3], [9, 5, 0, 4], [9, 8, 7, 6, 5]], convexity = 2); + } } - multmatrix([[1, 0, 0, 2], [0, 1, 0, 0], [0, 0, 1, 2], [0, 0, 0, 1]]) { + multmatrix([[1, 0, 0, 3], [0, 1, 0, 0], [0, 0, 1, 2], [0, 0, 0, 1]]) { cube(size = [8, 3, 3], center = true); } } diff --git a/tests/regression/dumptest/rotate_extrude-tests-expected.csg b/tests/regression/dumptest/rotate_extrude-tests-expected.csg index a86dd8f..d010bfd 100644 --- a/tests/regression/dumptest/rotate_extrude-tests-expected.csg +++ b/tests/regression/dumptest/rotate_extrude-tests-expected.csg @@ -50,4 +50,11 @@ group() { } } } + multmatrix([[1, 0, 0, 0], [0, 1, 0, 60], [0, 0, 1, 0], [0, 0, 0, 1]]) { + rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + multmatrix([[1, 0, 0, -20], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + square(size = [10, 10], center = false); + } + } + } } diff --git a/tests/regression/dumptest/stl-cgal-convert_to_Polyhedron-crash-expected.csg b/tests/regression/dumptest/stl-cgal-convert_to_Polyhedron-crash-expected.csg new file mode 100644 index 0000000..acad52f --- /dev/null +++ b/tests/regression/dumptest/stl-cgal-convert_to_Polyhedron-crash-expected.csg @@ -0,0 +1,5 @@ +group() { + render(convexity = 1) { + import(file = "stl-cgal-convert_to_Polyhedron-crash.stl", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + } +} diff --git a/tests/regression/echotest/search-tests-unicode-expected.echo b/tests/regression/echotest/search-tests-unicode-expected.echo new file mode 100644 index 0000000..801bc8c --- /dev/null +++ b/tests/regression/echotest/search-tests-unicode-expected.echo @@ -0,0 +1,109 @@ +ECHO: "----- Lookup of 1 byte into 1 byte" +ECHO: "Expect [0] for search(a, aaaa)=[0]. OK" +ECHO: "Expect [0] for search(a, aaaa, 1)=[0]. OK" +ECHO: "Expect [0, 0] for search(aa, aaaa)=[0, 0]. OK" +ECHO: "Expect [0, 0] for search(aa, aaaa, 1)=[0, 0]. OK" +ECHO: "Expect [[0, 1, 2, 3]] for search(a, aaaa, 0)=[[0, 1, 2, 3]]. OK" +ECHO: "Expect [[0, 1]] for search(a, aaaa, 2)=[[0, 1]]. OK" +ECHO: "Expect [[0, 1, 2]] for search(a, aaaa, 3)=[[0, 1, 2]]. OK" +ECHO: "Expect [[0, 1, 2, 3]] for search(a, aaaa, 4)=[[0, 1, 2, 3]]. OK" +ECHO: "Expect [[0, 1, 2, 3], [0, 1, 2, 3]] for search(aa, aaaa, 0)=[[0, 1, 2, 3], [0, 1, 2, 3]]. OK" + WARNING: search term not found: "b" +ECHO: "Expect [] for search(b, aaaa)=[]. OK" + WARNING: search term not found: "b" +ECHO: "Expect [] for search(b, aaaa, 1)=[]. OK" + WARNING: search term not found: "b" +ECHO: "Expect [[]] for search(b, aaaa, 0)=[[]]. OK" + WARNING: search term not found: "b" +ECHO: "Expect [[]] for search(b, aaaa, 2)=[[]]. OK" + WARNING: search term not found: "b" + WARNING: search term not found: "b" +ECHO: "Expect [] for search(bb, aaaa)=[]. OK" + WARNING: search term not found: "b" + WARNING: search term not found: "b" +ECHO: "Expect [] for search(bb, aaaa, 1)=[]. OK" + WARNING: search term not found: "b" + WARNING: search term not found: "b" +ECHO: "Expect [[], []] for search(bb, aaaa, 0)=[[], []]. OK" + WARNING: search term not found: "b" + WARNING: search term not found: "b" +ECHO: "Expect [[], []] for search(bb, aaaa, 2)=[[], []]. OK" +ECHO: "Expect [] for search(, aaaa)=[]. OK" +ECHO: "Expect [] for search(, )=[]. OK" + WARNING: search term not found: "a" +ECHO: "Expect [] for search(a, )=[]. OK" +ECHO: "----- Lookup of multi-byte into 1 byte" + WARNING: search term not found: "Π" +ECHO: "Expect [] for search(Π, aaaa)=[]. OK" + WARNING: search term not found: "π‘" +ECHO: "Expect [] for search(π‘, aaaa)=[]. OK" + WARNING: search term not found: "Π" +ECHO: "Expect [[]] for search(Π, aaaa, 0)=[[]]. OK" + WARNING: search term not found: "π‘" +ECHO: "Expect [[]] for search(π‘, aaaa, 0)=[[]]. OK" + WARNING: search term not found: "Π" + WARNING: search term not found: "Π" +ECHO: "Expect [] for search(ΠΠ, aaaa)=[]. OK" + WARNING: search term not found: "π‘" + WARNING: search term not found: "π‘" +ECHO: "Expect [] for search(π‘π‘, aaaa)=[]. OK" + WARNING: search term not found: "Π" + WARNING: search term not found: "Π" +ECHO: "Expect [[], []] for search(ΠΠ, aaaa, 0)=[[], []]. OK" + WARNING: search term not found: "π‘" + WARNING: search term not found: "π‘" +ECHO: "Expect [[], []] for search(π‘π‘, aaaa, 0)=[[], []]. OK" +ECHO: "----- Lookup of 1-byte into multi-byte" + WARNING: search term not found: "a" +ECHO: "Expect [] for search(a, ΠΠΠΠ)=[]. OK" + WARNING: search term not found: "a" +ECHO: "Expect [] for search(a, π‘π‘π‘π‘)=[]. OK" + WARNING: search term not found: "a" +ECHO: "Expect [] for search(a, ΠΠΠΠ, 1)=[]. OK" + WARNING: search term not found: "a" +ECHO: "Expect [[]] for search(a, π‘π‘π‘π‘, 0)=[[]]. OK" + WARNING: search term not found: "a" +ECHO: "Expect [[]] for search(a, π‘π‘π‘π‘, 2)=[[]]. OK" +ECHO: "----- Lookup of 1-byte into mixed multi-byte" +ECHO: "Expect [0] for search(a, aΠaΠaΠaΠa)=[0]. OK" +ECHO: "Expect [0] for search(a, aπ‘aπ‘aπ‘aπ‘a)=[0]. OK" +ECHO: "Expect [0] for search(a, aπ‘Ππ‘aπ‘Ππ‘a)=[0]. OK" +ECHO: "Expect [[0, 2, 4, 6, 8]] for search(a, aΠaΠaΠaΠa, 0)=[[0, 2, 4, 6, 8]]. OK" +ECHO: "Expect [[0, 2, 4, 6, 8]] for search(a, aπ‘aπ‘aπ‘aπ‘a, 0)=[[0, 2, 4, 6, 8]]. OK" +ECHO: "Expect [[0, 4, 8]] for search(a, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[0, 4, 8]]. OK" +ECHO: "----- Lookup of 2-byte into 2-byte" +ECHO: "Expect [0] for search(Π, ΠΠΠΠ)=[0]. OK" +ECHO: "Expect [[0, 1, 2, 3]] for search(Π, ΠΠΠΠ, 0)=[[0, 1, 2, 3]]. OK" +ECHO: "----- Lookup of 2-byte into 4-byte" + WARNING: search term not found: "Π" +ECHO: "Expect [] for search(Π, π‘π‘π‘π‘)=[]. OK" +ECHO: "----- Lookup of 4-byte into 4-byte" +ECHO: "Expect [0] for search(π‘, π‘π‘π‘π‘)=[0]. OK" +ECHO: "Expect [[0, 1, 2, 3]] for search(π‘, π‘π‘π‘π‘, 0)=[[0, 1, 2, 3]]. OK" +ECHO: "----- Lookup of 4-byte into 2-byte" + WARNING: search term not found: "π‘" +ECHO: "Expect [] for search(π‘, ΠΠΠΠ)=[]. OK" +ECHO: "----- Lookup of 2-byte into mixed multi-byte" +ECHO: "Expect [1] for search(Π, aΠaΠaΠaΠa, 1)=[1]. OK" + WARNING: search term not found: "Π" +ECHO: "Expect [] for search(Π, aπ‘aπ‘aπ‘aπ‘a, 1)=[]. OK" +ECHO: "Expect [2] for search(Π, aπ‘Ππ‘aπ‘Ππ‘a, 1)=[2]. OK" +ECHO: "Expect [[1, 3, 5, 7]] for search(Π, aΠaΠaΠaΠa, 0)=[[1, 3, 5, 7]]. OK" + WARNING: search term not found: "Π" +ECHO: "Expect [[]] for search(Π, aπ‘aπ‘aπ‘aπ‘a, 0)=[[]]. OK" +ECHO: "Expect [[2, 6]] for search(Π, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[2, 6]]. OK" +ECHO: "----- Lookup of 4-byte into mixed multi-byte" + WARNING: search term not found: "π‘" +ECHO: "Expect [] for search(π‘, aΠaΠaΠaΠa, 1)=[]. OK" +ECHO: "Expect [1] for search(π‘, aπ‘aπ‘aπ‘aπ‘a, 1)=[1]. OK" + WARNING: search term not found: "π‘" +ECHO: "Expect [[]] for search(π‘, aΠaΠaΠaΠa, 0)=[[]]. OK" +ECHO: "Expect [[1, 3, 5, 7]] for search(π‘, aπ‘aπ‘aπ‘aπ‘a, 0)=[[1, 3, 5, 7]]. OK" +ECHO: "Expect [[1, 3, 5, 7]] for search(π‘, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[1, 3, 5, 7]]. OK" +ECHO: "----- Lookup of mixed multi-byte into mixed multi-byte" + WARNING: search term not found: "π‘" +ECHO: "Expect [[0, 2, 4, 6, 8], [1, 3, 5, 7], []] for search(aΠπ‘, aΠaΠaΠaΠa, 0)=[[0, 2, 4, 6, 8], [1, 3, 5, 7], []]. OK" + WARNING: search term not found: "Π" +ECHO: "Expect [[0, 2, 4, 6, 8], [], [1, 3, 5, 7]] for search(aΠπ‘, aπ‘aπ‘aπ‘aπ‘a, 0)=[[0, 2, 4, 6, 8], [], [1, 3, 5, 7]]. OK" +ECHO: "Expect [[0, 4, 8], [2, 6], [1, 3, 5, 7]] for search(aΠπ‘, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[0, 4, 8], [2, 6], [1, 3, 5, 7]]. OK" +ECHO: "Expect [[1, 3, 5, 7], [0, 4, 8], [2, 6]] for search(π‘aΠ, aπ‘Ππ‘aπ‘Ππ‘a, 0)=[[1, 3, 5, 7], [0, 4, 8], [2, 6]]. OK" diff --git a/tests/regression/echotest/string-unicode-expected.echo b/tests/regression/echotest/string-unicode-expected.echo new file mode 100644 index 0000000..a1cd3be --- /dev/null +++ b/tests/regression/echotest/string-unicode-expected.echo @@ -0,0 +1,107 @@ +ECHO: "text_1bytes_len = ", "1234", " len = ", 4 +ECHO: "text_2bytes_len = ", "ΠΠΠΠ", " len = ", 4 +ECHO: "text_4bytes_len = ", "π‘π±ππ", " len = ", 4 +ECHO: "[", 0, "] = ", "DEADBEEF", " of len=", 8, ":" +ECHO: " [", 0, "]=", "D" +ECHO: " [", 1, "]=", "E" +ECHO: " [", 2, "]=", "A" +ECHO: " [", 3, "]=", "D" +ECHO: " [", 4, "]=", "B" +ECHO: " [", 5, "]=", "E" +ECHO: " [", 6, "]=", "E" +ECHO: " [", 7, "]=", "F" +ECHO: "[", 1, "] = ", "ΠΠ΅Π½ΠΈΠ²ΡΠΉ ΡΡΠΆΠΈΠΉ ΠΊΠΎΡ", " of len=", 17, ":" +ECHO: " [", 0, "]=", "Π" +ECHO: " [", 1, "]=", "Π΅" +ECHO: " [", 2, "]=", "Π½" +ECHO: " [", 3, "]=", "ΠΈ" +ECHO: " [", 4, "]=", "Π²" +ECHO: " [", 5, "]=", "Ρ" +ECHO: " [", 6, "]=", "ΠΉ" +ECHO: " [", 7, "]=", " " +ECHO: " [", 8, "]=", "Ρ" +ECHO: " [", 9, "]=", "Ρ" +ECHO: " [", 10, "]=", "ΠΆ" +ECHO: " [", 11, "]=", "ΠΈ" +ECHO: " [", 12, "]=", "ΠΉ" +ECHO: " [", 13, "]=", " " +ECHO: " [", 14, "]=", "ΠΊ" +ECHO: " [", 15, "]=", "ΠΎ" +ECHO: " [", 16, "]=", "Ρ" +ECHO: "[", 2, "] = ", "ΩΨ³ΩΩ Ψ§ΩΨ²ΩΨ¬Ψ¨ΩΩ Ψ§ΩΩΨ·", " of len=", 18, ":" +ECHO: " [", 0, "]=", "Ω" +ECHO: " [", 1, "]=", "Ψ³" +ECHO: " [", 2, "]=", "Ω" +ECHO: " [", 3, "]=", "Ω" +ECHO: " [", 4, "]=", " " +ECHO: " [", 5, "]=", "Ψ§" +ECHO: " [", 6, "]=", "Ω" +ECHO: " [", 7, "]=", "Ψ²" +ECHO: " [", 8, "]=", "Ω" +ECHO: " [", 9, "]=", "Ψ¬" +ECHO: " [", 10, "]=", "Ψ¨" +ECHO: " [", 11, "]=", "Ω" +ECHO: " [", 12, "]=", "Ω" +ECHO: " [", 13, "]=", " " +ECHO: " [", 14, "]=", "Ψ§" +ECHO: " [", 15, "]=", "Ω" +ECHO: " [", 16, "]=", "Ω" +ECHO: " [", 17, "]=", "Ψ·" +ECHO: "[", 3, "] = ", "ζΆζ°ηε§θ²", " of len=", 5, ":" +ECHO: " [", 0, "]=", "ζΆ" +ECHO: " [", 1, "]=", "ζ°" +ECHO: " [", 2, "]=", "η" +ECHO: " [", 3, "]=", "ε§" +ECHO: " [", 4, "]=", "θ²" +ECHO: "[", 4, "] = ", "Àâü ΓΓΓ Γ", " of len=", 9, ":" +ECHO: " [", 0, "]=", "Γ€" +ECHO: " [", 1, "]=", "ΓΆ" +ECHO: " [", 2, "]=", "ΓΌ" +ECHO: " [", 3, "]=", " " +ECHO: " [", 4, "]=", "Γ" +ECHO: " [", 5, "]=", "Γ" +ECHO: " [", 6, "]=", "Γ" +ECHO: " [", 7, "]=", " " +ECHO: " [", 8, "]=", "Γ" +ECHO: "[", 5, "] = ", "πππππ
πππππππππππ", " of len=", 16, ":" +ECHO: " [", 0, "]=", "π" +ECHO: " [", 1, "]=", "π" +ECHO: " [", 2, "]=", "π" +ECHO: " [", 3, "]=", "π" +ECHO: " [", 4, "]=", "π
" +ECHO: " [", 5, "]=", "π" +ECHO: " [", 6, "]=", "π" +ECHO: " [", 7, "]=", "π" +ECHO: " [", 8, "]=", "π" +ECHO: " [", 9, "]=", "π" +ECHO: " [", 10, "]=", "π" +ECHO: " [", 11, "]=", "π" +ECHO: " [", 12, "]=", "π" +ECHO: " [", 13, "]=", "π" +ECHO: " [", 14, "]=", "π" +ECHO: " [", 15, "]=", "π" +ECHO: "[", 6, "] = ", "β β β β β
β β β β β β β β β β ", " of len=", 15, ":" +ECHO: " [", 0, "]=", "β " +ECHO: " [", 1, "]=", "β " +ECHO: " [", 2, "]=", "β " +ECHO: " [", 3, "]=", "β " +ECHO: " [", 4, "]=", "β
" +ECHO: " [", 5, "]=", "β " +ECHO: " [", 6, "]=", "β " +ECHO: " [", 7, "]=", "β " +ECHO: " [", 8, "]=", "β " +ECHO: " [", 9, "]=", "β " +ECHO: " [", 10, "]=", "β " +ECHO: " [", 11, "]=", "β " +ECHO: " [", 12, "]=", "β " +ECHO: " [", 13, "]=", "β " +ECHO: " [", 14, "]=", "β " +ECHO: "[", 7, "] = ", "π‘π±ππ", " of len=", 4, ":" +ECHO: " [", 0, "]=", "π‘" +ECHO: " [", 1, "]=", "π±" +ECHO: " [", 2, "]=", "π" +ECHO: " [", 3, "]=", "π" +ECHO: "Past end of unicode only 2-byte ", undef +ECHO: "Past end of unicode only 4-byte ", undef +ECHO: "Past end of both 2-byte ", undef +ECHO: "Past end of both 4-byte ", undef diff --git a/tests/regression/opencsgtest/polyhedron-tests-expected.png b/tests/regression/opencsgtest/polyhedron-tests-expected.png Binary files differindex 0740f1a..f6665cf 100644 --- a/tests/regression/opencsgtest/polyhedron-tests-expected.png +++ b/tests/regression/opencsgtest/polyhedron-tests-expected.png diff --git a/tests/regression/opencsgtest/rotate_extrude-tests-expected.png b/tests/regression/opencsgtest/rotate_extrude-tests-expected.png Binary files differindex 861f6ab..0be247e 100644 --- a/tests/regression/opencsgtest/rotate_extrude-tests-expected.png +++ b/tests/regression/opencsgtest/rotate_extrude-tests-expected.png diff --git a/tests/regression/throwntogethertest/polyhedron-tests-expected.png b/tests/regression/throwntogethertest/polyhedron-tests-expected.png Binary files differindex 95ffeaa..c293d88 100644 --- a/tests/regression/throwntogethertest/polyhedron-tests-expected.png +++ b/tests/regression/throwntogethertest/polyhedron-tests-expected.png diff --git a/tests/regression/throwntogethertest/rotate_extrude-tests-expected.png b/tests/regression/throwntogethertest/rotate_extrude-tests-expected.png Binary files differindex 8956be2..1da4873 100644 --- a/tests/regression/throwntogethertest/rotate_extrude-tests-expected.png +++ b/tests/regression/throwntogethertest/rotate_extrude-tests-expected.png diff --git a/tests/test_pretty_print.py b/tests/test_pretty_print.py index a31b1a8..4c3993c 100755 --- a/tests/test_pretty_print.py +++ b/tests/test_pretty_print.py @@ -25,544 +25,447 @@ # todo # -# 1. Note: Wiki code is deprecated. All future development should move to -# create html output (or even xml output). Wiki design was based on the -# wrong assumption of easily accessible public wiki servers with -# auto-upload scripts available. wiki code should be removed and code -# simplified. -# -# to still use wiki, use args '--wiki' and/or '--wiki-upload' -# -# 2. why is hash differing - -import string,sys,re,os,hashlib,subprocess,textwrap,time,platform +# 1. why is hash differing + +import string +import sys +import re +import os +import hashlib +import subprocess +import time +import platform +try: + from urllib.request import urlopen + from urllib.parse import urlencode +except: + from urllib2 import urlopen + from urllib import urlencode def tryread(filename): - data = None - try: - f = open(filename,'rb') - data = f.read() - f.close() - except Exception, e: - print 'couldn\'t open ',filename - print type(e), e - return data - -def trysave(filename,data): - dir = os.path.dirname(filename) - try: - if not os.path.isdir(dir): - if not dir == '': - debug( 'creating' + dir) - os.mkdir(dir) - f=open(filename,'wb') - f.write(data) - f.close() - except Exception, e: - print 'problem writing to',filename - print type(e), e - return None - return True - -def ezsearch(pattern,str): - x = re.search(pattern,str,re.DOTALL|re.MULTILINE) - if x and len(x.groups())>0: return x.group(1).strip() - return '' - + data = None + try: + f = open(filename,'rb') + data = f.read() + f.close() + except Exception as e: + print 'couldn\'t open ',filename + print type(e), e + return data + +def trysave(filename, data): + dir = os.path.dirname(filename) + try: + if not os.path.isdir(dir): + if not dir == '': + debug( 'creating' + dir) + os.mkdir(dir) + f=open(filename,'wb') + f.write(data) + f.close() + except Exception as e: + print 'problem writing to',filename + print type(e), e + return None + return True + +def ezsearch(pattern, str): + x = re.search(pattern,str,re.DOTALL|re.MULTILINE) + if x and len(x.groups())>0: return x.group(1).strip() + return '' + def read_gitinfo(): - # won't work if run from outside of branch. - try: - data = subprocess.Popen(['git','remote','-v'],stdout=subprocess.PIPE).stdout.read() - origin = ezsearch('^origin *?(.*?)\(fetch.*?$',data) - upstream = ezsearch('^upstream *?(.*?)\(fetch.*?$',data) - data = subprocess.Popen(['git','branch'],stdout=subprocess.PIPE).stdout.read() - branch = ezsearch('^\*(.*?)$',data) - out = 'Git branch: ' + branch + ' from origin ' + origin + '\n' - out += 'Git upstream: ' + upstream + '\n' - except: - out = 'Problem running git' - return out + # won't work if run from outside of branch. + try: + data = subprocess.Popen(['git', 'remote', '-v'], stdout=subprocess.PIPE).stdout.read() + origin = ezsearch('^origin *?(.*?)\(fetch.*?$', data) + upstream = ezsearch('^upstream *?(.*?)\(fetch.*?$', data) + data = subprocess.Popen(['git', 'branch'], stdout=subprocess.PIPE).stdout.read() + branch = ezsearch('^\*(.*?)$', data) + out = 'Git branch: ' + branch + ' from origin ' + origin + '\n' + out += 'Git upstream: ' + upstream + '\n' + except: + out = 'Problem running git' + return out def read_sysinfo(filename): - data = tryread(filename) - if not data: - sinfo = platform.sys.platform - sinfo += '\nsystem cannot create offscreen GL framebuffer object' - sinfo += '\nsystem cannot create GL based images' - sysid = platform.sys.platform+'_no_GL_renderer' - return sinfo, sysid + data = tryread(filename) + if not data: + sinfo = platform.sys.platform + sinfo += '\nsystem cannot create offscreen GL framebuffer object' + sinfo += '\nsystem cannot create GL based images' + sysid = platform.sys.platform+'_no_GL_renderer' + return sinfo, sysid - machine = ezsearch('Machine:(.*?)\n',data) - machine = machine.replace(' ','-').replace('/','-') + machine = ezsearch('Machine:(.*?)\n',data) + machine = machine.replace(' ','-').replace('/','-') - osinfo = ezsearch('OS info:(.*?)\n',data) - osplain = osinfo.split(' ')[0].strip().replace('/','-') - if 'windows' in osinfo.lower(): osplain = 'win' + osinfo = ezsearch('OS info:(.*?)\n',data) + osplain = osinfo.split(' ')[0].strip().replace('/','-') + if 'windows' in osinfo.lower(): + osplain = 'win' - renderer = ezsearch('GL Renderer:(.*?)\n',data) - tmp = renderer.split(' ') - tmp = string.join(tmp[0:3],'-') - tmp = tmp.split('/')[0] - renderer = tmp + renderer = ezsearch('GL Renderer:(.*?)\n',data) + tmp = renderer.split(' ') + tmp = string.join(tmp[0:3],'-') + tmp = tmp.split('/')[0] + renderer = tmp - data += read_gitinfo() + data += read_gitinfo() - data += 'Image comparison: ImageMagick' + data += 'Image comparison: ImageMagick' - data = data.strip() + data = data.strip() - # create 4 letter hash and stick on end of sysid - nondate_data = re.sub("\n.*?ompile date.*?\n","\n",data).strip() - hexhash = hashlib.md5() - hexhash.update(nondate_data) - hexhash = hexhash.hexdigest()[-4:].upper() - hash = '' - for c in hexhash: hash += chr(ord(c)+97-48) + # create 4 letter hash and stick on end of sysid + nondate_data = re.sub("\n.*?ompile date.*?\n", "\n", data).strip() + hexhash = hashlib.md5(nondate_data).hexdigest()[-4:].upper() + hash_ = ''.join(chr(ord(c) + 97 - 48) for c in hexhash) - sysid = osplain + '_' + machine + '_' + renderer + '_' + hash - sysid = sysid.replace('(','_').replace(')','_') - sysid = sysid.lower() + sysid = '_'.join([osplain, machine, renderer, hash_]) + sysid = sysid.replace('(', '_').replace(')', '_') + sysid = sysid.lower() - return data, sysid + return data, sysid class Test: - def __init__(self,fullname,time,passed,output,type,actualfile,expectedfile,scadfile,log): - self.fullname,self.time,self.passed,self.output = \ - fullname, time, passed, output - self.type, self.actualfile, self.expectedfile, self.scadfile = \ - type, actualfile, expectedfile, scadfile - self.fulltestlog = log - - def __str__(self): - x = 'fullname: ' + self.fullname - x+= '\nactualfile: ' + self.actualfile - x+= '\nexpectedfile: ' + self.expectedfile - x+= '\ntesttime: ' + self.time - x+= '\ntesttype: ' + self.type - x+= '\npassed: ' + str(self.passed) - x+= '\nscadfile: ' + self.scadfile - x+= '\noutput bytes: ' + str(len(self.output)) - x+= '\ntestlog bytes: ' + str(len(self.fulltestlog)) - x+= '\n' - return x + def __init__(self, fullname, subpr, passed, output, type, actualfile, + expectedfile, scadfile, log): + self.fullname, self.time = fullname, time + self.passed, self.output = passed, output + self.type, self.actualfile = type, actualfile + self.expectedfile, self.scadfile = expectedfile, scadfile + self.fulltestlog = log + + def __str__(self): + x = 'fullname: ' + self.fullname + x+= '\nactualfile: ' + self.actualfile + x+= '\nexpectedfile: ' + self.expectedfile + x+= '\ntesttime: ' + self.time + x+= '\ntesttype: ' + self.type + x+= '\npassed: ' + str(self.passed) + x+= '\nscadfile: ' + self.scadfile + x+= '\noutput bytes: ' + str(len(self.output)) + x+= '\ntestlog bytes: ' + str(len(self.fulltestlog)) + x+= '\n' + return x def parsetest(teststring): - patterns = ["Test:(.*?)\n", # fullname - "Test time =(.*?) sec\n", - "Test time.*?Test (Passed)", # pass/fail - "Output:(.*?)<end of output>", - 'Command:.*?-s" "(.*?)"', # type - "^ actual .*?:(.*?)\n", - "^ expected .*?:(.*?)\n", - 'Command:.*?(testdata.*?)"' # scadfile - ] - hits = map( lambda pattern: ezsearch(pattern,teststring), patterns ) - test = Test(hits[0],hits[1],hits[2]=='Passed',hits[3],hits[4],hits[5],hits[6],hits[7],teststring) - if len(test.actualfile) > 0: test.actualfile_data = tryread(test.actualfile) - if len(test.expectedfile) > 0: test.expectedfile_data = tryread(test.expectedfile) - return test + patterns = ["Test:(.*?)\n", # fullname + "Test time =(.*?) sec\n", + "Test time.*?Test (Passed)", # pass/fail + "Output:(.*?)<end of output>", + 'Command:.*?-s" "(.*?)"', # type + "^ actual .*?:(.*?)\n", + "^ expected .*?:(.*?)\n", + 'Command:.*?(testdata.*?)"' # scadfile + ] + hits = map( lambda pattern: ezsearch(pattern, teststring), patterns) + test = Test(hits[0], hits[1], hits[2]=='Passed', hits[3], hits[4], hits[5], + hits[6], hits[7], teststring) + if len(test.actualfile) > 0: + test.actualfile_data = tryread(test.actualfile) + if len(test.expectedfile) > 0: + test.expectedfile_data = tryread(test.expectedfile) + return test def parselog(data): - startdate = ezsearch('Start testing: (.*?)\n',data) - enddate = ezsearch('End testing: (.*?)\n',data) - pattern = '([0-9]*/[0-9]* Testing:.*?time elapsed.*?\n)' - test_chunks = re.findall(pattern,data,re.S) - tests = map( parsetest, test_chunks ) - tests = sorted(tests, key = lambda t:t.passed) - return startdate, tests, enddate + startdate = ezsearch('Start testing: (.*?)\n', data) + enddate = ezsearch('End testing: (.*?)\n', data) + pattern = '([0-9]*/[0-9]* Testing:.*?time elapsed.*?\n)' + test_chunks = re.findall(pattern,data, re.S) + tests = map( parsetest, test_chunks ) + tests = sorted(tests, key = lambda t: t.passed) + return startdate, tests, enddate def load_makefiles(builddir): - filelist = [] - for root, dirs, files in os.walk(builddir): - for fname in files: filelist += [ os.path.join(root, fname) ] - files = filter(lambda x: 'build.make' in os.path.basename(x), filelist) - files += filter(lambda x: 'flags.make' in os.path.basename(x), filelist) - files = filter(lambda x: 'esting' not in x and 'emporary' not in x, files) - result = {} - for fname in files: - result[fname.replace(builddir,'')] = open(fname,'rb').read() - return result - -def wikify_filename(fname, wiki_rootpath, sysid): - wikifname = fname.replace('/','_').replace('\\','_').strip('.') - return wiki_rootpath + '_' + sysid + '_' + wikifname - -def towiki(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, makefiles): - - wiki_template = """ -<h3>[[WIKI_ROOTPATH]] test run report</h3> - -'''Sysid''': SYSID - -'''Result summary''': NUMPASSED / NUMTESTS tests passed ( PERCENTPASSED % ) <br> - -'''System info''': -<pre> -SYSINFO -</pre> - -start time: STARTDATE <br> -end time : ENDDATE <br> - -'''Image tests''' - -<REPEAT1> -{| border=1 cellspacing=0 cellpadding=1 -|- -| colspan=2 | FTESTNAME -|- -| Expected image || Actual image -|- -| [[File:EXPECTEDFILE|250px]] || ACTUALFILE_WIKI -|} - -<pre> -TESTLOG -</pre> - - - -</REPEAT1> - - -'''Text tests''' - -<REPEAT2> -{|border=1 cellspacing=0 cellpadding=1 -|- -| FTESTNAME -|} - -<pre> -TESTLOG -</pre> - - -</REPEAT2> - -'''build.make and flags.make''' -<REPEAT3> -*[[MAKEFILE_NAME]] -</REPEAT3> -""" - txtpages = {} - imgs = {} - passed_tests = filter(lambda x: x.passed, tests) - failed_tests = filter(lambda x: not x.passed, tests) - - tests_to_report = failed_tests - if include_passed: tests_to_report = tests - - try: percent = str(int(100.0*len(passed_tests) / len(tests))) - except ZeroDivisionError: percent = 'n/a' - s = wiki_template - repeat1 = ezsearch('(<REPEAT1>.*?</REPEAT1>)',s) - repeat2 = ezsearch('(<REPEAT2>.*?</REPEAT2>)',s) - repeat3 = ezsearch('(<REPEAT3>.*?</REPEAT3>)',s) - dic = { 'STARTDATE': startdate, 'ENDDATE': enddate, 'WIKI_ROOTPATH': wiki_rootpath, - 'SYSINFO': sysinfo, 'SYSID':sysid, - 'NUMTESTS':len(tests), 'NUMPASSED':len(passed_tests), 'PERCENTPASSED':percent } - for key in dic.keys(): - s = s.replace(key,str(dic[key])) - - for t in tests_to_report: - if t.type in ('txt', 'ast', 'csg', 'term', 'echo'): - newchunk = re.sub('FTESTNAME',t.fullname,repeat2) - newchunk = newchunk.replace('TESTLOG',t.fulltestlog) - s = s.replace(repeat2, newchunk+repeat2) - elif t.type=='png': - tmp = t.actualfile.replace(builddir,'') - wikiname_a = wikify_filename(tmp,wiki_rootpath,sysid) - tmp = t.expectedfile.replace(os.path.dirname(builddir),'') - wikiname_e = wikify_filename(tmp,wiki_rootpath,sysid) - if hasattr(t, 'expectedfile_data'): - imgs[wikiname_e] = t.expectedfile_data - if t.actualfile: - actualfile_wiki = '[[File:'+wikiname_a+'|250px]]' - if hasattr(t, 'actualfile_data'): - imgs[wikiname_a] = t.actualfile_data - else: - actualfile_wiki = 'No image generated.' - newchunk = re.sub('FTESTNAME',t.fullname,repeat1) - newchunk = newchunk.replace('ACTUALFILE_WIKI',actualfile_wiki) - newchunk = newchunk.replace('EXPECTEDFILE',wikiname_e) - newchunk = newchunk.replace('TESTLOG',t.fulltestlog) - s = s.replace(repeat1, newchunk+repeat1) - else: - raise Exception("Unknown test type %r"%t.type) - - makefiles_wikinames = {} - for mf in sorted(makefiles.keys()): - tmp = mf.replace('CMakeFiles','').replace('.dir','') - wikiname = wikify_filename(tmp,wiki_rootpath,sysid) - newchunk = re.sub('MAKEFILE_NAME',wikiname,repeat3) - s = s.replace(repeat3, newchunk+repeat3) - makefiles_wikinames[mf] = wikiname - - s = s.replace(repeat1,'') - s = s.replace(repeat2,'') - s = s.replace(repeat3,'') - s = re.sub('<REPEAT.*?>\n','',s) - s = re.sub('</REPEAT.*?>','',s) - - mainpage_wikiname = wiki_rootpath + '_' + sysid + '_test_report' - txtpages[ mainpage_wikiname ] = s - for mf in sorted(makefiles.keys()): - txtpages[ makefiles_wikinames[ mf ] ] = '\n*Subreport from [['+mainpage_wikiname+']]\n\n\n<pre>\n'+makefiles[mf]+'\n</pre>' - - return imgs, txtpages - -def png_encode64( fname, width=250 ): - # en.wikipedia.org/wiki/Data_URI_scheme - try: - f = open( fname, "rb" ) - data = f.read() - except: - data = '' - data_uri = data.encode("base64").replace("\n","") - tag = '<img' - tag += ' style="border:1px solid gray"' - tag += ' src="data:image/png;base64,' - tag += data_uri + '"' - tag += ' width="'+str(width)+'"' - if data =='': - tag += ' alt="error: no image generated"' - else: - tag += ' alt="openscad_test_image"' - tag += ' />\n' - return tag - -def tohtml(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, makefiles): - # kludge. assume wiki stuff has alreayd run and dumped files properly - head = '<html><head><title>'+wiki_rootpath+' test run for '+sysid +'</title></head><body>' - tail = '</body></html>' - - passed_tests = filter(lambda x: x.passed, tests) - failed_tests = filter(lambda x: not x.passed, tests) - try: percent = str(int(100.0*len(passed_tests) / len(tests))) - except ZeroDivisionError: percent = 'n/a' - - tests_to_report = failed_tests - if include_passed: tests_to_report = tests - - s='' - - s+= '\n<h3>' - s+= '\nSystem info\n' - s+= '\n</h3><p>' - s+= '<pre>'+sysinfo+'</pre>\n' - - s+= '\n<pre>' - s+= '\nSTARTDATE: '+ startdate - s+= '\nENDDATE: '+ enddate - s+= '\nWIKI_ROOTPATH: '+ wiki_rootpath - s+= '\nSYSID: '+sysid - s+= '\nNUMTESTS: '+str(len(tests)) - s+= '\nNUMPASSED: '+str(len(passed_tests)) - s+= '\nPERCENTPASSED: '+ percent - s+= '\n</pre>' - - if not include_passed: - s+= '<h3>Failed tests:</h3>\n' - - if len(tests_to_report)==0: - s+= '<p>none</p>' - - for t in tests_to_report: - if t.type in ('txt', 'ast', 'csg', 'term', 'echo'): - s+='\n<pre>'+t.fullname+'</pre>\n' - s+='<p><pre>'+t.fulltestlog+'</pre>\n\n' - elif t.type=='png': - tmp = t.actualfile.replace(builddir,'') - wikiname_a = wikify_filename(tmp,wiki_rootpath,sysid) - tmp = t.expectedfile.replace(os.path.dirname(builddir),'') - wikiname_e = wikify_filename(tmp,wiki_rootpath,sysid) - # imgtag_e = <img src='+wikiname_e+' width=250/>' - # imatag_a = <img src='+wikiname_a+' width=250/>' - imgtag_e = png_encode64( t.expectedfile, 250 ) - imgtag_a = png_encode64( t.actualfile, 250 ) - s+='<table>' - s+='\n<tr><td colspan=2>'+t.fullname - s+='\n<tr><td>Expected<td>Actual' - s+='\n<tr><td>' + imgtag_e + '</td>' - s+='\n <td>' + imgtag_a + '</td>' - s+='\n</table>' - s+='\n<pre>' - s+=t.fulltestlog - s+='\n</pre>' - else: - raise Exception("Unknown test type %r"%t.type) - - s+='\n\n<p>\n\n' - - s+= '<h3> CMake .build files </h3>\n' - s+= '\n<pre>' - makefiles_wikinames = {} - for mf in sorted(makefiles.keys()): - mfname = mf.strip().lstrip(os.path.sep) - text = open(os.path.join(builddir,mfname)).read() - s+= '</pre><h4>'+mfname+'</h4><pre>' - s+= text - tmp = mf.replace('CMakeFiles','').replace('.dir','') - wikiname = wikify_filename(tmp,wiki_rootpath,sysid) - # s += '\n<a href='+wikiname+'>'+wikiname+'</a><br>' - s+= '\n</pre>' - s+='\n' - - return head + s + tail - -def wiki_login(wikiurl,api_php_path,botname,botpass): - site = mwclient.Site(wikiurl,api_php_path) - site.login(botname,botpass) - return site - -def wiki_upload(wikiurl,api_php_path,botname,botpass,filedata,wikipgname): - counter = 0 - done = False - descrip = 'test' - time.sleep(1) - while not done: - try: - print 'login',botname,'to',wikiurl - site = wiki_login(wikiurl,api_php_path,botname,botpass) - print 'uploading...', - if wikipgname.endswith('png'): - site.upload(filedata,wikipgname,descrip,ignore=True) - else: - page = site.Pages[wikipgname] - text = page.edit() - page.save(filedata) - done = True - print 'transfer ok' - except Exception, e: - print 'Error:', type(e),e - counter += 1 - if counter>maxretry: - print 'giving up. please try a different wiki site' - done = True - else: - print 'wiki',wikiurl,'down. retrying in 15 seconds' - time.sleep(15) - -def upload(wikiurl,api_php_path='/',wiki_rootpath='test', sysid='null', botname='cakebaby',botpass='anniew',wikidir='.',dryrun=True): - wetrun = not dryrun - if dryrun: print 'dry run' - try: - global mwclient - import mwclient - except: - print 'please download mwclient 0.6.5 and unpack here:', os.getcwd() - sys.exit() - - if wetrun: site = wiki_login(wikiurl,api_php_path,botname,botpass) - - wikifiles = os.listdir(wikidir) - testreport_page = filter( lambda x: 'test_report' in x, wikifiles ) - if (len(testreport_page)>1): - print 'multiple test reports found, please clean dir',wikidir - sys.exit() - - rootpage = testreport_page[0] - print 'add',rootpage,' to main report page ',wiki_rootpath - if wetrun: - page = site.Pages[wiki_rootpath] - text = page.edit() - if not '[['+rootpage+']]' in text: - page.save(text +'\n*[['+rootpage+']]\n') - - wikifiles = os.listdir(wikidir) - wikifiles = filter(lambda x: not x.endswith('html'), wikifiles) - - print 'upload wiki pages:' - for wikiname in wikifiles: - filename = os.path.join(wikidir,wikiname) - filedata = tryread(filename) - print 'upload',len(filedata),'bytes from',wikiname - if wetrun and len(filedata)>0: - wiki_upload(wikiurl,api_php_path,botname,botpass,filedata,wikiname) - if len(filedata)==0: - print 'cancelling empty upload' + filelist = [] + for root, dirs, files in os.walk(builddir): + for fname in files: filelist += [ os.path.join(root, fname) ] + files = [file for file in filelist if 'build.make' in os.path.basename(file) + or 'flags.make' in os.path.basename(file)] + files = [file for file in files if 'esting' not in file and 'emporary' not in file] + result = {} + for fname in files: + result[fname.replace(builddir, '')] = tryread(fname) + return result + + +def png_encode64(fname, width=250, data=None): + # en.wikipedia.org/wiki/Data_URI_scheme + data = data or tryread(fname) or '' + data_uri = data.encode('base64').replace('\n', '') + tag = '''<img src="data:image/png;base64,%s" width="%s" %s/>''' + if data == '': + alt = 'alt="error: no image generated" ' + else: + alt = 'alt="openscad_test_image" ' + tag %= (data_uri, width, alt) + return tag + def findlogfile(builddir): - logpath = os.path.join(builddir,'Testing','Temporary') - logfilename = os.path.join(logpath,'LastTest.log.tmp') - if not os.path.isfile(logfilename): - logfilename = os.path.join(logpath,'LastTest.log') - if not os.path.isfile(logfilename): - print 'cant find and/or open logfile',logfilename - sys.exit() - return logpath, logfilename + logpath = os.path.join(builddir, 'Testing', 'Temporary') + logfilename = os.path.join(logpath, 'LastTest.log.tmp') + if not os.path.isfile(logfilename): + logfilename = os.path.join(logpath, 'LastTest.log') + if not os.path.isfile(logfilename): + print 'can\'t find and/or open logfile', logfilename + sys.exit() + return logfilename + +# --- Templating --- + +class Templates(object): + html_template = '''<html> + <head><title>Test run for {sysid}</title> + {style} + </head> + <body> + <h1>{project_name} test run report</h1> + <p> + <b>Sysid</b>: {sysid} + </p> + <p> + <b>Result summary</b>: {numpassed} / {numtests} tests passed ({percent}%) + </p> + + <h2>System info</h2> + <pre>{sysinfo}</pre> + + <p>start time: {startdate}</p> + <p>end time: {enddate}</p> + + <h2>Image tests</h2> + {image_tests} + + <h2>Text tests</h2> + {text_tests} + + <h2>build.make and flags.make</h2> + {makefiles} + </body></html>''' + + style = ''' + <style> + body { + color: black; + } + + table { + border-collapse: collapse; + } + + table td, th { + border: 2px solid gray; + } + + .text-name { + border: 2px solid black; + padding: 0.14em; + } + </style>''' + + image_template = '''<table> + <tbody> + <tr><td colspan="2">{test_name}</td></tr> + <tr><td> Expected image </td><td> Actual image </td></tr> + <tr><td> {expected} </td><td> {actual} </td></tr> + </tbody> + </table> + + <pre> + {test_log} + </pre> + ''' + + text_template = ''' + <span class="text-name">{test_name}</span> + + <pre> + {test_log} + </pre> + ''' + + makefile_template = ''' + <h4>{name}</h4> + <pre> + {text} + </pre> + ''' + + def __init__(self, **defaults): + self.filled = {} + self.defaults = defaults + + def fill(self, template, *args, **kwargs): + kwds = self.defaults.copy() + kwds.update(kwargs) + return getattr(self, template).format(*args, **kwds) + + def add(self, template, var, *args, **kwargs): + self.filled[var] = self.filled.get(var, '') + self.fill(template, *args, **kwargs) + return self.filled[var] + + def get(self, var): + return self.filled.get(var, '') + + +def to_html(project_name, startdate, tests, enddate, sysinfo, sysid, makefiles): + passed_tests = [test for test in tests if test.passed] + failed_tests = [test for test in tests if not test.passed] + + report_tests = failed_tests + if include_passed: + report_tests = tests + + percent = '%.0f' % (100.0 * len(passed_tests) / len(tests)) if tests else 'n/a' + + templates = Templates() + for test in report_tests: + if test.type in ('txt', 'ast', 'csg', 'term', 'echo'): + templates.add('text_template', 'text_tests', + test_name=test.fullname, + test_log=test.fulltestlog) + elif test.type == 'png': + actual_img = png_encode64(test.actualfile, + data=vars(test).get('actualfile_data')) + expected_img = png_encode64(test.expectedfile, + data=vars(test).get('expectedfile_data')) + templates.add('image_template', 'image_tests', + test_name=test.fullname, + test_log=test.fulltestlog, + actual=actual_img, + expected=expected_img) + else: + raise TypeError('Unknown test type %r' % test.type) + + for mf in sorted(makefiles.keys()): + mfname = mf.strip().lstrip(os.path.sep) + text = open(os.path.join(builddir, mfname)).read() + templates.add('makefile_template', 'makefiles', name=mfname, text=text) + + text_tests = templates.get('text_tests') + image_tests = templates.get('image_tests') + makefiles_str = templates.get('makefiles') + + return templates.fill('html_template', style=Templates.style, + sysid=sysid, sysinfo=sysinfo, + startdate=startdate, enddate=enddate, + project_name=project_name, + numtests=len(tests), + numpassed=len(passed_tests), + percent=percent, image_tests=image_tests, + text_tests=text_tests, makefiles=makefiles_str) + +# --- End Templating --- + +# --- Web Upload --- + +def postify(data): + return urlencode(data).encode() + +def create_page(): + data = { + 'action': 'create', + 'type': 'html' + } + try: + response = urlopen('http://www.dinkypage.com', data=postify(data)) + except: + return None + return response.geturl() + +def upload_html(page_url, title, html): + data = { + 'mode': 'editor', + 'title': title, + 'html': html, + 'ajax': '1' + } + try: + response = urlopen(page_url, data=postify(data)) + except: + return False + return 'success' in response.read().decode() + +# --- End Web Upload --- def debug(x): - if debug_test_pp: print 'test_pretty_print: '+x + if debug_test_pp: + print 'test_pretty_print: ' + x -debug_test_pp=False -builddir=os.getcwd() +debug_test_pp = False +include_passed = False +builddir = os.getcwd() def main(): - #wikisite = 'cakebaby.referata.com' - #wiki_api_path = '' - global wikisite, wiki_api_path, wiki_rootpath, builddir, debug_test_pp - global maxretry, dry, include_passed - - wikisite = 'cakebaby.wikia.com' - wiki_api_path = '/' - wiki_rootpath = 'OpenSCAD' - if '--debug' in string.join(sys.argv): debug_test_pp=True - maxretry = 10 - - if bool(os.getenv("TEST_GENERATE")): sys.exit(0) - - include_passed = False - if '--include-passed' in sys.argv: include_passed = True - - dry = False - debug( 'running test_pretty_print' ) - if '--dryrun' in sys.argv: dry=True - suffix = ezsearch('--suffix=(.*?) ',string.join(sys.argv)+' ') - builddir = ezsearch('--builddir=(.*?) ',string.join(sys.argv)+' ') - if builddir=='': builddir=os.getcwd() - debug( 'build dir set to ' + builddir ) - - sysinfo, sysid = read_sysinfo(os.path.join(builddir,'sysinfo.txt')) - makefiles = load_makefiles(builddir) - logpath, logfilename = findlogfile(builddir) - testlog = tryread(logfilename) - startdate, tests, enddate = parselog(testlog) - if debug_test_pp: - print 'found sysinfo.txt,', - print 'found', len(makefiles),'makefiles,', - print 'found', len(tests),'test results' - - imgs, txtpages = towiki(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, makefiles) - - wikidir = os.path.join(logpath,sysid+'_report') - debug( 'erasing files in ' + wikidir ) - try: map(lambda x:os.remove(os.path.join(wikidir,x)), os.listdir(wikidir)) - except: pass - debug( 'output dir:\n' + wikidir.replace(os.getcwd(),'') ) - debug( 'writing ' + str(len(imgs)) + ' images' ) - debug( 'writing ' + str(len(txtpages)-1) + ' text pages' ) - debug( 'writing index.html ' ) - if '--wiki' in string.join(sys.argv): - print "wiki output is deprecated" - for pgname in sorted(imgs): trysave( os.path.join(wikidir,pgname), imgs[pgname]) - for pgname in sorted(txtpages): trysave( os.path.join(wikidir,pgname), txtpages[pgname]) - - htmldata = tohtml(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, makefiles) - html_basename = sysid+'_report.html' - html_filename = os.path.join(builddir,'Testing','Temporary',html_basename) - debug('saving ' +html_filename + ' ' + str(len(htmldata)) + ' bytes') - trysave( html_filename, htmldata ) - print "report saved:", html_filename.replace(os.getcwd()+os.path.sep,'') - - if '--wiki-upload' in sys.argv: - print "wiki upload is deprecated." - upload(wikisite,wiki_api_path,wiki_rootpath,sysid,'openscadbot', - 'tobdacsnepo',wikidir,dryrun=dry) - print 'upload attempt complete' - - debug( 'test_pretty_print complete' ) + global builddir, debug_test_pp + global maxretry, dry, include_passed + project_name = 'OpenSCAD' + + if bool(os.getenv("TEST_GENERATE")): + sys.exit(0) + + # --- Command Line Parsing --- + + if '--debug' in ' '.join(sys.argv): + debug_test_pp = True + maxretry = 10 + + if '--include-passed' in sys.argv: + include_passed = True + + dry = False + debug('running test_pretty_print') + if '--dryrun' in sys.argv: + dry = True + + suffix = ezsearch('--suffix=(.*?) ', ' '.join(sys.argv) + ' ') + builddir = ezsearch('--builddir=(.*?) ', ' '.join(sys.argv) + ' ') + if not builddir: + builddir = os.getcwd() + debug('build dir set to ' + builddir) + + upload = False + if '--upload' in sys.argv: + upload = True + debug('will upload test report') + + # Workaround for old cmake's not being able to pass parameters + # to CTEST_CUSTOM_POST_TEST + if bool(os.getenv("OPENSCAD_UPLOAD_TESTS")): + upload = True + + # --- End Command Line Parsing --- + + sysinfo, sysid = read_sysinfo(os.path.join(builddir, 'sysinfo.txt')) + makefiles = load_makefiles(builddir) + logfilename = findlogfile(builddir) + testlog = tryread(logfilename) + startdate, tests, enddate = parselog(testlog) + if debug_test_pp: + print 'found sysinfo.txt,', + print 'found', len(makefiles),'makefiles,', + print 'found', len(tests),'test results' + + + html = to_html(project_name, startdate, tests, enddate, sysinfo, sysid, makefiles) + html_basename = sysid + '_report.html' + html_filename = os.path.join(builddir, 'Testing', 'Temporary', html_basename) + debug('saving ' + html_filename + ' ' + str(len(html)) + ' bytes') + trysave(html_filename, html) + print "report saved:\n", html_filename.replace(os.getcwd()+os.path.sep,'') + + if upload: + page_url = create_page() + if upload_html(page_url, title='OpenSCAD test results', html=html): + share_url = page_url.partition('?')[0] + print 'html report uploaded at', share_url + else: + print 'could not upload html report' + + debug('test_pretty_print complete') if __name__=='__main__': - main() + main() |