testvb.py :  » Windows » pyExcelerator » pywin32-214 » com » win32com » test » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Windows » pyExcelerator 
pyExcelerator » pywin32 214 » com » win32com » test » testvb.py
# Test code for a VB Program.
#
# This requires the PythonCOM VB Test Harness.
#

import sys
import winerror
import pythoncom, win32com.client, win32com.client.dynamic, win32com.client.gencache
from win32com.server.util import NewCollection,wrap
from win32com.test import util
from pywin32_testutil import str2memory

import traceback

# for debugging
useDispatcher = None
##  import win32com.server.dispatcher
##  useDispatcher = win32com.server.dispatcher.DefaultDebugDispatcher

error = RuntimeError

# Set up a COM object that VB will do some callbacks on.  This is used
# to test byref params for gateway IDispatch.
class TestObject:
    _public_methods_ = ["CallbackVoidOneByRef","CallbackResultOneByRef", "CallbackVoidTwoByRef",
                                        "CallbackString","CallbackResultOneByRefButReturnNone",
                                        "CallbackVoidOneByRefButReturnNone",
                                        "CallbackArrayResult", "CallbackArrayResultOneArrayByRef",
                                        "CallbackArrayResultWrongSize"
                                       ]
    def CallbackVoidOneByRef(self, intVal):
        return intVal + 1
    def CallbackResultOneByRef(self, intVal):
        return intVal, intVal + 1
    def CallbackVoidTwoByRef(self, int1, int2):
        return int1+int2, int1-int2
    def CallbackString(self, strVal):
        return 0, strVal + " has visited Python"
    def CallbackArrayResult(self, arrayVal):
        ret = []
        for i in arrayVal:
            ret.append(i+1)
        # returning as a list forces it be processed as a single result
        # (rather than a tuple, where it may be interpreted as
        # multiple results for byref unpacking)
        return ret
    def CallbackArrayResultWrongSize(self, arrayVal):
        return list(arrayVal[:-1])
    def CallbackArrayResultOneArrayByRef(self, arrayVal):
        ret = []
        for i in arrayVal:
            ret.append(i+1)
        # See above for list processing.
        return list(arrayVal), ret

    def CallbackResultOneByRefButReturnNone(self, intVal):
        return
    def CallbackVoidOneByRefButReturnNone(self, intVal):
        return

def TestVB( vbtest, bUseGenerated ):
    vbtest.LongProperty = -1
    if vbtest.LongProperty != -1:
        raise error("Could not set the long property correctly.")
    vbtest.IntProperty = 10
    if vbtest.IntProperty != 10:
        raise error("Could not set the integer property correctly.")
    vbtest.VariantProperty = 10
    if vbtest.VariantProperty != 10:
        raise error("Could not set the variant integer property correctly.")
    vbtest.VariantProperty = str2memory('raw\0data')
    if vbtest.VariantProperty != str2memory('raw\0data'):
        raise error("Could not set the variant buffer property correctly.")
    vbtest.StringProperty = "Hello from Python"
    if vbtest.StringProperty != "Hello from Python":
        raise error("Could not set the string property correctly.")
    vbtest.VariantProperty = "Hello from Python"
    if vbtest.VariantProperty != "Hello from Python":
        raise error("Could not set the variant string property correctly.")
    vbtest.VariantProperty = (1.0, 2.0, 3.0)
    if vbtest.VariantProperty != (1.0, 2.0, 3.0):
        raise error("Could not set the variant property to an array of floats correctly - '%s'." % (vbtest.VariantProperty,))

    TestArrays(vbtest, bUseGenerated)
    TestStructs(vbtest)
    TestCollections(vbtest)

    assert vbtest.TakeByValObject(vbtest)==vbtest

    # Python doesnt support PUTREF properties without a typeref
    # (although we could)
    if bUseGenerated:
        ob = vbtest.TakeByRefObject(vbtest)
        assert ob[0]==vbtest and ob[1]==vbtest

        # A property that only has PUTREF defined.
        vbtest.VariantPutref = vbtest
        if vbtest.VariantPutref._oleobj_!= vbtest._oleobj_:
            raise error("Could not set the VariantPutref property correctly.")
        # Cant test further types for this VariantPutref, as only
        # COM objects can be stored ByRef.

        # A "set" type property - only works for generated.
        # VB recognizes a collection via a few "private" interfaces that we
        # could later build support in for.
