

from Ft.Ods import StorageManager
from Ft.Ods.StorageManager import Adapters
from Ft.Ods.StorageManager.Adapters import Constants

import os, string, time
DBNAME=os.environ.get("ODS_TEST_DB","ods:test")

class DummyFactory:
    def _4ods_endTransaction(self,*args):
        pass


class DummyEnum:
    def __init__(self,v,n):
        self._v = v
        self._n = n

class DummyBlobOwner:
    def __init__(self):
        pass

    def _4ods_setBlobId(self,name,bid):
        self.bid = bid

    def _pseudo_del(self):pass

class DummyPO:
    def __init__(self,pt,rid=0):
        self.meta_kind = DummyEnum(14,'pt_short')

        self.rid = rid

    def _4ods_setRepositoryId(self,rid):
        self.rid = rid
    def _4ods_getId(self):
        return self.rid

    def _4ods_getFullTuple(self):
        return [(self.rid,)] + self.values
    def _pseudo_del(self):pass

    def _4ods_getOdsType(self):
        return Constants.Types.ROBJECT


    _extents = ('extent',)

    _tupleTypes = ((Constants.Types.ROBJECT,),
                   (Constants.Types.ENUMERATION,),
                   (Constants.Types.STRING,),
                   (Constants.Types.STRING,),
                   (Constants.Types.SET_COLLECTION,),
                   (Constants.Types.SET_COLLECTION,),
                   (Constants.Types.SET_COLLECTION,),
                   (Constants.Types.SET_COLLECTION,),
                   (Constants.Types.SET_COLLECTION,),
                   (Constants.Types.SET_COLLECTION,),
                   (Constants.Types.SET_COLLECTION,),
                   (Constants.Types.SET_COLLECTION,),
                   (Constants.Types.SET_COLLECTION,),
                   (Constants.Types.ENUMERATION,),
                   )

    _tupleNames = (('_repoId',), ('meta_kind',), ('name',), ('comment',), ('definedIn',), ('collections',), ('dictionaries',), ('specifiers',), ('unions',), ('operations',), ('properties',), ('constants',), ('type_defs',), ('primitive_kind',))

    values = [(14,),("Test Type",),("Comment",),(0,),(0,),(0,),(0,),(0,),(0,),(0,),(0,),(0,),(3,)]


class DummyCollection:

    def __init__(self,collectionType,subType,cid = 0,changes = []):
        self._collectionType = collectionType
        self.subType = subType

        self.cid = cid
        self.changes = changes

    def _4ods_getSubType(self):
        return self.subType

    def _4ods_getSubRepositoryId(self):
        return -1

    def _4ods_setCid(self,cid):
        self.cid = cid


    def _4ods_getChanges(self):
        return self.changes

    def _4ods_getId(self):
        return self.cid

    def _4ods_isModified(self):
        return len(self.changes)
    def _pseudo_del(self):pass

    def _4ods_getOdsType(self):
        return Constants.Types.LIST_COLLECTION

    _extents = ()

class DummyDictionary:

    def __init__(self,keyType,subType,did = 0,changes = []):
        self.keyType = keyType
        self.subType = subType
        self.did = did
        self.changes = changes

    def _4ods_getSubType(self):
        return self.subType

    def _4ods_getKeyType(self):
        return self.keyType

    def _4ods_getKeyRepositoryId(self):
        return -1
    def _4ods_getSubRepositoryId(self):
        return -1


    def _4ods_setDid(self,did):
        self.did = did

    def _4ods_getChanges(self):
        return self.changes

    def _4ods_getId(self):
        return self.did

    def _4ods_isModified(self):
        return len(self.changes)
    def _pseudo_del(self):pass

    def _4ods_getOdsType(self):
        return Constants.Types.DICTIONARY_COLLECTION
        
    _extents = ()


class DummyLiteral:
    def __init__(self,db,data):
        pass


