[Python-Dev] Re: C testing framework

Trent Mick trentm@ActiveState.com
Wed, 26 Jul 2000 16:01:57 -0700


On Tue, Jul 25, 2000 at 01:09:58PM -0500, Skip Montanaro wrote:
> 
>     [c-based testing framework]
> 
>     Trent> Show it? PEP it? Forget it?
> 
> I say show it.  I see no reason to make a PEP unless there are a number of
> potential immediate alternatives.  It doesn't affect the functionality of
> the distribution, only its quality.  If something better comes along later,
> Trent's can be replaced.

Here is a proposed patch for a Python/C API testing framework. Simple simple.

Basic Overview:

- add a _test C extension module that exports test functions beginning with
  'test_'; NULL and a TestError exception indicates a test failure and
  Py_None indicate a test pass
- add a test_capi.py test module that calls each of the 'test_' exported
  functions in the '_test' module
- changes to the build system files for Win32 and Unix are includes to build
  _testmodule.c as a shared extension
- new files: Lib/test/test_capi.py, Lib/test/output/test_capi,
  Modules/_testmodule.c, and PCbuild/_test.dsp


Patch:


*** /home/trentm/main/contrib/python/dist/src/Lib/test/test_capi.py	Wed Jul 26 15:39:35 2000
--- /home/trentm/main/Apps/Perlium/Python/dist/src/Lib/test/test_capi.py	Wed Jul 26 10:37:31 2000
***************
*** 0 ****
--- 1,17 ----
+ import sys
+ import test_support
+ import _test
+ 
+ # import and run the _test module tests (tests for the Python/C API)
+ #
+ # (any exported function beginning with 'test_')
+ 
+ for name in dir(_test):
+ 	if name.startswith('test_'):
+ 		test = getattr(_test, name)
+ 		if test_support.verbose:
+ 			print "internal", name
+ 		try:
+ 			test()
+ 		except _test.error:
+ 			raise test_support.TestFailed, sys.exc_info()[1]
*** /home/trentm/main/contrib/python/dist/src/Lib/test/output/test_capi	Wed Jul 26 15:39:35 2000
--- /home/trentm/main/Apps/Perlium/Python/dist/src/Lib/test/output/test_capi	Wed Jul 26 10:36:37 2000
***************
*** 0 ****
--- 1 ----
+ test_capi
*** /home/trentm/main/contrib/python/dist/src/Modules/_testmodule.c	Wed Jul 26 15:39:35 2000
--- /home/trentm/main/Apps/Perlium/Python/dist/src/Modules/_testmodule.c	Wed Jul 26 15:39:31 2000
***************
*** 0 ****
--- 1,64 ----
+ //---------------------------------------------------------------------------
+ // C Extension module to test Python interpreter C APIs.
+ //
+ // The 'test_*' functions exprted by this module are run as part of
+ // the standard Python regression test (via test_capi.py).
+ //---------------------------------------------------------------------------
+ 
+ #include "Python.h"
+ #include "marshal.h"
+ 
+ #define TEST_FILENAME "__test_filename"   // filename used for testing
+ 
+ PyObject *TestError;
+ 
+ 
+ /* test defines from config.h (particularly the SIZEOF_* defines)
+ 
+    The ones derived from autoconf on the UNIX-like OSes can be relied
+    upon, but the Microsoft platform have these hardcoded. Better safe
+    than sorry.
+ */
+ PyObject*
+ test_config(PyObject *self, PyObject *args)
+ {
+     /*XXX could probably break these out to allow the error message to be
+      * better, as well could test more config.h settings */
+     if (SIZEOF_INT != sizeof(int) ||
+ 		SIZEOF_LONG != sizeof(long) ||
+ #ifdef HAVE_LONG_LONG
+ 		SIZEOF_LONG_LONG != sizeof(LONG_LONG) ||
+ #endif
+ 		SIZEOF_VOID_P != sizeof(void*) ||
+ 		SIZEOF_TIME_T != sizeof(time_t)) {
+ 		PyErr_SetString(TestError,
+ 			"SIZEOF_* configuration defines are not all correct");
+ 		return NULL;
+ 	}
+ 	
+ 	Py_INCREF(Py_None);
+ 	return Py_None;
+ }
+ 
+ 
+ 
+ 
+ /* must defined special structure to define methods and attributes to Python */
+ static PyMethodDef TestMethods[] = {
+ 	{"test_config", test_config, METH_VARARGS},
+ 	{NULL, NULL} /* sentinel */
+ };
+ 
+ 
+ /* must define intialization function, often 'init<modulename>' */
+ DL_EXPORT(void)
+ init_test(void)
+ {
+ 	PyObject *m, *d;
+ 	
+ 	m = Py_InitModule("_test", TestMethods);
+ 	
+ 	TestError = PyErr_NewException("_test.error", NULL, NULL);
+ 	d = PyModule_GetDict(m);
+ 	PyDict_SetItemString(d, "error", TestError);
+ }
*** /home/trentm/main/contrib/python/dist/src/Modules/Setup.in	Fri Jun 30 09:05:22 2000
--- /home/trentm/main/Apps/Perlium/Python/dist/src/Modules/Setup.in	Wed Jul 26 14:30:37 2000
***************
*** 426,431 ****
--- 426,436 ----
  #EXPAT_DIR=/usr/local/src/expat
  #pyexpat pyexpat.c -I$(EXPAT_DIR)/xmlparse -L$(EXPAT_DIR) -lexpat
  
