Commits

Anonymous committed 172a2f5

Added missing pgcompat.h include to pygame2.base module installation target.
Fixed argument NULL pointer checks for C API calls.
Added first, simple C api tests under test/c_api.

Comments (0)

Files changed (23)

 	$(top_srcdir)/doc \
 	$(top_srcdir)/doc/src \
 	$(top_srcdir)/test \
+	$(top_srcdir)/test/c_api \
 	$(top_srcdir)/test/util \
 	$(top_srcdir)/lib \
 	$(top_srcdir)/lib/sdl \

examples/physics/simple.py

     world = None
     world = physics.World ()
     world.gravity = 0, 1
+    
+    for i in range(1, 2):
+        shape = physics.RectShape ((0, 0, 30, 28))
+        body = physics.Body (shape)
+        body.position = 400, 100 + 40 * i
+        body.rotation = 33 * i
+        body.restitution = 0.0
+        body.mass = 20
+        world.add_body (body)
+    
+    shape = physics.RectShape ((0, 0, 760, 20))
+    base = physics.Body (shape)
+    base.position = 20, 300
+    base.restitution = 0.0
+    base.rotation = 15
+    base.static = True
+    base.mass = 1e100
 
-    shape = physics.RectShape ((0, 0, 20, 20))
-    body = physics.Body (shape)
-    body.position = 0, 0
-    body.velocity = 2, 0
-    body.restitution = 1
-    body.mass = 20
-
-    world.add_body (body)
-    
-    shape = physics.RectShape ((0, 0, 100, 10))
-    base = physics.Body (shape)
-    base.position = 0, 400
-    base.static = True
-    base.mass = 200000
-    
     world.add_body (base)
-    
     return world
 
 def run ():
                       "src/base/color.c",
                       "src/base/floatrect.c",
                       "src/base/rect.c" ],
-            [ "src/base/pgbase.h",
+            [ "src/pgcompat.h",
+              "src/base/pgbase.h",
               "src/base/pgdefines.h",
               "src/base/pgtypes.h" ], "base.xml"),
 

src/mask/maskmod.c

     }
 
     /* lock the surface, release the GIL. */
-    lock = PySurface_AcquireLockObj (surfobj, self);
+    lock = PySurface_AcquireLockObj (surfobj, (PyObject*)mask);
     if (!lock)
         return NULL;
 
         PyErr_SetString (PyExc_MemoryError, "memory allocation failed");
         return NULL;
     }
-    
-    lock1 = PySurface_AcquireLockObj (surfobj, self);
+
+    maskobj = (PyMask*)PyMask_Type.tp_new (&PyMask_Type, NULL, NULL);
+    if (!maskobj)
+    {
+        bitmask_free (m);
+        return NULL;
+    }
+
+    lock1 = PySurface_AcquireLockObj (surfobj, (PyObject*)maskobj);
     if (!lock1)
     {
+        Py_DECREF (maskobj);
         bitmask_free (m);
         return NULL;
     }
 
     if (surfobj2)
     {
-        lock2 = PySurface_AcquireLockObj (surfobj2, self);
+        lock2 = PySurface_AcquireLockObj (surfobj2, (PyObject*)maskobj);
         if (!lock2)
         {
             Py_DECREF (lock1);
+            Py_DECREF (maskobj);
             bitmask_free (m);
             return NULL;
         }
     Py_DECREF (lock1);
     Py_XDECREF (lock2);
 
-    maskobj = (PyMask*)PyMask_Type.tp_new (&PyMask_Type, NULL, NULL);
-    if(maskobj)
-        maskobj->mask = m;
-    else
-        bitmask_free (m);
-
+    maskobj->mask = m;
     return (PyObject*)maskobj;
 }
 

src/physics/aabbox.c

     from_y = MAX (boxA->bottom, boxB->bottom);
     to_x = MIN (boxA->right, boxB->right);
     to_y = MIN (boxA->top, boxB->top);