#               vbtest.CollectionProperty = NewCollection((1,2,"3", "Four"))
#               if vbtest.CollectionProperty != (1,2,"3", "Four"):
#                       raise error("Could not set the Collection property correctly - got back " + str(vbtest.CollectionProperty))

        # These are sub's that have a single byref param
        # Result should be just the byref.
        if vbtest.IncrementIntegerParam(1) != 2:
            raise error("Could not pass an integer byref")

# Sigh - we cant have *both* "ommited byref" and optional args
# We really have to opt that args nominated as optional work as optional
# rather than simply all byrefs working as optional.
#               if vbtest.IncrementIntegerParam() != 1:
#                       raise error("Could not pass an omitted integer byref")

        if vbtest.IncrementVariantParam(1) != 2:
            raise error("Could not pass an int VARIANT byref:"+str(vbtest.IncrementVariantParam(1)))

        if vbtest.IncrementVariantParam(1.5) != 2.5:
            raise error("Could not pass a float VARIANT byref")

        # Can't test IncrementVariantParam with the param omitted as it
        # it not declared in the VB code as "Optional"
        callback_ob = wrap(TestObject(), useDispatcher = useDispatcher)
        vbtest.DoSomeCallbacks(callback_ob)

    ret = vbtest.PassIntByVal(1)
    if ret != 2:
        raise error("Could not increment the integer - "+str(ret))

    TestVBInterface(vbtest)
    # Python doesnt support byrefs without some sort of generated support.
    if bUseGenerated:
        # This is a VB function that takes a single byref
        # Hence 2 return values - function and byref.
        ret = vbtest.PassIntByRef(1)
        if ret != (1,2):
            raise error("Could not increment the integer - "+str(ret))
        # Check you can leave a byref arg blank.
# see above
#               ret = vbtest.PassIntByRef()
#               if ret != (0,1):
#                       raise error("Could not increment the integer with default arg- "+str(ret))

def _DoTestCollection(vbtest, col_name, expected):
    # It sucks that some objects allow "Count()", but others "Count"
    def _getcount(ob):
        r = getattr(ob, "Count")
        if type(r)!=type(0):
            return r()
        return r
    c = getattr(vbtest, col_name)
    check = []
    for item in c:
        check.append(item)
    if check != list(expected):
        raise error("Collection %s didn't have %r (had %r)" % (col_name, expected, check))
    # Just looping over the collection again works (ie, is restartable)
    check = []
    for item in c:
        check.append(item)
    if check != list(expected):
        raise error("Collection 2nd time around %s didn't have %r (had %r)" % (col_name, expected, check))
    # Check we can get it via iter()
    i = iter(getattr(vbtest, col_name))
    check = []
    for item in i:
        check.append(item)
    if check != list(expected):
        raise error("Collection iterator %s didn't have %r 2nd time around (had %r)" % (col_name, expected, check))
    # but an iterator is not restartable
    check = []
    for item in i:
        check.append(item)
    if check != []:
        raise error("2nd time around Collection iterator %s wasn't empty (had %r)" % (col_name, check))

    # Check len()==Count()
    c = getattr(vbtest, col_name)
    if len(c) != _getcount(c):
        raise error("Collection %s __len__(%r) wasn't==Count(%r)" % (col_name, len(c), _getcount(c)))
    # Check we can do it with zero based indexing.
    c = getattr(vbtest, col_name)
    check = []
    for i in range(_getcount(c)):
        check.append(c[i])
    if check != list(expected):
        raise error("Collection %s didn't have %r (had %r)" % (col_name, expected, check))

    # Check we can do it with our old "Skip/Next" methods.
    c = getattr(vbtest, col_name)._NewEnum()
    check = []
    while 1:
        n = c.Next()
        if not n:
            break
        check.append(n[0])
    if check != list(expected):
        raise error("Collection %s didn't have %r (had %r)" % (col_name, expected, check))