def test_repo(tester):

    tester.startGroup("Storage Manager Repos %s Driver" % tester.test_data['driver'])

    tester.startTest("Init DB")
    mang = Adapters.GetManager()
    adapter = Adapters.GetAdapter()

    if mang.exists(DBNAME):
        mang.reinit(DBNAME,adapter)
    else:
        mang.create(DBNAME)
        mang.init(DBNAME)


    #Force an extent in there
    db = mang.connect(DBNAME) 
    adapter.begin(db)
    try:
        adapter.addExtent(db,'extent',Constants.Types.ROBJECT)
    finally:
        adapter.commit(db)

    tester.testDone()

    f = DummyFactory()
    sm = StorageManager.StorageManager(f,DBNAME)

    tester.startTest("Test new RepoObject")
    sm.begin()
    try:
        ro = DummyPO(Constants.Types.ROBJECT)
        sm._4ods_registerNewPersistentObject(ro)
        #Get the extent
        ext = sm._4ods_lookup('extent')
        tester.testResults(1,len(ext.data),done=0,msg='ext 1')
    finally:
        sm.commit()

    tester.testDone()

    rid = ro._4ods_getId()

    tester.startTest("Get the object")
    sm = StorageManager.StorageManager(f,DBNAME)
    sm.begin()
    try:
        ro = sm._4ods_getRepositoryObject(rid)
        tester.testResults(0,ro == None,done=0,msg="get1")
    finally:
        sm.commit()
    tester.testDone()

    tester.startTest("Check Extent")
    sm = StorageManager.StorageManager(f,DBNAME)
    sm.begin()
    try:
        ext = sm._4ods_lookup('extent')
        tester.testResults(1,len(ext.data),done=0,msg='ext 1')
        tester.testDone()


        #Delete it
        tester.startTest("Delete")
        ro = DummyPO(Constants.Types.ROBJECT,rid)
        sm._4ods_deletePersistentObject(ro)
    finally:
        sm.commit()

    sm = StorageManager.StorageManager(f,DBNAME)
    sm.begin()
    try:
        try:
            sm._4ods_getRepositoryObject(rid)
        except:
            pass
        else:
            tester.error("No Exception")
        tester.testDone()

        tester.groupDone()
    finally:
        sm.abort()


def test_literal(tester):

    tester.startGroup("Storage Manager Literals %s Driver" % tester.test_data['driver'])

    tester.startTest("Init DB")
    mang = Adapters.GetManager()
    adapter = Adapters.GetAdapter()

    if mang.exists(DBNAME):
        mang.reinit(DBNAME,adapter)
    else:
        mang.create(DBNAME)
        mang.init(DBNAME)


    tester.testDone()

    f = DummyFactory()
    sm = StorageManager.StorageManager(f,DBNAME)

    tester.startTest("Test new Literal")
    sm.begin()
    try:
        sm._4ods_registerNewLiteralClass(Constants.Types.ENUMERATION,100,DummyLiteral)

        l = sm._4ods_createLiteralInstance(Constants.Types.ENUMERATION,100,())
        import test_storage_manager
        tester.compare(1,isinstance(l,test_storage_manager.DummyLiteral))
    finally:
        sm.commit()
    tester.testDone()
                   
    
    tester.startTest("Test persistence")
    sm = StorageManager.StorageManager(f,DBNAME)
    sm.begin()
    try:
        l = sm._4ods_createLiteralInstance(Constants.Types.ENUMERATION,100,())
        tester.compare(1,isinstance(l,test_storage_manager.DummyLiteral))
        tester.testDone()
        tester.startTest("Test Reading from Cache")
        l = sm._4ods_createLiteralInstance(Constants.Types.ENUMERATION,100,())
        tester.compare(1,isinstance(l,test_storage_manager.DummyLiteral))
    finally:
        sm.commit()
    tester.testDone()
                   
    tester.groupDone()

    
def test_collection(tester):

    tester.startGroup("Storage Manager Collections %s Driver" % tester.test_data['driver'])

    tester.startTest("Init DB")
    mang = Adapters.GetManager()
    adapter = Adapters.GetAdapter()

    if mang.exists(DBNAME):
        mang.reinit(DBNAME,adapter)
    else:
        mang.create(DBNAME)
        mang.init(DBNAME)

    tester.testDone()


    tester.startTest("Create Collection")
    f = DummyFactory()
    sm = StorageManager.StorageManager(f,DBNAME)

    sm.begin()
    try:
        changes = [(Constants.CollectionChanges.APPEND,[(0,0),(0,1)])]
        
        col = DummyCollection(Constants.CollectionTypes.BAG,Constants.Types.BOOLEAN,changes=changes)
        
        sm._4ods_registerNewPersistentObject(col)

    finally:
        sm.commit()

    tester.testDone()

    cid = col.cid
    tester.startTest("Modify Collection")
    sm = StorageManager.StorageManager(f,DBNAME)
    sm.begin()
    try:
    
        changes = [(Constants.CollectionChanges.INSERT,[(0,0)])]
        col = DummyCollection(Constants.CollectionTypes.BAG,Constants.Types.BOOLEAN,cid=cid,changes=changes)
        sm._4ods_registerModifiedPersistentObject(col)

    finally:
        sm.commit()

    tester.testDone()
    tester.startTest("Delete Collection")

    sm = StorageManager.StorageManager(f,DBNAME)
    sm.begin()
    try:
        col = DummyCollection(Constants.CollectionTypes.BAG,Constants.Types.BOOLEAN,cid=cid)
        sm._4ods_deletePersistentObject(col)
    finally:
        sm.commit()

    

    tester.testDone()
    tester.groupDone()