-    return from_x - eps <= to_x + eps && from_y - eps <= to_y + eps;
+
+    return (from_x - eps <= to_x + eps) && (from_y - eps <= to_y + eps);
 }
 
 int
 {
     double x, y, w, h;
     AABBox *box;
-    if (!PySequence_Check (seq) || PySequence_Size (seq) < 4)
+    if (!seq || !PySequence_Check (seq) || PySequence_Size (seq) < 4)
     {
         PyErr_SetString (PyExc_TypeError,
             "argument must be a 4-value sequence");
 {
     double t, l, b, r;
     AABBox *box;
+
+    if (!rect)
+    {
+        PyErr_SetString (PyExc_TypeError,
+            "argument must be a Rect, FRect or 4-value sequence");
+        return NULL;
+    }
+
     if (PyRect_Check (rect))
     {
         l = ((PyRect*)rect)->x;

src/physics/body.c

     if (!PyArg_ParseTuple (args, "O", &shape))
         return -1;
 
-    if (!PyShape_Check (shape))
+    if (!shape || !PyShape_Check (shape))
     {
         PyErr_SetString (PyExc_TypeError, "shape must be a Shape");
         return -1;
     if (!body)
         return NULL;
 
-    if (!PyShape_Check (shape))
+    if (!shape || !PyShape_Check (shape))
     {
         PyErr_SetString (PyExc_TypeError, "shape must be a Shape");
         Py_DECREF (body);
 PyObject*
 PyBody_CheckCollision (PyObject *body1, PyObject *body2)
 {
-    if (!PyBody_Check (body1) || !PyBody_Check (body2))
+    if (!body1 || !body2 || !PyBody_Check (body1) || !PyBody_Check (body2))
     {
         PyErr_SetString (PyExc_TypeError,
             "body arguments must be Body objects");
 PyObject*
 PyBody_GetPoints (PyObject *body)
 {
-    if (!PyBody_Check (body))
+    if (!body || !PyBody_Check (body))
     {
         PyErr_SetString (PyExc_TypeError, "argument must be a Body");
         return NULL;

src/physics/collision.c

     {
         conts[0][i] = collision->contacts[i];
         /* TODO: Maybe invert pos1/pos2 */
-        conts[1][i] = PyVector2_Transform (conts[0][i], *pos1, rot1, *pos2, rot2);
+        conts[1][i] = PyVector2_Transform (conts[0][i], *pos1, rot1,
+            *pos2, rot2);
     }
     
     box[0] = box1;
     box[1] = box2;
-    /* TODO */
     ppos[0] = incpos[1] = *pos1;
     prot[0] = incrot[1] = rot1;
     ppos[1] = incpos[0] = *pos2;
     PyRectShape *rsh1 = (PyRectShape*) shape1;
     PyRectShape *rsh2 = (PyRectShape*) shape2;
 
+    if (!shape1 || !shape2)
+        return NULL;
+
     collision.normal.real = collision.normal.imag = 0;
     
     box1 = PyShape_GetAABBox_FAST (shape1);

src/physics/contact.c

 PyObject*
 PyContact_New (void)
 {
-    /* TODO */
     return (PyObject*) PyContact_Type.tp_new (&PyContact_Type, NULL, NULL);
 }
 
 int
 PyContact_Collision (PyObject *contact, double steptime)
 {
-    if (!PyContact_Check (contact))
+    if (!contact || !PyContact_Check (contact))
     {
         PyErr_SetString (PyExc_TypeError, "contact must be a Contact");
         return 0;
 PyContact_Collision_FAST (PyContact *contact, double steptime)
 {
 /**
- * MAX_C_DEP is the maximal permitted penetrating depth after collision reaction.
- * BIAS_FACTOR is a empirical factor. The two constants are used for position collision
- * after collision reaction is done.
+ * MAX_C_DEP is the maximal permitted penetrating depth after collision
+ * reaction.
+ * BIAS_FACTOR is a empirical factor. The two constants are used for
+ * position collision after collision reaction is done.
  * for further learning you can read Erin Canto's GDC 2006 Slides, page 23.
  * (You can download it from www.gphysics.com)
  */
 
     /*
      * The algorithm below is an implementation of the empirical formula for
-	 * impulse-based collision reaction. You can learn the formula thoroughly
-	 * from Helmut Garstenauer's thesis, Page 60.
+     * impulse-based collision reaction. You can learn the formula thoroughly
+     * from Helmut Garstenauer's thesis, Page 60.
      */
     refR = c_diff(contact->position, refBody->position);
     incidR = c_diff(contact->position, incidBody->position);
     //dV = v2 + w2xr2 - (v1 + w1xr1)
-    incidV = c_sum(incidBody->linear_velocity, PyVector2_fCross(incidBody->angle_velocity,
-            incidR));
-    refV = c_sum(refBody->linear_velocity, PyVector2_fCross(refBody->angle_velocity,
-            refR));
+    incidV = c_sum(incidBody->linear_velocity,
+        PyVector2_fCross(incidBody->angle_velocity, incidR));
+    refV = c_sum(refBody->linear_velocity,
+        PyVector2_fCross(refBody->angle_velocity, refR));
 
     contact->dv = c_diff(incidV, refV);
     neg_dV = c_diff(refV, incidV);
 	
-    moment_len = PyVector2_Dot(PyVector2_MultiplyWithReal(neg_dV, (1 + contact->resist)), 
-        contact->normal)/contact->kfactor;
+    moment_len = PyVector2_Dot (PyVector2_MultiplyWithReal(neg_dV,
+            (1 + contact->resist)), contact->normal)/contact->kfactor;
     moment_len = MAX(0, moment_len);
     
-    //finally we get the momentum(oh...)
+    /* finally we get the momentum(oh...) */
     moment = PyVector2_MultiplyWithReal(contact->normal, moment_len);
     contact->acc_moment.real += moment.real/contact->weight;
     contact->acc_moment.imag += moment.imag/contact->weight; 
 
-    //split impulse
+    /* split impulse */
     vbias = BIAS_FACTOR*MAX(0, contact->depth - MAX_C_DEP)/steptime;
-    //biased dv
-    bincidV = c_sum(incidBody->bias_lv, PyVector2_fCross(incidBody->bias_w, incidR));
+    /* biased dv */
+    bincidV = c_sum(incidBody->bias_lv,
+        PyVector2_fCross(incidBody->bias_w, incidR));
     brefV = c_sum(refBody->bias_lv, PyVector2_fCross(refBody->bias_w, refR));
     bneg_dV = c_diff(brefV, bincidV); 
-    //biased moment
+    /* biased moment */
     bm_len = PyVector2_Dot(PyVector2_MultiplyWithReal(bneg_dV, 1.),
         contact->normal)/contact->kfactor;
     bm_len = MAX(0, bm_len + vbias/contact->kfactor);

src/physics/joint.c

 int
 PyJoint_SolveConstraints (PyObject *joint, double steptime)
 {
-    if (!PyJoint_Check (joint))
+    if (!joint || !PyJoint_Check (joint))
     {
         PyErr_SetString (PyExc_TypeError, "joint must be a Joint");
         return 0;

src/physics/physicsmod.c

     Py_INCREF (&PyShape_Type);
     Py_INCREF (&PyRectShape_Type);
 
-
 #if PY_VERSION_HEX < 0x03000000
     mod = Py_InitModule3 ("physics", NULL, NULL);
 #else
     aabbox_export_capi (c_api);
     body_export_capi (c_api);
     shape_export_capi (c_api);
+    rectshape_export_capi (c_api);
     joint_export_capi (c_api);
     contact_export_capi (c_api);
     world_export_capi (c_api);

src/physics/rectshape.c

     PyBody_GetGlobalPos (body, tr, gp[2]);
     PyBody_GetGlobalPos (body, tl, gp[3]);
 
+    AABBox_Reset (&(r->box));
     AABBox_ExpandTo (&(r->box), &(gp[0]));
     AABBox_ExpandTo (&(r->box), &(gp[1]));
     AABBox_ExpandTo (&(r->box), &(gp[2]));
 PyRectShape_New (AABBox box)
 {
     /* TODO: is anything correctly initialised? */
-    PyRectShape *shape = (PyRectShape*)PyRectShape_Type.tp_new (&PyRectShape_Type, NULL, NULL);
+    PyRectShape *shape = (PyRectShape*)PyRectShape_Type.tp_new
+        (&PyRectShape_Type, NULL, NULL);
     if (!shape)
         return NULL;
 

src/physics/shape.c

 PyShape_Collide (PyObject *shape1, PyVector2 pos1, double rot1,
     PyObject *shape2, PyVector2 pos2, double rot2, int *refid)
 {
-    if (!PyShape_Check (shape1) || !PyShape_Check (shape2))
+    if (!shape1 || !shape2 || !PyShape_Check (shape1) ||
+        !PyShape_Check (shape2))
     {
         PyErr_SetString (PyExc_TypeError,
             "shape arguments must be Shape objects");
 int
 PyShape_Update (PyObject *shape, PyObject *body)
 {
-    if (!PyShape_Check (shape))
+    if (!shape || !PyShape_Check (shape))
     {
         PyErr_SetString (PyExc_TypeError, "shape must be a Shape");
         return 0;
     }
-    if (!PyBody_Check (body))
+    if (!body || !PyBody_Check (body))
     {
         PyErr_SetString (PyExc_TypeError, "body must be a Body");
         return 0;
 AABBox*
 PyShape_GetAABBox (PyObject *shape)
 {
-    if (!PyShape_Check (shape))
+    if (!shape || !PyShape_Check (shape))
     {
         PyErr_SetString (PyExc_TypeError, "shape must be a Shape");
         return NULL;
         PyErr_SetString (PyExc_RuntimeError, "count argument missing");
         return NULL;
     }
-    if (!PyShape_Check (shape))
+    if (!shape || !PyShape_Check (shape))
     {
         PyErr_SetString (PyExc_TypeError, "shape must be a Shape");
         return NULL;

src/physics/world.c

             refbody->bias_w = 0.f;
         }
 
-        /* Clear impulse */
+        /* clear impulse */
         for (i = 0; i < contact_cnt; ++i)
         {
             contact = PyList_GET_ITEM (world->contactlist, i);
 int
 PyEvent_SDLEventFromEvent (PyObject *ev, SDL_Event *event)
 {
-    if (!PyEvent_Check (ev))
+    if (!event)
+        return NULL;
+
+    if (!ev || !PyEvent_Check (ev))
     {
         PyErr_SetString (PyExc_TypeError, "event must be an Event");
         return 0;

src/sdl/overlay.c

     SDL_Surface *sdlsurface;
     SDL_Overlay *sdloverlay;
 
-    if (!PySurface_Check (surface))
+    if (!surface || !PySurface_Check (surface))
     {
         PyErr_SetString (PyExc_TypeError, "surface must be a Surface");
         return NULL;
     PyOverlay *ov = (PyOverlay*)overlay;
     PyObject *wkref;
 
-    if (!PyOverlay_Check (overlay))
+    if (!overlay || !PyOverlay_Check (overlay))
     {
         PyErr_SetString (PyExc_TypeError, "overlay must be an Overlay");
         return 0;
     Py_ssize_t size;
     int found = 0, noerror = 1;
 
-    if (!PyOverlay_Check (overlay))
+    if (!lock)
+    {
+        PyErr_SetString (PyExc_TypeError, "lock must not be NULL");
+        return 0;
+    }
+
+    if (!overlay || !PyOverlay_Check (overlay))
     {
         PyErr_SetString (PyExc_TypeError, "overlay must be an Overlay");
         return 0;

src/sdl/surface.c

     Py_ssize_t size;
     int found = 0, noerror = 1;
 
+    if (!lock)
+    {
+        PyErr_SetString (PyExc_TypeError, "lock must not be NULL");
+        return 0;
+    }
+
     if (!PySurface_Check (surface))
     {
         PyErr_SetString (PyExc_TypeError, "surface must be a Surface");
     PyObject *cobj;
     SurfaceLock *c_lock;
 
-    if (!PySurface_Check (surface))
+    if (!lock)
+    {
+        PyErr_SetString (PyExc_TypeError, "lock must not be NULL");
+        return 0;
+    }
+
+    if (!surface || !PySurface_Check (surface))
     {
         PyErr_SetString (PyExc_TypeError, "surface must be a Surface");
         return 0;
     PyObject *surfobj;
     SDL_Surface *surface, *newsurface;
 
-    if (!PySurface_Check (source))
+    if (!source || !PySurface_Check (source))
     {
         PyErr_SetString (PyExc_TypeError, "source must be a Surface");
         return NULL;

src/sdl/videomod.c

 {
     Uint8 rgba[4];
 
-    if (!value)
+    if (!value || !format || !color)
         return 0;
 
     if (PyInt_Check (value))

src/sdlext/pixelarray.c

 {
     SDL_Surface *surface;
 
-    if (!PySurface_Check (surfobj))
+    if (!surfobj || !PySurface_Check (surfobj))
     {
         PyErr_SetString (PyExc_TypeError, "argument must be a Surface");
         return NULL;

src/sdlmixer/chunk.c

 
     ASSERT_MIXER_OPEN(NULL);
     
+    if (!filename)
+        return NULL;
+
     chunk = (PyChunk*) PyChunk_Type.tp_new (&PyChunk_Type, NULL, NULL);
     if (!chunk)
         return NULL;
 
     ASSERT_MIXER_OPEN(NULL);
 
+    if (!sample)
+        return NULL;
+
     chunk = (PyChunk*) PyChunk_Type.tp_new (&PyChunk_Type, NULL, NULL);
     if (!chunk)
         return NULL;

src/sdlmixer/music.c

     Mix_Music *sample;
 
     ASSERT_MIXER_OPEN(NULL);
+
+    if (!filename)
+        return NULL;
     
     music = (PyMusic*) PyMusic_Type.tp_new (&PyMusic_Type, NULL, NULL);
     if (!music)

src/sdlttf/font.c

     TTF_Font *ttf;
 
     ASSERT_TTF_INIT (NULL);
-    
+
+    if (!file)
+        return NULL;
+
     font = (PyFont*) PyFont_Type.tp_new (&PyFont_Type, NULL, NULL);
     if (!font)
         return NULL;

test/c_api/Makefile

+SOURCES = base_tests.c
+OBJECTS = $(SOURCES:%.c=%.o)
+TARGETS = base_tests
+
+CC ?= gcc
+CFLAGS = -W -Wall -g 
+
+# Windows includes (MinGW)
+#INCLUDES = -DWIN32 -I. -Ic:\\Python25\\include
+#LIBS = -Lc:\\Python25\\libs -mwindows -lm -lpython25 -lopengl32 -lglu32 -lglut32win 
+
+# Linux/Unix includes
+INCLUDES = -I. -I/usr/local/include/ -I/usr/local/include/python2.5
+LIBS = -L/usr/local/lib -lpython2.5 -lm
+
+CFLAGS += $(INCLUDES)
+LDFLAGS += $(LIBS)
+
+all: $(OBJECTS) $(TARGETS)
+
+base_tests.o: base_tests.c
+	$(CC) $(CFLAGS) -c -o $@ $*.c
+
+base_tests: base_tests.o
+	$(CC) base_tests.o -o base_tests $(LDFLAGS) 
+
+clean:
+	rm -f *.o *.core *~ $(TARGETS)

test/c_api/base_tests.c

+#include <stdio.h>
+#include <stdlib.h>
+#include <pygame2/pgbase.h>
+
+#define ERROR(x)                                \
+    {                                           \
+        fprintf(stderr, "*** %s\n", x);         \
+        PyErr_Print ();                         \
+        Py_Finalize ();                         \
+        exit(1);                                \
+    }
+
+static void
+test_helpers (void)
+{
+    PyObject *val, *seq, *string, *tmp;
+    pgint32 sw, sh;
+    double d, e;
+    int i, j;
+    unsigned int u;
+    char *str;
+
+    val = PyFloat_FromDouble (55.33f);
+    if (!DoubleFromObj(val, &d))
+        ERROR ("Mismatch in DoubleFromObj");
+    if (d != 55.33f)
+        ERROR ("Mismatch in DoubleFromObj result");
+    Py_DECREF (val);
+    
+    val = PyLong_FromLong (-10);
+    if (!IntFromObj(val, &i))
+        ERROR ("Mismatch in IntFromObj");
+    if (i != -10)
+        ERROR ("Mismatch in IntFromObj result");
+    Py_DECREF (val);
+
+    val = PyLong_FromLong (10);
+    if (!UintFromObj(val, &u))
+        ERROR ("Mismatch in UintFromObj");
+    if (u != 10)
+        ERROR ("Mismatch in UintFromObj result");
+    Py_DECREF (val);
+
+    seq = PyTuple_New (2);
+    PyTuple_SET_ITEM (seq, 0, PyLong_FromLong (2));
+    PyTuple_SET_ITEM (seq, 1, PyLong_FromLong (4));
+
+    if (!DoubleFromSeqIndex (seq, 0, &d))
+        ERROR ("Mismatch in DoubleFromSeqIndex (0)");
+    if (d != 2.f)
+        ERROR ("Mismatch in DoubleFromSeqIndex result 0");
+    if (!DoubleFromSeqIndex (seq, 1, &d))
+        ERROR ("Mismatch in DoubleFromSeqIndex (1)");
+    if (d != 4.f)
+        ERROR ("Mismatch in DoubleFromSeqIndex result 1");
+
+    if (!IntFromSeqIndex (seq, 0, &i))
+        ERROR ("Mismatch in IntFromSeqIndex (0)");
+    if (i != 2)
+        ERROR ("Mismatch in IntFromSeqIndex result 0");
+    if (!IntFromSeqIndex (seq, 1, &i))
+        ERROR ("Mismatch in IntFromSeqIndex (1)");
+    if (i != 4)
+        ERROR ("Mismatch in IntFromSeqIndex result 1");
+
+    if (!UintFromSeqIndex (seq, 0, &u))
+        ERROR ("Mismatch in UintFromSeqIndex (0)");
+    if (u != 2)
+        ERROR ("Mismatch in UintFromSeqIndex result 0");
+    if (!UintFromSeqIndex (seq, 1, &u))
+        ERROR ("Mismatch in UintFromSeqIndex (1)");
+    if (u != 4)
+        ERROR ("Mismatch in UintFromSeqIndex result 1");
+
+    if (!PointFromObject (seq, &i, &j))
+        ERROR ("Mismatch in PointFromObject");
+    if (i != 2 || j != 4)
+        ERROR ("Mismatch in PointFromObject result");
+
+    if (!SizeFromObject (seq, &sw, &sh))
+        ERROR ("Mismatch in SizeFromObject");
+    if (sw != 2 || sh != 4)
+        ERROR ("Mismatch in SizeFromObject result");
+
+    if (!FPointFromObject (seq, &d, &e))
+        ERROR ("Mismatch in FPointFromObject");
+    if (d != 2.f || e != 4.f)
+        ERROR ("Mismatch in FPointFromObject result");
+
+    if (!FSizeFromObject (seq, &d, &e))
+        ERROR ("Mismatch in FSizeFromObject");
+    if (d != 2.f || e != 4.f)
+        ERROR ("Mismatch in FSizeFromObject result");
+    Py_DECREF (seq);
+
+    string = PyString_FromString ("Hello World!");
+    if (!ASCIIFromObject (string, &str, &tmp))
+        ERROR ("Mismatch in ASCIIFromObject");
+    if (strcmp (str, "Hello World!") != 0)
+        ERROR ("Mismatch in ASCIIFromObject result");
+    Py_XDECREF (tmp);
+
+    if (!UTF8FromObject (string, &str, &tmp))
+        ERROR ("Mismatch in UTF8FromObject");
+    if (strcmp (str, "Hello World!") != 0)
+        ERROR ("Mismatch in UTF8FromObject result");
+    Py_XDECREF (tmp);
+}
+
+static void
+test_colors (void)
+{
+    PyObject *color;
+    pgbyte rgba[4] = { 255, 155, 55, 5 };
+    pguint32 rgba_int = 0x05ff9b37;
+    pguint32 tmp;
+
+    color = PyColor_New (rgba);
+    if (!PyColor_Check (color))
+        ERROR ("Color mismatch in PyColor_Check");
+
+    if (((PyColor*)color)->r != 255 ||
+        ((PyColor*)color)->g != 155 ||
+        ((PyColor*)color)->b != 55 ||
+        ((PyColor*)color)->a != 5)
+        ERROR ("Color mismatch in PyColor_New");
+
+    tmp = PyColor_AsNumber (color);
+    if (tmp != rgba_int)
+        ERROR("Color mismatch in PyColor_AsNumber");
+    Py_DECREF (color);
+
+    rgba_int = 0xFF00FF00;
+    color = PyColor_NewFromNumber (rgba_int);
+    tmp = PyColor_AsNumber (color);
+    if (tmp != rgba_int)
+        ERROR("Color mismatch in PyColor_NewFromNumber");
+    Py_DECREF (color);
+}
+
+static void
+test_rect (void)
+{
+    PyObject *rect;
+    double dx, dy, dw, dh;
+    pgint32 x, y;
+    pgint32 w, h;
+
+    rect = PyRect_New (1, 2, 3, 4);
+    if (!PyRect_Check (rect))
+        ERROR ("Rect mismatch in PyRect_Check");
+
+    if (((PyRect*)rect)->x != 1 ||
+        ((PyRect*)rect)->y != 2 ||
+        ((PyRect*)rect)->w != 3 ||
+        ((PyRect*)rect)->h != 4)
+        ERROR ("Rect mismatch in PyRect_New");
+
+    if (!SizeFromObject (rect, &w, &h))
+        ERROR ("Mismatch in SizeFromObject for PyRect");
+    if (w != 3 || h != 4)
+        ERROR ("Mismatch in SizeFromObject result for PyRect");
+
+    if (!PointFromObject (rect, (int*)&x, (int*)&y))
+        ERROR ("Mismatch in PointFromObject for PyRect");
+    if (x != 1 || y != 2)
+        ERROR ("Mismatch in PointFromObject result for PyRect");
+
+    if (!FSizeFromObject (rect, &dw, &dh))
+        ERROR ("Mismatch in FSizeFromObject for PyRect");
+    if (dw != 3 || dh != 4)
+        ERROR ("Mismatch in FSizeFromObject result for PyRect");
+
+    if (!FPointFromObject (rect, &dx, &dy))
+        ERROR ("Mismatch in FPointFromObject for PyRect");
+    if (dx != 1 || dy != 2)
+        ERROR ("Mismatch in FPointFromObject result for PyRect");
+    
+    Py_DECREF (rect);
+}
+int
+main (int argc, char *argv[])
+{
+    Py_Initialize ();
+    if (import_pygame2_base () == -1)
+        ERROR("Could not import pygame2.base");
+    
+    test_helpers ();
+    test_colors ();
+    test_rect ();
+    Py_Finalize ();
+    return 0;
+}