+ # internal C API testing module (tests exprted by this module are
+ # called as part of the test suite)
+ *shared*
+ _test _testmodule.c
+ *static*
  
  # Example -- included for reference only:
  # xx xxmodule.c
*** /home/trentm/main/contrib/python/dist/src/PCbuild/_test.dsp	Wed Jul 26 15:39:35 2000
--- /home/trentm/main/Apps/Perlium/Python/dist/src/PCbuild/_test.dsp	Wed Jul 26 14:30:03 2000
***************
*** 0 ****
--- 1,100 ----
+ # Microsoft Developer Studio Project File - Name="_test" - Package Owner=<4>
+ # Microsoft Developer Studio Generated Build File, Format Version 6.00
+ # ** DO NOT EDIT **
+ 
+ # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+ 
+ CFG=_test - Win32 Debug
+ !MESSAGE This is not a valid makefile. To build this project using NMAKE,
+ !MESSAGE use the Export Makefile command and run
+ !MESSAGE 
+ !MESSAGE NMAKE /f "_test.mak".
+ !MESSAGE 
+ !MESSAGE You can specify a configuration when running NMAKE
+ !MESSAGE by defining the macro CFG on the command line. For example:
+ !MESSAGE 
+ !MESSAGE NMAKE /f "_test.mak" CFG="_test - Win32 Debug"
+ !MESSAGE 
+ !MESSAGE Possible choices for configuration are:
+ !MESSAGE 
+ !MESSAGE "_test - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+ !MESSAGE "_test - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+ !MESSAGE 
+ 
+ # Begin Project
+ # PROP AllowPerConfigDependencies 0
+ # PROP Scc_ProjName ""
+ # PROP Scc_LocalPath ""
+ CPP=cl.exe
+ MTL=midl.exe
+ RSC=rc.exe
+ 
+ !IF  "$(CFG)" == "_test - Win32 Release"
+ 
+ # PROP BASE Use_MFC 0
+ # PROP BASE Use_Debug_Libraries 0
+ # PROP BASE Output_Dir "Release"
+ # PROP BASE Intermediate_Dir "Release"
+ # PROP BASE Target_Dir ""
+ # PROP Use_MFC 0
+ # PROP Use_Debug_Libraries 0
+ # PROP Output_Dir "."
+ # PROP Intermediate_Dir "x86-temp-release\_test"
+ # PROP Ignore_Export_Lib 0
+ # PROP Target_Dir ""
+ F90=df.exe
+ # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_TEST_EXPORTS" /YX /FD /c
+ # ADD CPP /nologo /MD /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+ # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+ # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+ # ADD BASE RSC /l 0x409 /d "NDEBUG"
+ # ADD RSC /l 0x409 /d "NDEBUG"
+ BSC32=bscmake.exe
+ # ADD BASE BSC32 /nologo
+ # ADD BSC32 /nologo
+ LINK32=link.exe
+ # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+ # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"./_test.pyd" /export:init_test
+ # SUBTRACT LINK32 /pdb:none
+ 
+ !ELSEIF  "$(CFG)" == "_test - Win32 Debug"
+ 
+ # PROP BASE Use_MFC 0
+ # PROP BASE Use_Debug_Libraries 1
+ # PROP BASE Output_Dir "Debug"
+ # PROP BASE Intermediate_Dir "Debug"
+ # PROP BASE Target_Dir ""
+ # PROP Use_MFC 0
+ # PROP Use_Debug_Libraries 1
+ # PROP Output_Dir "."
+ # PROP Intermediate_Dir "x86-temp-debug\_test"
+ # PROP Ignore_Export_Lib 0
+ # PROP Target_Dir ""
+ F90=df.exe
+ # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "_TEST_EXPORTS" /YX /FD /GZ /c
+ # ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\Include" /I "..\PC" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
+ # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+ # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+ # ADD BASE RSC /l 0x409 /d "_DEBUG"
+ # ADD RSC /l 0x409 /d "_DEBUG"
+ BSC32=bscmake.exe
+ # ADD BASE BSC32 /nologo
+ # ADD BSC32 /nologo
+ LINK32=link.exe
+ # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+ # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"./_test_d.pyd" /pdbtype:sept /export:init_test
+ # SUBTRACT LINK32 /pdb:none
+ 
+ !ENDIF 
+ 
+ # Begin Target
+ 
+ # Name "_test - Win32 Release"
+ # Name "_test - Win32 Debug"
+ # Begin Source File
+ 
+ SOURCE=..\Modules\_testmodule.c
+ # ADD CPP /I "..\Include" /I "..\PC"
+ # End Source File
+ # End Target
+ # End Project
*** /home/trentm/main/contrib/python/dist/src/PCbuild/pcbuild.dsw	Wed Jul 26 15:10:27 2000
--- /home/trentm/main/Apps/Perlium/Python/dist/src/PCbuild/pcbuild.dsw	Wed Jul 26 15:13:22 2000
***************
*** 33,38 ****
--- 33,53 ----
  
  ###############################################################################
  
+ Project: "_test"=".\_test.dsp" - Package Owner=<4>
+ 
+ Package=<5>
+ {{{
+ }}}
+ 
+ Package=<4>
+ {{{
+     Begin Project Dependency
+     Project_Dep_Name python20
+     End Project Dependency
+ }}}
+ 
+ ###############################################################################
+ 
  Project: "_tkinter"=".\_tkinter.dsp" - Package Owner=<4>
  
  Package=<5>


-- 
Trent Mick
TrentM@ActiveState.com