def TestCollections(vbtest):
    _DoTestCollection(vbtest, "CollectionProperty", [1,"Two", "3"])
    # zero based indexing works for simple VB collections.
    if vbtest.CollectionProperty[0] != 1:
        raise error("The CollectionProperty[0] element was not the default value")

    _DoTestCollection(vbtest, "EnumerableCollectionProperty", [])
    vbtest.EnumerableCollectionProperty.Add(1)
    vbtest.EnumerableCollectionProperty.Add("Two")
    vbtest.EnumerableCollectionProperty.Add("3")
    _DoTestCollection(vbtest, "EnumerableCollectionProperty", [1,"Two", "3"])

def _DoTestArray(vbtest, data, expected_exception = None):
    try:
        vbtest.ArrayProperty = data
        if expected_exception is not None:
            raise error("Expected '%s'" % expected_exception)
    except expected_exception:
        return
    got = vbtest.ArrayProperty
    if got != data:
        raise error(
              "Could not set the array data correctly - got %r, expected %r"
              % (got, data))

def TestArrays(vbtest, bUseGenerated):
    # Try and use a safe array (note that the VB code has this declared as a VARIANT
    # and I cant work out how to force it to use native arrays!
    # (NOTE Python will convert incoming arrays to tuples, so we pass a tuple, even tho
    # a list works fine - just makes it easier for us to compare the result!
    # Empty array
    _DoTestArray(vbtest, ())
    # Empty child array
    _DoTestArray(vbtest, ((), ()))
    # ints
    _DoTestArray(vbtest, tuple(range(1,100)))
    # Floats
    _DoTestArray(vbtest, (1.0, 2.0, 3.0))
    # Strings.
    _DoTestArray(vbtest, tuple("Hello from Python".split()))
    # Date and Time?
    # COM objects.
    _DoTestArray(vbtest, (vbtest, vbtest))
    # Mixed
    _DoTestArray(vbtest, (1, 2.0, "3"))
    # Array alements containing other arrays
    _DoTestArray(vbtest, (1,(vbtest, vbtest),("3","4")))
    # Multi-dimensional
    _DoTestArray(vbtest, (( (1,2,3), (4,5,6) )))
    _DoTestArray(vbtest, (( (vbtest,vbtest,vbtest), (vbtest,vbtest,vbtest) )))
    # Another dimension!
    arrayData = ( ((1,2),(3,4),(5,6)), ((7,8),(9,10),(11,12)) )
    arrayData = ( ((vbtest,vbtest),(vbtest,vbtest),(vbtest,vbtest)),
                  ((vbtest,vbtest),(vbtest,vbtest),(vbtest,vbtest)) )
    _DoTestArray(vbtest, arrayData)

    # Check that when a '__getitem__ that fails' object is the first item
    # in the structure, we don't mistake it for a sequence.
    _DoTestArray(vbtest, (vbtest, 2.0, "3"))
    _DoTestArray(vbtest, (1, 2.0, vbtest))

    # Pass arbitrarily sized arrays - these used to fail, but thanks to 
    # Stefan Schukat, they now work!
    expected_exception = None
    arrayData = ( ((1,2,1),(3,4),(5,6)), ((7,8),(9,10),(11,12)) )
    _DoTestArray(vbtest, arrayData, expected_exception)
    arrayData = ( ((vbtest,vbtest),), ((vbtest,),))
    _DoTestArray(vbtest, arrayData, expected_exception)
    # Pass bad data - last item wrong size
    arrayData = ( ((1,2),(3,4),(5,6,8)), ((7,8),(9,10),(11,12)) )
    _DoTestArray(vbtest, arrayData, expected_exception)
    
    # byref safearray results with incorrect size.
    callback_ob = wrap(TestObject(), useDispatcher = useDispatcher)
    print "** Expecting a 'ValueError' exception to be printed next:"
    try:
        vbtest.DoCallbackSafeArraySizeFail(callback_ob)
    except pythoncom.com_error, exc:
        assert exc.excepinfo[1] == "Python COM Server Internal Error", "Didnt get the correct exception - '%s'" % (exc,)
        
    if bUseGenerated:
        # This one is a bit strange!  The array param is "ByRef", as VB insists.
        # The function itself also _returns_ the arram param.
        # Therefore, Python sees _2_ result values - one for the result,
        # and one for the byref.
        testData = "Mark was here".split()
        resultData, byRefParam = vbtest.PassSAFEARRAY(testData)
        if testData != list(resultData):
            raise error("The safe array data was not what we expected - got " + str(resultData))
        if testData != list(byRefParam):
            raise error("The safe array data was not what we expected - got " + str(byRefParam))
        testData = [1.0, 2.0, 3.0]
        resultData, byRefParam = vbtest.PassSAFEARRAYVariant(testData)
        assert testData == list(byRefParam)
        assert testData == list(resultData)
        testData = ["hi", "from", "Python"]
        resultData, byRefParam = vbtest.PassSAFEARRAYVariant(testData)
        assert testData == list(byRefParam), "Expected '%s', got '%s'" % (testData, list(byRefParam))
        assert testData == list(resultData), "Expected '%s', got '%s'" % (testData, list(resultData))
        # This time, instead of an explicit str() for 1.5, we just
        # pass Unicode, so the result should compare equal
        testData = [1, 2.0, u"3"]
        resultData, byRefParam = vbtest.PassSAFEARRAYVariant(testData)
        assert testData == list(byRefParam)
        assert testData == list(resultData)
    print "Array tests passed"

