summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/CMakeLists.txt60
-rw-r--r--tests/OffscreenContext.h2
-rw-r--r--tests/OffscreenContext.mm10
-rw-r--r--tests/OffscreenContextGLX.cc (renamed from tests/OffscreenContext.cc)63
-rw-r--r--tests/OffscreenContextWGL.cc45
-rw-r--r--tests/OffscreenView.cc35
-rw-r--r--tests/OffscreenView.h2
-rw-r--r--tests/cgalpngtest.cc3
-rw-r--r--tests/csgtestcore.cc97
-rw-r--r--tests/fbo.cc21
-rw-r--r--tests/system-gl.cc38
-rw-r--r--tests/system-gl.h3
-rwxr-xr-xtests/test_cmdline_tool.py9
-rwxr-xr-xtests/test_pretty_print.py321
14 files changed, 630 insertions, 79 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 221500a..5e93680 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -75,24 +75,26 @@ if (NOT $ENV{MACOSX_DEPLOY_DIR} STREQUAL "")
set(BOOST_ROOT "$ENV{MACOSX_DEPLOY_DIR}")
endif()
-if(BOOST_ROOT)
- #set(Boost_DEBUG TRUE)
- set(Boost_NO_SYSTEM_PATHS TRUE)
- set(Boost_ADDITIONAL_VERSIONS "1.47.0")
- find_package( Boost 1.35.0 COMPONENTS thread program_options )
- if(Boost_FOUND)
- message(STATUS "Boost includes found: " ${Boost_INCLUDE_DIRS})
- message(STATUS "Boost libraries found:")
- foreach(boostlib ${Boost_LIBRARIES})
- message(STATUS " " ${boostlib})
- endforeach()
- include_directories(${Boost_INCLUDE_DIRS})
- else()
- message(STATUS "BOOST_ROOT:" ${BOOST_ROOT})
- message(FATAL_ERROR "BOOST_ROOT specified but no boost found")
- endif()
+if (WIN32)
+ set(Boost_USE_STATIC_LIBS TRUE)
+ set(BOOST_STATIC TRUE)
+ set(BOOST_THREAD_USE_LIB TRUE)
+endif()
+
+#set(Boost_DEBUG TRUE)
+set(Boost_NO_SYSTEM_PATHS TRUE)
+set(Boost_ADDITIONAL_VERSIONS "1.47.0" "1.46.0")
+find_package( Boost 1.35.0 COMPONENTS thread program_options )
+if(Boost_FOUND)
+ message(STATUS "Boost includes found: " ${Boost_INCLUDE_DIRS})
+ message(STATUS "Boost libraries found:")
+ foreach(boostlib ${Boost_LIBRARIES})
+ message(STATUS " " ${boostlib})
+ endforeach()
+ include_directories(${Boost_INCLUDE_DIRS})
else()
- message(STATUS "BOOST_ROOT unset. Assuming it will be found automatically.")
+ message(STATUS "BOOST_ROOT: ${BOOST_ROOT}")
+ message(FATAL_ERROR "Boost not found.")
endif()
# Mac OS X
@@ -258,13 +260,13 @@ set(COMMON_SOURCES
#
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
message(STATUS "Offscreen OpenGL Context - using Apple CGL")
- set(OFFSCREEN_CTX_SOURCE "OffscreenContext.mm")
+ set(OFFSCREEN_CTX_SOURCE "OffscreenContext.mm" CACHE TYPE STRING)
elseif(UNIX)
message(STATUS "Offscreen OpenGL Context - using Unix GLX")
- set(OFFSCREEN_CTX_SOURCE "OffscreenContext.cc")
+ set(OFFSCREEN_CTX_SOURCE "OffscreenContextGLX.cc" CACHE TYPE STRING)
elseif(WIN32)
message(STATUS "Offscreen OpenGL Context - using Microsoft WGL")
- set(OFFSCREEN_CTX_SOURCE "OffscreenContextWGL.cc")
+ set(OFFSCREEN_CTX_SOURCE "OffscreenContextWGL.cc" CACHE TYPE STRING)
endif()
set(OFFSCREEN_SOURCES
@@ -360,6 +362,24 @@ endfunction()
enable_testing()
+# set up custom pretty printing of results
+
+set(INFOCMD "execute_process(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/opencsgtest --info OUTPUT_FILE sysinfo.txt)")
+set(PRETTYCMD "\"${PYTHON_EXECUTABLE} test_pretty_print.py\"")
+set(CTEST_CUSTOM_FILE ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake)
+set(CTEST_CUSTOM_TXT "\n
+ message(\"running 'opencsgtest --info' to generate sysinfo.txt\")\n
+ ${INFOCMD}\n
+ # set(CTEST_CUSTOM_POST_TEST ${PRETTYCMD})\n # doesn't work. log is written
+ # after all tests run.
+")
+file(WRITE ${CTEST_CUSTOM_FILE} ${CTEST_CUSTOM_TXT})
+
+foreach(FILE test_pretty_print.py)
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${FILE}
+ ${CMAKE_CURRENT_BINARY_DIR}/${FILE} COPYONLY)
+endforeach()
+
# Find all scad files
file(GLOB MINIMAL_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/minimal/*.scad)
file(GLOB FEATURES_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/features/*.scad)
diff --git a/tests/OffscreenContext.h b/tests/OffscreenContext.h
index a079c3f..6eebcba 100644
--- a/tests/OffscreenContext.h
+++ b/tests/OffscreenContext.h
@@ -2,10 +2,12 @@
#define OFFSCREENCONTEXT_H_
#include <iostream> // for error output
+#include <string>
struct OffscreenContext *create_offscreen_context(int w, int h);
void bind_offscreen_context(OffscreenContext *ctx);
bool teardown_offscreen_context(OffscreenContext *ctx);
bool save_framebuffer(OffscreenContext *ctx, const char *filename);
+std::string offscreen_context_getinfo(OffscreenContext *ctx);
#endif
diff --git a/tests/OffscreenContext.mm b/tests/OffscreenContext.mm
index 140516f..5a6a8ec 100644
--- a/tests/OffscreenContext.mm
+++ b/tests/OffscreenContext.mm
@@ -16,6 +16,15 @@ struct OffscreenContext
fbo_t *fbo;
};
+string offscreen_context_getinfo(OffscreenContext *ctx)
+{
+ stringstream out;
+ out << "GL context creator: Cocoa / CGL\n"
+ << "PNG generator: Core Foundation\n"
+ << "OS info: Mac OSX\n"
+ << "Machine: Apple(TM) Mac(TM)\n";
+ return out.str();
+}
OffscreenContext *create_offscreen_context(int w, int h)
{
@@ -94,6 +103,7 @@ bool teardown_offscreen_context(OffscreenContext *ctx)
*/
bool save_framebuffer(OffscreenContext *ctx, const char *filename)
{
+ if (!ctx || !filename) return false;
// Read pixels from OpenGL
int samplesPerPixel = 4; // R, G, B and A
int rowBytes = samplesPerPixel * ctx->width;
diff --git a/tests/OffscreenContext.cc b/tests/OffscreenContextGLX.cc
index 839eea9..e607593 100644
--- a/tests/OffscreenContext.cc
+++ b/tests/OffscreenContextGLX.cc
@@ -44,6 +44,11 @@ See Also
#include <GL/gl.h>
#include <GL/glx.h>
+#include <assert.h>
+#include <sstream>
+
+#include <sys/utsname.h> // for uname
+
using namespace std;
struct OffscreenContext
@@ -66,6 +71,42 @@ void offscreen_context_init(OffscreenContext &ctx, int width, int height)
ctx.fbo = NULL;
}
+string get_os_info()
+{
+ struct utsname u;
+ stringstream out;
+
+ if (uname(&u) < 0)
+ out << "OS info: unknown, uname() error\n";
+ else {
+ out << "OS info: "
+ << u.sysname << " "
+ << u.release << " "
+ << u.version << "\n";
+ out << "Machine: " << u.machine;
+ }
+ return out.str();
+}
+
+string offscreen_context_getinfo(OffscreenContext *ctx)
+{
+ assert(ctx);
+
+ if (!ctx->xdisplay)
+ return string("No GL Context initialized. No information to report\n");
+
+ int major, minor;
+ glXQueryVersion(ctx->xdisplay, &major, &minor);
+
+ stringstream out;
+ out << "GL context creator: GLX\n"
+ << "PNG generator: lodepng\n"
+ << "GLX version: " << major << "." << minor << "\n"
+ << get_os_info();
+
+ return out.str();
+}
+
static XErrorHandler original_xlib_handler = (XErrorHandler) NULL;
static bool XCreateWindow_failed = false;
static int XCreateWindow_error(Display *dpy, XErrorEvent *event)
@@ -94,11 +135,15 @@ bool create_glx_dummy_window(OffscreenContext &ctx)
*/
int attributes[] = {
- GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT, //support all 3, for OpenCSG
GLX_RENDER_TYPE, GLX_RGBA_BIT,
- GLX_RED_SIZE, 1,
- GLX_GREEN_SIZE, 1,
- GLX_BLUE_SIZE, 1,
+ GLX_RED_SIZE, 8,
+ GLX_GREEN_SIZE, 8,
+ GLX_BLUE_SIZE, 8,
+ GLX_ALPHA_SIZE, 8,
+ GLX_DEPTH_SIZE, 24, // depth-stencil for OpenCSG
+ GLX_STENCIL_SIZE, 8,
+ GLX_DOUBLEBUFFER, True,
None
};
@@ -123,8 +168,9 @@ bool create_glx_dummy_window(OffscreenContext &ctx)
Window root = DefaultRootWindow( dpy );
XSetWindowAttributes xwin_attr;
- int width = 42;
- int height = 42;
+ int width = ctx.width;
+ int height = ctx.height;
+ xwin_attr.background_pixmap = None;
xwin_attr.background_pixel = 0;
xwin_attr.border_pixel = 0;
xwin_attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
@@ -137,7 +183,6 @@ bool create_glx_dummy_window(OffscreenContext &ctx)
// Window xWin = XCreateSimpleWindow( dpy, DefaultRootWindow(dpy), 0,0,42,42, 0,0,0 );
-
XSync( dpy, false );
if ( XCreateWindow_failed ) {
XFree( visinfo );
@@ -227,7 +272,6 @@ OffscreenContext *create_offscreen_context(int w, int h)
cerr << "Unable to init GLEW: " << glewGetErrorString(err) << endl;
return NULL;
}
- glew_dump();
ctx->fbo = fbo_new();
if (!fbo_init(ctx->fbo, w, h)) {
@@ -256,6 +300,7 @@ bool teardown_offscreen_context(OffscreenContext *ctx)
*/
bool save_framebuffer(OffscreenContext *ctx, const char *filename)
{
+ glXSwapBuffers(ctx->xdisplay, ctx->xwindow);
if (!ctx || !filename) return false;
int samplesPerPixel = 4; // R, G, B and A
GLubyte pixels[ctx->width * ctx->height * samplesPerPixel];
@@ -265,7 +310,7 @@ bool save_framebuffer(OffscreenContext *ctx, const char *filename)
int rowBytes = samplesPerPixel * ctx->width;
unsigned char *flippedBuffer = (unsigned char *)malloc(rowBytes * ctx->height);
if (!flippedBuffer) {
- std::cerr << "Unable to allocate flipped buffer for corrected image.";
+ cerr << "Unable to allocate flipped buffer for corrected image.";
return 1;
}
flip_image(pixels, flippedBuffer, samplesPerPixel, ctx->width, ctx->height);
diff --git a/tests/OffscreenContextWGL.cc b/tests/OffscreenContextWGL.cc
index 3b966e2..ba12a4f 100644
--- a/tests/OffscreenContextWGL.cc
+++ b/tests/OffscreenContextWGL.cc
@@ -22,6 +22,10 @@ For more info:
#include <GL/gl.h> // must be included after glew.h
+#include <map>
+#include <string>
+#include <sstream>
+
using namespace std;
struct OffscreenContext
@@ -44,6 +48,45 @@ void offscreen_context_init(OffscreenContext &ctx, int width, int height)
ctx.fbo = NULL;
}
+string get_os_info()
+{
+ OSVERSIONINFO osvi;
+
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&osvi);
+
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ map<WORD,const char*> archs;
+ archs[PROCESSOR_ARCHITECTURE_AMD64] = "amd64";
+ archs[PROCESSOR_ARCHITECTURE_IA64] = "itanium";
+ archs[PROCESSOR_ARCHITECTURE_INTEL] = "x86";
+ archs[PROCESSOR_ARCHITECTURE_UNKNOWN] = "unknown";
+
+ stringstream out;
+ out << "OS info: "
+ << "Microsoft(TM) Windows(TM) " << osvi.dwMajorVersion << " "
+ << osvi.dwMinorVersion << " " << osvi.dwBuildNumber << " "
+ << osvi.szCSDVersion;
+ if (archs.find(si.wProcessorArchitecture) != archs.end())
+ out << " " << archs[si.wProcessorArchitecture];
+ out << "\n";
+
+ out << "Machine: " << si.dwProcessorType;
+
+ return out.str();
+}
+
+string offscreen_context_getinfo(OffscreenContext *ctx)
+{
+ stringstream out;
+ out << "GL context creator: WGL\n"
+ out << "PNG generator: lodepng\n"
+ << get_windows_info();
+ return out.str();
+}
+
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
return DefWindowProc( hwnd, message, wparam, lparam );
@@ -142,7 +185,7 @@ OffscreenContext *create_offscreen_context(int w, int h)
cerr << "Unable to init GLEW: " << glewGetErrorString(err) << "\n";
return NULL;
}
- glew_dump();
+ //cerr << glew_dump(0);
ctx->fbo = fbo_new();
if (!fbo_init(ctx->fbo, w, h)) {
diff --git a/tests/OffscreenView.cc b/tests/OffscreenView.cc
index 46951c1..9c8964c 100644
--- a/tests/OffscreenView.cc
+++ b/tests/OffscreenView.cc
@@ -1,11 +1,13 @@
#include <GL/glew.h>
#include "OffscreenView.h"
+#include "system-gl.h"
#include <opencsg.h>
#include "renderer.h"
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <cstdlib>
+#include <sstream>
#define FAR_FAR_AWAY 100000.0
@@ -17,19 +19,6 @@ OffscreenView::OffscreenView(size_t width, size_t height)
this->ctx = create_offscreen_context(width, height);
if ( this->ctx == NULL ) throw -1;
-#ifdef DEBUG
- GLint rbits, gbits, bbits, abits, dbits, sbits;
- glGetIntegerv(GL_RED_BITS, &rbits);
- glGetIntegerv(GL_GREEN_BITS, &gbits);
- glGetIntegerv(GL_BLUE_BITS, &bbits);
- glGetIntegerv(GL_ALPHA_BITS, &abits);
- glGetIntegerv(GL_DEPTH_BITS, &dbits);
- glGetIntegerv(GL_STENCIL_BITS, &sbits);
-
- fprintf(stderr, "FBO: RGBA(%d%d%d%d), depth(%d), stencil(%d)\n",
- rbits, gbits, bbits, abits, dbits, sbits);
-#endif
-
initializeGL();
resizeGL(width, height);
}
@@ -249,6 +238,26 @@ bool OffscreenView::save(const char *filename)
return save_framebuffer(this->ctx, filename);
}
+std::string OffscreenView::getInfo()
+{
+ std::stringstream out;
+ GLint rbits, gbits, bbits, abits, dbits, sbits;
+ glGetIntegerv(GL_RED_BITS, &rbits);
+ glGetIntegerv(GL_GREEN_BITS, &gbits);
+ glGetIntegerv(GL_BLUE_BITS, &bbits);
+ glGetIntegerv(GL_ALPHA_BITS, &abits);
+ glGetIntegerv(GL_DEPTH_BITS, &dbits);
+ glGetIntegerv(GL_STENCIL_BITS, &sbits);
+
+ out << glew_dump(false)
+ << "FBO: RGBA(" << rbits << gbits << bbits << abits
+ << "), depth(" << dbits
+ << "), stencil(" << sbits << ")\n"
+ << offscreen_context_getinfo(this->ctx);
+
+ return out.str();
+}
+
void OffscreenView::setCamera(const Eigen::Vector3d &pos, const Eigen::Vector3d &center)
{
this->camera_eye = pos;
diff --git a/tests/OffscreenView.h b/tests/OffscreenView.h
index e3c8579..2e35921 100644
--- a/tests/OffscreenView.h
+++ b/tests/OffscreenView.h
@@ -4,6 +4,7 @@
#include "OffscreenContext.h"
#include <Eigen/Core>
#include <Eigen/Geometry>
+#include <string>
#ifndef _MSC_VER
#include <stdint.h>
#endif
@@ -22,6 +23,7 @@ public:
void setupOrtho(bool offset=false);
void paintGL();
bool save(const char *filename);
+ std::string getInfo();
GLint shaderinfo[11];
OffscreenContext *ctx;
diff --git a/tests/cgalpngtest.cc b/tests/cgalpngtest.cc
index bfa92da..cc747fb 100644
--- a/tests/cgalpngtest.cc
+++ b/tests/cgalpngtest.cc
@@ -190,16 +190,19 @@ int main(int argc, char **argv)
BoundingBox bbox;
if (cgalRenderer.polyhedron) {
+ std::cout << "polyhedron\n" ;
CGAL::Bbox_3 cgalbbox = cgalRenderer.polyhedron->bbox();
bbox = BoundingBox(Vector3d(cgalbbox.xmin(), cgalbbox.ymin(), cgalbbox.zmin()),
Vector3d(cgalbbox.xmax(), cgalbbox.ymax(), cgalbbox.zmax()));
}
else if (cgalRenderer.polyset) {
+ std::cout << "polyset\n" ;
bbox = cgalRenderer.polyset->getBoundingBox();
}
Vector3d center = getBoundingCenter(bbox);
double radius = getBoundingRadius(bbox);
+ std::cout << "radius: " << radius << "\n";
Vector3d cameradir(1, 1, -0.5);
Vector3d camerapos = center - radius*2*cameradir;
diff --git a/tests/csgtestcore.cc b/tests/csgtestcore.cc
index 034084c..a3d5097 100644
--- a/tests/csgtestcore.cc
+++ b/tests/csgtestcore.cc
@@ -25,8 +25,15 @@
#include <QDir>
#include <QSet>
#include <QTimer>
+
#include <sstream>
+#include <vector>
+
+#include <boost/program_options.hpp>
+namespace po = boost::program_options;
+using std::string;
+using std::vector;
using std::cerr;
using std::cout;
@@ -41,9 +48,9 @@ public:
CsgInfo();
CSGTerm *root_norm_term; // Normalized CSG products
class CSGChain *root_chain;
- std::vector<CSGTerm*> highlight_terms;
+ vector<CSGTerm*> highlight_terms;
CSGChain *highlights_chain;
- std::vector<CSGTerm*> background_terms;
+ vector<CSGTerm*> background_terms;
CSGChain *background_chain;
OffscreenView *glview;
};
@@ -51,9 +58,9 @@ public:
CsgInfo::CsgInfo() {
root_norm_term = NULL;
root_chain = NULL;
- highlight_terms = std::vector<CSGTerm*>();
+ highlight_terms = vector<CSGTerm*>();
highlights_chain = NULL;
- background_terms = std::vector<CSGTerm*>();
+ background_terms = vector<CSGTerm*>();
background_chain = NULL;
glview = NULL;
}
@@ -67,16 +74,81 @@ AbstractNode *find_root_tag(AbstractNode *n)
return NULL;
}
+string info_dump(OffscreenView *glview)
+{
+ assert(glview);
+
+#ifdef __GNUG__
+#define compiler_info "GCC " << __VERSION__
+#elif defined(_MSC_VER)
+#define compiler_info "MSVC " << _MSC_FULL_VER
+#else
+#define compiler_info "unknown compiler"
+#endif
+
+ std::stringstream out;
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+ out << "\nOpenSCAD Version: " << TOSTRING(OPENSCAD_VERSION)
+ << "\nCompiled by: " << compiler_info
+ << "\nCompile date: " << __DATE__
+ << "\nBoost version: " << BOOST_LIB_VERSION
+ << "\nEigen version: " << EIGEN_WORLD_VERSION << "."
+ << EIGEN_MAJOR_VERSION << "." << EIGEN_MINOR_VERSION
+ // << "\nCGAL version: " << CGAL_VERSION ???
+ // << "\nOpenCSG" << ???
+ << "\n" << glview->getInfo()
+ << "\n";
+
+ return out.str();
+}
+
+po::variables_map parse_options(int argc, char *argv[])
+{
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help,h", "help message")//;
+ ("info,i", "information on GLEW, OpenGL, OpenSCAD, and OS")//;
+
+// po::options_description hidden("Hidden options");
+// hidden.add_options()
+ ("input-file", po::value< vector<string> >(), "input file")
+ ("output-file", po::value< vector<string> >(), "ouput file");
+
+ po::positional_options_description p;
+ p.add("input-file", 1).add("output-file", 1);
+
+ po::options_description all_options;
+ all_options.add(desc); // .add(hidden);
+
+ po::variables_map vm;
+ po::store(po::command_line_parser(argc, argv).options(all_options).positional(p).run(), vm);
+ po::notify(vm);
+
+ return vm;
+}
+
int csgtestcore(int argc, char *argv[], test_type_e test_type)
{
- if (argc != 3) {
- fprintf(stderr, "Usage: %s <file.scad> <output.png>\n", argv[0]);
+ bool sysinfo_dump = false;
+ const char *filename, *outfilename = NULL;
+ po::variables_map vm;
+ try {
+ vm = parse_options(argc, argv);
+ } catch ( po::error e ) {
+ cerr << "error parsing options\n";
+ }
+ if (vm.count("info")) sysinfo_dump = true;
+ if (vm.count("input-file"))
+ filename = vm["input-file"].as< vector<string> >().begin()->c_str();
+ if (vm.count("output-file"))
+ outfilename = vm["output-file"].as< vector<string> >().begin()->c_str();
+
+ if ((!filename || !outfilename) && !sysinfo_dump) {
+ cerr << "Usage: " << argv[0] << " <file.scad> <output.png>\n";
exit(1);
}
- const char *filename = argv[1];
- const char *outfilename = argv[2];
-
Builtins::instance()->initialize();
QApplication app(argc, argv, false);
@@ -110,7 +182,11 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type)
AbstractModule *root_module;
ModuleInstantiation root_inst;
- root_module = parsefile(filename);
+ if (sysinfo_dump)
+ root_module = parse("sphere();","",false);
+ else
+ root_module = parsefile(filename);
+
if (!root_module) {
exit(1);
}
@@ -194,6 +270,7 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type)
fprintf(stderr,"Can't create OpenGL OffscreenView. Code: %i. Exiting.\n", error);
exit(1);
}
+ if (sysinfo_dump) cout << info_dump(csgInfo.glview);
BoundingBox bbox = csgInfo.root_chain->getBoundingBox();
Vector3d center = (bbox.min() + bbox.max()) / 2;
diff --git a/tests/fbo.cc b/tests/fbo.cc
index 2a3342d..a6677c1 100644
--- a/tests/fbo.cc
+++ b/tests/fbo.cc
@@ -93,6 +93,7 @@ bool fbo_ext_init(fbo_t *fbo, size_t width, size_t height)
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, fbo->depthbuf_id);
if (report_glerror("specifying depth render buffer EXT")) return false;
+
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, fbo->depthbuf_id);
if (report_glerror("specifying stencil render buffer EXT")) return false;
@@ -142,7 +143,12 @@ bool fbo_arb_init(fbo_t *fbo, size_t width, size_t height)
return false;
}
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+ //glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+ // to prevent Mesa's software renderer from crashing, do this in two stages.
+ // ie. instead of using GL_DEPTH_STENCIL_ATTACHMENT, do DEPTH then STENCIL.
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, fbo->depthbuf_id);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, fbo->depthbuf_id);
if (report_glerror("specifying depth stencil render buffer")) return false;
@@ -183,24 +189,25 @@ bool fbo_resize(fbo_t *fbo, size_t width, size_t height)
glBindRenderbufferEXT(GL_RENDERBUFFER, fbo->depthbuf_id);
if (glewIsSupported("GL_EXT_packed_depth_stencil")) {
glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
- if (report_glerror("creating depth stencil render buffer")) return false;
+ if (report_glerror("creating EXT depth stencil render buffer")) return false;
}
else {
glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
- if (report_glerror("creating depth render buffer")) return false;
+ if (report_glerror("creating EXT depth render buffer")) return false;
}
glBindRenderbufferEXT(GL_RENDERBUFFER, fbo->renderbuf_id);
glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_RGBA8, width, height);
- if (report_glerror("creating color render buffer")) return false;
+ if (report_glerror("creating EXT color render buffer")) return false;
} else {
+ glBindRenderbuffer(GL_RENDERBUFFER, fbo->renderbuf_id);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
+ if (report_glerror("creating color render buffer")) return false;
+
glBindRenderbuffer(GL_RENDERBUFFER, fbo->depthbuf_id);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
if (report_glerror("creating depth stencil render buffer")) return false;
- glBindRenderbuffer(GL_RENDERBUFFER, fbo->renderbuf_id);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
- if (report_glerror("creating color render buffer")) return false;
}
return true;
diff --git a/tests/system-gl.cc b/tests/system-gl.cc
index f95a5ca..2e3f3bc 100644
--- a/tests/system-gl.cc
+++ b/tests/system-gl.cc
@@ -2,34 +2,40 @@
/* OpenGL helper functions */
#include <iostream>
+#include <sstream>
+#include <string>
#include "system-gl.h"
#include <boost/algorithm/string.hpp>
using namespace std;
using namespace boost;
-void glew_dump() {
- cerr << "GLEW version: " << glewGetString(GLEW_VERSION) << endl
- << "Renderer: " << (const char *)glGetString(GL_RENDERER) << endl
- << "Vendor: " << (const char *)glGetString(GL_VENDOR) << endl
- << "OpenGL version: " << (const char *)glGetString(GL_VERSION) << endl;
+string glew_dump(bool dumpall)
+{
+ stringstream out;
+ out << "GLEW version: " << glewGetString(GLEW_VERSION) << endl
+ << "GL Renderer: " << (const char *)glGetString(GL_RENDERER) << endl
+ << "GL Vendor: " << (const char *)glGetString(GL_VENDOR) << endl
+ << "OpenGL Version: " << (const char *)glGetString(GL_VERSION) << endl;
- bool dumpall = false;
+ out << "GL Extensions: " << endl;
if (dumpall) {
string extensions((const char *)glGetString(GL_EXTENSIONS));
replace_all( extensions, " ", "\n " );
- cerr << "Extensions: " << endl << " " << extensions << endl;
+ out << " " << extensions << endl;
}
- cerr << " GL_ARB_framebuffer_object: "
- << (glewIsSupported("GL_ARB_framebuffer_object") ? "yes" : "no")
- << endl
- << " GL_EXT_framebuffer_object: "
- << (glewIsSupported("GL_EXT_framebuffer_object") ? "yes" : "no")
- << endl
- << " GL_EXT_packed_depth_stencil: "
- << (glewIsSupported("GL_EXT_packed_depth_stencil") ? "yes" : "no")
- << endl;
+ out << "GL_ARB_framebuffer_object: "
+ << (glewIsSupported("GL_ARB_framebuffer_object") ? "yes" : "no")
+ << endl
+ << "GL_EXT_framebuffer_object: "
+ << (glewIsSupported("GL_EXT_framebuffer_object") ? "yes" : "no")
+ << endl
+ << "GL_EXT_packed_depth_stencil: "
+ << (glewIsSupported("GL_EXT_packed_depth_stencil") ? "yes" : "no")
+ << endl;
+
+ return out.str();
};
bool report_glerror(const char * function)
diff --git a/tests/system-gl.h b/tests/system-gl.h
index bb41be5..45d5130 100644
--- a/tests/system-gl.h
+++ b/tests/system-gl.h
@@ -2,8 +2,9 @@
#define SYSTEMGL_H_
#include <GL/glew.h>
+#include <string>
-void glew_dump();
+std::string glew_dump(bool dumpall);
bool report_glerror(const char *task);
#endif
diff --git a/tests/test_cmdline_tool.py b/tests/test_cmdline_tool.py
index 688026e..3e9f45a 100755
--- a/tests/test_cmdline_tool.py
+++ b/tests/test_cmdline_tool.py
@@ -64,16 +64,21 @@ def compare_text(expected, actual):
return get_normalized_text(expected) == get_normalized_text(actual)
def compare_default(resultfilename):
+ print >> sys.stderr, 'diff text compare: '
+ print >> sys.stderr, ' expected textfile: ', expectedfilename
+ print >> sys.stderr, ' actual textfile: ', resultfilename
if not compare_text(expectedfilename, resultfilename):
execute_and_redirect("diff", [expectedfilename, resultfilename], sys.stderr)
return False
return True
def compare_png(resultfilename):
+ print >> sys.stderr, 'Yee image compare:'
+ print >> sys.stderr, ' expected image: ', expectedfilename
if not resultfilename:
- print >> sys.stderr, "Error: OpenSCAD did not generate an image"
+ print >> sys.stderr, "Error: OpenSCAD did not generate an image to test"
return False
- print >> sys.stderr, 'Yee image compare: ', expectedfilename, ' ', resultfilename
+ print >> sys.stderr, ' actual image: ', resultfilename
if execute_and_redirect("./yee_compare", [expectedfilename, resultfilename, "-downsample", "2", "-threshold", "300"], sys.stderr) != 0:
return False
return True
diff --git a/tests/test_pretty_print.py b/tests/test_pretty_print.py
new file mode 100755
index 0000000..897f7b8
--- /dev/null
+++ b/tests/test_pretty_print.py
@@ -0,0 +1,321 @@
+#!/usr/bin/python
+#
+# This program 'pretty prints' the ctest output, namely
+# files from builddir/Testing/Temporary.
+# html & wiki output are produced
+# wiki uploading is available by running
+#
+# python test_pretty_print.py --upload
+
+# todo
+# ban opencsg<2.0 from opencsgtest
+# copy all images, sysinfo.txt to bundle for html/upload (images
+# can be altered by subsequent runs)
+# figure out hwo to make the thing run after the test
+# figure out how CTEST treats the logfiles.
+# why is hash differing
+# instead of having special '-info' prerun, put it as yet-another-test
+# and parse the log
+# provide option to replace 'expected' images on wiki
+# (yes sometimes you do need to change/update them)
+
+import string,sys,re,os,hashlib,subprocess
+
+def tryread(filename):
+ data = None
+ try:
+ print 'reading', filename
+ f = open(filename)
+ data = f.read()
+ f.close()
+ except:
+ print 'couldn\'t open ',filename
+ return data
+
+def trysave(data,filename):
+ try:
+ f=open(filename,'w')
+ print 'writing',len(data),'bytes to',filename
+ f.write(data)
+ f.close()
+ except:
+ print 'problem writing to',filename
+ 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.
+ 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'
+ return out
+
+def read_sysinfo(filename):
+ data = tryread(filename)
+ if not data: return 'sysinfo: unknown'
+
+ 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'
+
+ renderer = ezsearch('GL Renderer:(.*?)\n',data)
+ tmp = renderer.split(' ')
+ tmp = string.join(tmp[0:3],'-')
+ tmp = tmp.split('/')[0]
+ renderer = tmp
+
+ hexhash = hashlib.md5()
+ hexhash.update(data)
+ hexhash = hexhash.hexdigest()[-4:].upper()
+ hash = ''
+ for c in hexhash: hash += chr(ord(c)+97-48)
+
+ sysid = osplain + '_' + machine + '_' + renderer + '_' + hash
+ sysid = sysid.lower()
+
+ data += read_gitinfo()
+
+ data += 'Image comparison: PerceptualDiff by H. Yee'
+ 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 parsetest(teststring):
+ patterns = ["Test:(.*?)\n", # fullname
+ "Test time =(.*?) sec\n",
+ "Test time.*?Test (Passed)",
+ "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)
+ 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 )
+ print 'found', len(tests),'test results'
+ return startdate, tests, enddate
+
+def wikify_filename(testname,filename,sysid):
+ # translate from local system to wiki style filename.
+ result = wiki_rootpath+'_'+testname+'_'
+ expected = ezsearch('(expected....$)',filename)
+ if expected!='': result += expected
+ actual = ezsearch(os.sep+'.*?-output.*?(actual.*)',filename)
+ if actual!='':
+ result += sysid+'_'+actual
+ return result.replace('/','_')
+
+
+def towiki(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, testlog):
+ 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>
+
+'''Failed image tests'''
+
+{| border=1 cellspacing=0 cellpadding=1
+! Testname !! expected output !! actual output
+<REPEAT1>
+|-
+| FTESTNAME || [[File:EXPECTEDFILE|thumb|250px]] || ACTUALFILE_WIKI
+</REPEAT1>
+|}
+
+'''Failed text tests'''
+
+{|border=1 cellspacing=0 cellpadding=1
+! Testname
+<REPEAT2>
+|-
+| FTESTNAME
+</REPEAT2>
+|}
+
+'''Test logs'''
+
+(excerpted from Testing/Temporary/LastTest.Log)
+
+<pre>
+FAILED_TESTLOGS
+</pre>
+
+"""
+ numpassed = len(filter(lambda x: x.passed, tests))
+ percent = str(int(100.0*numpassed / len(tests)))
+ manifest = {}
+ s = wiki_template
+ repeat1 = ezsearch('(<REPEAT1>.*?</REPEAT1>)',s)
+ repeat2 = ezsearch('(<REPEAT2>.*?</REPEAT2>)',s)
+ dic = { 'STARTDATE': startdate, 'ENDDATE': enddate, 'WIKI_ROOTPATH': wiki_rootpath,
+ 'SYSINFO': sysinfo, 'SYSID':sysid, 'LASTTESTLOG':testlog,
+ 'NUMTESTS':len(tests), 'NUMPASSED':numpassed, 'PERCENTPASSED':percent }
+ for key in dic.keys():
+ s = re.sub(key,str(dic[key]),s)
+ testlogs = ''
+ for t in tests:
+ # if t.passed: noop
+ if not t.passed:
+ testlogs += '\n\n'+t.fulltestlog
+ if t.type=='txt':
+ newchunk = re.sub('FTEST_OUTPUTFILE',t.fullname,repeat2)
+ newchunk = re.sub('FTESTNAME',t.fullname,repeat2)
+ s = s.replace(repeat2, newchunk+repeat2)
+ elif t.type=='png':
+ manifest[t.actualfile] = wikify_filename(t.fullname,t.actualfile,sysid)
+ manifest[t.expectedfile] = wikify_filename(t.fullname,t.expectedfile,sysid)
+ if t.actualfile:
+ actualfile_wiki = '[[File:'+manifest[t.actualfile]+'|thumb|250px]]'
+ else:
+ actualfile_wiki = 'No file generated.<br/>See log for details'
+ newchunk = re.sub('FTESTNAME',t.fullname,repeat1)
+ newchunk = newchunk.replace('ACTUALFILE_WIKI',actualfile_wiki)
+ newchunk = newchunk.replace('EXPECTEDFILE',manifest[t.expectedfile])
+ s = s.replace(repeat1, newchunk+repeat1)
+ s = s.replace('FAILED_TESTLOGS',testlogs)
+ s = s.replace(repeat1,'')
+ s = s.replace(repeat2,'')
+ s = re.sub('<REPEAT.*?>\n','',s)
+ s = re.sub('</REPEAT.*?>','',s)
+ return manifest, s
+
+
+def wikitohtml(wiki_rootpath, sysid, wikidata, manifest):
+ head = '<html><head><title>'+wiki_rootpath+' test run for '+sysid +'</title></head><body>'
+ revmanifest = dict((val,key) for key, val in manifest.iteritems())
+ x=re.sub('\{\|(.*?)\n','<table \\1>\n',wikidata)
+ x=re.sub("'''(.*?)'''","<b>\\1</b>",x)
+ filestrs=re.findall('\[\[File\:(.*?)\|.*?\]\]',x)
+ for f in filestrs:
+ newfile_html='<img src="'+revmanifest[f]+'" width=250/>'
+ x=re.sub('\[\[File\:'+f+'\|.*?\]\]',newfile_html,x)
+ dic = { '|}':'</table>', '|-':'<tr>', '||':'<td>', '|':'<td>',
+ '!!':'<th>', '!':'<tr><th>', '\n\n':'\n<p>\n'} #order matters
+ for key in dic: x=x.replace(key,dic[key])
+ x=re.sub("\[\[(.*?)\]\]","\\1",x)
+ return head + x + '</body></html>'
+
+def upload_dryrun(wikiurl,api_php_path,wikidata,manifest,wiki_rootpath,sysid,botname,botpass):
+ print 'dry run. no files to be uploaded'
+ print 'log in', wikiurl, api_php_path, botname, botpass
+ print 'save ' + '*[['+wiki_rootpath+sysid+']]' + ' to page ' + wiki_rootpath
+ print 'save ', len(wikidata), ' bytes to page ',wiki_rootpath+sysid
+ for localfile in manifest.keys():
+ if localfile:
+ localf=open(localfile)
+ wikifile = manifest[localfile]
+ print 'upload',localfile,wikifile
+
+def upload(wikiurl,api_php_path,wikidata,manifest,wiki_rootpath,sysid,botname,botpass,dryrun=True):
+ if dryrun:
+ upload_dryrun(wikiurl,api_php_path,wikidata,manifest,wiki_rootpath,sysid,botname,botpass)
+ return None
+ try:
+ import mwclient
+ except:
+ print 'please download mwclient and unpack here:', os.cwd()
+ print 'open site',wikiurl
+ if not api_php_path == '':
+ site = mwclient.Site(wikiurl,api_php_path)
+ else:
+ site = mwclient.Site(wikiurl)
+
+ print 'bot login'
+ site.login(botname,botpass)
+
+ print 'edit ',wiki_rootpath
+ page = site.Pages[wiki_rootpath]
+ text = page.edit()
+ rootpage = wiki_rootpath + sysid
+ if not '[['+rootpage+']]' in text:
+ page.save(text +'\n*[['+rootpage+']]\n')
+
+ print 'upload wiki data to',rootpage
+ page = site.Pages[rootpage]
+ text = page.edit()
+ page.save(wikidata)
+
+ print 'upload images'
+ for localfile in sorted(manifest.keys()):
+ if localfile:
+ localf=open(localfile)
+ wikifile = manifest[localfile]
+ skip=False
+ if 'expected.png' in wikifile.lower():
+ image = site.Images[wikifile]
+ if image.exists:
+ print 'skipping ',wikifile, '(expected image, already on wiki)'
+ skip=True
+ if not skip:
+ print wikifile,'...'
+ site.upload(localf,wikifile,wiki_rootpath + ' test', ignore=True)
+
+wikisite = 'cakebaby.referata.com'
+wiki_rootpath = 'OpenSCAD'
+builddir = os.getcwd()
+logpath = os.path.join(builddir,'Testing','Temporary')
+logfilename = os.path.join(logpath,'LastTest.log')
+
+def main():
+ testlog = tryread(logfilename)
+ startdate, tests, enddate = parselog(testlog)
+ tests = sorted(tests, key = lambda t:t.passed)
+ sysinfo, sysid = read_sysinfo('sysinfo.txt')
+ if '--hack' in sys.argv: sysid+='_hack'
+ manifest, wikidata = towiki(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, testlog)
+ trysave(wikidata, os.path.join(logpath,sysid+'.wiki'))
+ htmldata = wikitohtml(wiki_rootpath, sysid, wikidata, manifest)
+ trysave(htmldata, os.path.join(logpath,sysid+'.html'))
+ if '--upload' in sys.argv:
+ upload(wikisite,'',wikidata,manifest,wiki_rootpath,sysid,'openscadbot','tobdacsnepo',dryrun=False)
+main()
+
contact: Jan Huwald // Impressum