def test_blobs(tester):

    tester.startGroup('Storage Manager Blobs %s Driver' % tester.test_data['driver'])
    tester.startTest("Init DB")
    mang = Adapters.GetManager()
    adapter = Adapters.GetAdapter()

    if mang.exists(DBNAME):
        mang.reinit(DBNAME,adapter)
    else:
        mang.create(DBNAME)
        mang.init(DBNAME)

    tester.testDone()

    tester.startTest("Create Blob")

    f = DummyFactory()
    sm = StorageManager.StorageManager(f,DBNAME)
    sm.begin()
    try:
        inst = DummyBlobOwner()
        sm._4ods_registerNewBlob(inst,'foo',"This is a test"*1000)
    finally:
        sm.commit()
    tester.testDone()

    tester.startTest("Fetch Blob")
    bid = inst.bid

    sm = StorageManager.StorageManager(f,DBNAME)
    sm.begin()
    try:
        tester.testResults(len("This is a test"*1000),len(sm._4ods_readBlob(bid)),done=0,msg='len new blob')
        sm._4ods_registerModifiedBlob(bid,"Another Test")
    finally:
        sm.commit()
    tester.testDone()

    tester.startTest("Modify Blob")
    sm = StorageManager.StorageManager(f,DBNAME)
    sm.begin()
    try:
        tester.testResults("Another Test",sm._4ods_readBlob(bid),done=0,msg='read 1')
        sm._4ods_deleteBlob(inst,'foo',bid)
    finally:
        sm.commit()
    
    sm = StorageManager.StorageManager(f,DBNAME)
    sm.begin()
    try:
        try:
            print sm._4ods_readBlob(bid)
        except:
            pass
        else:
            tester.error("Blob not deleted")
    finally:
        sm.abort()
    tester.testDone()
    tester.groupDone()


def test_dictionary(tester):

    tester.startGroup("Storage Manager Dictionary %s Driver" % tester.test_data['driver'])

    tester.startTest("Init DB")
    mang = Adapters.GetManager()
    adapter = Adapters.GetAdapter()

    if mang.exists(DBNAME):
        mang.reinit(DBNAME,adapter)
    else:
        mang.create(DBNAME)
        mang.init(DBNAME)

    tester.testDone()


    tester.startTest("Create Dictionary")
    f = DummyFactory()
    sm = StorageManager.StorageManager(f,DBNAME)

    sm.begin()
    try:
        changes = [(Constants.DictionaryChanges.ADD,"foo",0)]

        col = DummyDictionary(Constants.Types.STRING,Constants.Types.BOOLEAN,changes=changes)
        sm._4ods_registerNewPersistentObject(col)
    finally:
        sm.commit()
    tester.testDone()

    did = col.did
    tester.startTest("Modify Dictionary")
    sm = StorageManager.StorageManager(f,DBNAME)
    sm.begin()
    try:
    
        changes = [(Constants.DictionaryChanges.ADD,'baz',0)]
        dict = DummyDictionary(Constants.Types.STRING,Constants.Types.BOOLEAN,did=did,changes=changes)
        sm._4ods_registerModifiedPersistentObject(dict)
    finally:
        sm.commit()
    tester.testDone()

    tester.startTest("Delete Dictionary")

    sm = StorageManager.StorageManager(f,DBNAME)
    sm.begin()
    try:
        dict = DummyDictionary(Constants.Types.STRING,Constants.Types.BOOLEAN,did=did)
        sm._4ods_deletePersistentObject(dict)

    finally:
        sm.commit()

    tester.testDone()
    tester.groupDone()


def Test(tester):
    test_repo(tester)
    test_literal(tester)
    test_collection(tester)
    test_blobs(tester)
    test_dictionary(tester)