def TestStructs(vbtest):
    try:
        vbtest.IntProperty = "One"
        raise error("Should have failed by now")
    except pythoncom.com_error, exc:
        if exc.hresult != winerror.DISP_E_TYPEMISMATCH:
            raise error("Expected DISP_E_TYPEMISMATCH")

    s = vbtest.StructProperty
    if s.int_val != 99 or str(s.str_val) != "hello":
        raise error("The struct value was not correct")
    s.str_val = "Hi from Python"
    s.int_val = 11
    if s.int_val != 11 or str(s.str_val) != "Hi from Python":
        raise error("The struct value didnt persist!")

    if s.sub_val.int_val != 66 or str(s.sub_val.str_val) != "sub hello":
        raise error("The sub-struct value was not correct")
    sub = s.sub_val
    sub.int_val = 22
    if sub.int_val != 22:
        print sub.int_val
        raise error("The sub-struct value didnt persist!")

    if s.sub_val.int_val != 22:
        print s.sub_val.int_val
        raise error("The sub-struct value (re-fetched) didnt persist!")

    if s.sub_val.array_val[0].int_val != 0 or str(s.sub_val.array_val[0].str_val) != "zero":
        print s.sub_val.array_val[0].int_val
        raise error("The array element wasnt correct")
    s.sub_val.array_val[0].int_val = 99
    s.sub_val.array_val[1].int_val = 66
    if s.sub_val.array_val[0].int_val != 99 or \
       s.sub_val.array_val[1].int_val != 66:
        print s.sub_val.array_val[0].int_val
        raise error("The array element didnt persist.")
    # Now pass the struct back to VB
    vbtest.StructProperty = s
    # And get it back again
    s = vbtest.StructProperty
    if s.int_val != 11 or str(s.str_val) != "Hi from Python":
        raise error("After sending to VB, the struct value didnt persist!")
    if s.sub_val.array_val[0].int_val != 99:
        raise error("After sending to VB, the struct array value didnt persist!")

    # Now do some object equality tests.
    assert s==s
    assert s!=None
    if sys.version_info > (3,0):
        try:
            s < None
            raise error("Expected type error")
        except TypeError:
            pass
        try:
            None < s
            raise error("Expected type error")
        except TypeError:
            pass
    assert s != s.sub_val
    import copy
    s2 = copy.copy(s)
    assert s is not s2
    assert s == s2
    s2.int_val = 123
    assert s != s2
    # Make sure everything works with functions
    s2 = vbtest.GetStructFunc()
    assert s==s2
    vbtest.SetStructSub(s2)

    # Create a new structure, and set its elements.
    s = win32com.client.Record("VBStruct", vbtest)
    assert s.int_val == 0, "new struct inst initialized correctly!"
    s.int_val = -1
    vbtest.SetStructSub(s)
    assert vbtest.GetStructFunc().int_val == -1, "new struct didnt make the round trip!"
    # Finally, test stand-alone structure arrays.
    s_array = vbtest.StructArrayProperty
    assert s_array is None, "Expected None from the uninitialized VB array"
    vbtest.MakeStructArrayProperty(3)
    s_array = vbtest.StructArrayProperty
    assert len(s_array)==3
    for i in range(len(s_array)):
        assert s_array[i].int_val == i
        assert s_array[i].sub_val.int_val == i
        assert s_array[i].sub_val.array_val[0].int_val == i
        assert s_array[i].sub_val.array_val[1].int_val == i+1
        assert s_array[i].sub_val.array_val[2].int_val == i+2

    # Some error type checks.
    try:
        s.bad_attribute
        raise RuntimeError("Could get a bad attribute")
    except AttributeError:
        pass
    m = s.__members__
    assert m[0]=="int_val" and m[1]=="str_val" and m[2]=="ob_val" and m[3]=="sub_val", m

    # Test attribute errors.
    try:
        s.foo
        raise RuntimeError("Expected attribute error")
    except AttributeError, exc:
        assert "foo" in str(exc), exc

    # test repr - it uses repr() of the sub-objects, so check it matches.
    expected = "com_struct(int_val=%r, str_val=%r, ob_val=%r, sub_val=%r)" % (s.int_val, s.str_val, s.ob_val, s.sub_val)
    if repr(s) != expected:
        print "Expected repr:", expected
        print "Actual repr  :", repr(s)
        raise RuntimeError("repr() of record object failed")
    
    print "Struct/Record tests passed"

def TestVBInterface(ob):
    t = ob.GetInterfaceTester(2)
    if t.getn() != 2:
        raise error("Initial value wrong")
    t.setn(3)
    if t.getn() != 3:
        raise error("New value wrong")

def TestObjectSemantics(ob):
    # a convenient place to test some of our equality semantics
    assert ob==ob._oleobj_
    assert not ob!=ob._oleobj_
    # same test again, but lhs and rhs reversed.
    assert ob._oleobj_==ob
    assert not ob._oleobj_!=ob
    # same tests but against different pointers.  COM identity rules should
    # still ensure all works
    assert ob._oleobj_==ob._oleobj_.QueryInterface(pythoncom.IID_IUnknown)
    assert not ob._oleobj_!=ob._oleobj_.QueryInterface(pythoncom.IID_IUnknown)

    assert ob._oleobj_!=None
    assert None!=ob._oleobj_
    assert ob!=None
    assert None!=ob
    if sys.version_info > (3,0):
        try:
            ob < None
            raise error("Expected type error")
        except TypeError:
            pass
        try:
            None < ob
            raise error("Expected type error")
        except TypeError:
            pass

    assert ob._oleobj_.QueryInterface(pythoncom.IID_IUnknown)==ob._oleobj_
    assert not ob._oleobj_.QueryInterface(pythoncom.IID_IUnknown)!=ob._oleobj_

    assert ob._oleobj_==ob._oleobj_.QueryInterface(pythoncom.IID_IDispatch)
    assert not ob._oleobj_!=ob._oleobj_.QueryInterface(pythoncom.IID_IDispatch)

    assert ob._oleobj_.QueryInterface(pythoncom.IID_IDispatch)==ob._oleobj_
    assert not ob._oleobj_.QueryInterface(pythoncom.IID_IDispatch)!=ob._oleobj_

    print "Object semantic tests passed"

def DoTestAll():
    o = win32com.client.Dispatch("PyCOMVBTest.Tester")
    TestObjectSemantics(o)
    TestVB(o,1)

    o = win32com.client.dynamic.DumbDispatch("PyCOMVBTest.Tester")
    TestObjectSemantics(o)
    TestVB(o,0)

def TestAll():
    # Import the type library for the test module.  Let the 'invalid clsid'
    # exception filter up, where the test runner will treat it as 'skipped'
    win32com.client.gencache.EnsureDispatch("PyCOMVBTest.Tester")

    if not __debug__:
        raise RuntimeError("This must be run in debug mode - we use assert!")
    try:
        DoTestAll()
        print "All tests appear to have worked!"
    except:
        # ?????
        print "TestAll() failed!!"
        traceback.print_exc()
        raise

# Make this test run under our test suite to leak tests etc work
def suite():
    import unittest
    test = util.CapturingFunctionTestCase(TestAll, description="VB tests")
    suite = unittest.TestSuite()
    suite.addTest(test)
    return suite

if __name__=='__main__':
    util.testmain()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.