/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/
#include "e32base.h"
#include "e32debug.h"

#ifndef ALFMODULETEST_H
#define ALFMODULETEST_H

// Define this to build module testing enchanced version of ALF
//#define USE_MODULE_TEST_HOOKS_FOR_ALF 

#if !defined(USE_MODULE_TEST_HOOKS_FOR_ALF) || !defined(AMT_CONTROL)

#define AMT_DATA()
#define AMT_FUNC(func)                                
#define AMT_FUNC_EXC(func)
#define AMT_FUNC_EXC_RET(ret, func)
#define AMT_FUNC_EXC_IF(cond, func)
#define AMT_FUNC_EXC_IF_RET(cond, ret, func)
#define AMT_INC_COUNTER(member)
#define AMT_DEC_COUNTER(member)
#define AMT_SET_VALUE(member, val)
#define AMT_GET_VALUE(x, member)
#define AMT_INC_COUNTER_IF(cond, member)
#define AMT_DEC_COUNTER_IF(cond, member)
#define AMT_SET_VALUE_IF(cond, member, val)
#define AMT_GET_VALUE_IF(cond, x, member)

#define AMT_MAP_APPEND(memberMap, key, type, defaultValue)          
#define AMT_MAP_SET_VALUE_IF(cond, memberMap, key, value, type)     
#define AMT_MAP_INC_VALUE_IF(cond, memberMap, key, type)            
#define AMT_MAP_DEC_VALUE_IF(cond, memberMap, key, type)            
#define AMT_MAP_SET_VALUE(memberMap, key, value, type)              
#define AMT_MAP_INC_VALUE(memberMap, key, type)                              
#define AMT_MAP_DEC_VALUE(memberMap, key, type)                     
#define AMT_MAP_RESET(memberMap)                                    

#define AMT_PRINT_STATE()

#ifndef AMT_CONTROL
#error "Error: you need to define AMT_CONTROL macro in your code to be able to use ALF module test system!"
// The user have to define AMT_CONTROL, e.g. like this:
// #define AMT_CONTROL() static_cast<CAlfModuleTestDataControl*>(Dll::Tls())
// or
// #define AMT_CONTROL() iMyModuleTestDataControl
// etc.
#endif

#else


//  *** Use these macros to access global memory chunk


// Note: If you read/write a large block of data members, it is advisable not use the AMT_FUNC_EXC() based macros below. 
//       Use Lock() and Unlock() around the block explicitely, and use AMT_FUNC() macro.
//       That is to avoid unnecessary nested lock-unlock sequences (even if nested locks are working ok).

// Note: Be careful not to lock the the mutex for a long time as it will halt other processes if they are using the lock during that time!

// Generic macros
#define AMT_DATA()                  AMT_CONTROL()->iModuleTestData
#define AMT_FUNC(func)              if (AMT_DATA()->iIsEnabled) {func;}                                         
#define AMT_FUNC_EXC(func)          {AMT_CONTROL()->Lock(); if (AMT_DATA()->iIsEnabled) {func;} AMT_CONTROL()->Unlock();}
#define AMT_FUNC_EXC_RET(ret, func) {AMT_CONTROL()->Lock(); if (AMT_DATA()->iIsEnabled) {ret = func;} AMT_CONTROL()->Unlock();}
#define AMT_FUNC_EXC_IF(cond, func) {AMT_CONTROL()->Lock(); if (AMT_DATA()->iIsEnabled && (cond)) {func;} AMT_CONTROL()->Unlock();}        
#define AMT_FUNC_EXC_IF_RET(cond, ret, func) {AMT_CONTROL()->Lock(); if (AMT_DATA()->iIsEnabled && (cond)) {ret = func;} AMT_CONTROL()->Unlock();}

// Single operation macros, that will do lock/unlock.
#define AMT_INC_COUNTER(member)     AMT_FUNC_EXC(AMT_DATA()->member++)
#define AMT_DEC_COUNTER(member)     AMT_FUNC_EXC(AMT_DATA()->member--)
#define AMT_SET_VALUE(member, val)  AMT_FUNC_EXC(AMT_DATA()->member=(val))
#define AMT_GET_VALUE(x, member)    AMT_FUNC_EXC((x) = AMT_DATA()->member)
#define AMT_PRINT_STATE()           AMT_FUNC_EXC(AMT_DATA()->PrintState())

// Conditional single operation macros, that will do lock/unlock.
#define AMT_INC_COUNTER_IF(cond, member)    AMT_FUNC_EXC_IF((cond), AMT_DATA()->member++)
#define AMT_DEC_COUNTER_IF(cond, member)    AMT_FUNC_EXC_IF((cond), AMT_DATA()->member--)
#define AMT_SET_VALUE_IF(cond, member, val) AMT_FUNC_EXC_IF((cond), AMT_DATA()->member=(val))
#define AMT_GET_VALUE_IF(cond, x, member)   AMT_FUNC_EXC_IF((cond), (x) = AMT_DATA()->member)

// Map operation macros, that will do lock/unlock
#define AMT_MAP_APPEND(memberMap, key, type, defaultValue)          AMT_FUNC_EXC(AMT_DATA()->memberMap.Append(key, type, defaultValue))
#define AMT_MAP_SET_VALUE_IF(cond, memberMap, key, value, type)     AMT_FUNC_EXC_IF((cond), AMT_DATA()->memberMap.SetValue(key, value, type))
#define AMT_MAP_INC_VALUE_IF(cond, memberMap, key, type)            AMT_FUNC_EXC_IF((cond && AMT_DATA()->memberMap.Find(key, type)), AMT_DATA()->memberMap.SetValue(key, AMT_DATA()->memberMap.Find(key, type)->Value() + 1, type))
#define AMT_MAP_DEC_VALUE_IF(cond, memberMap, key, type)            AMT_FUNC_EXC_IF((cond && AMT_DATA()->memberMap.Find(key, type)), AMT_DATA()->memberMap.SetValue(key, AMT_DATA()->memberMap.Find(key, type)->Value() - 1, type))
#define AMT_MAP_SET_VALUE(memberMap, key, value, type)              AMT_FUNC_EXC_IF(ETrue, AMT_DATA()->memberMap.SetValue(key, value, type))
#define AMT_MAP_INC_VALUE(memberMap, key, type)                     AMT_MAP_INC_VALUE_IF(ETrue, memberMap, key, type)              
#define AMT_MAP_DEC_VALUE(memberMap, key, type)                     AMT_MAP_DEC_VALUE_IF(ETrue, memberMap, key, type)
#define AMT_MAP_RESET(memberMap)                                    AMT_FUNC_EXC(AMT_DATA()->memberMap.Reset())

// *** Global object names
_LIT(KAlfModuleTestChunkName, "ALF_MODULE_TEST_CHUNK");
_LIT(KAlfModuleTestMutexName, "ALF_MODULE_TEST_MUTEX");


/**
 * TAlfModuleTestType specifies recognized test types.
 */
enum TAlfModuleTestType
    {
    // Do not use this value when creating item.
    EAlfModuleTestTypeNone,
    
    // Render stage component specific tests
    EAlfModuleTestTypeRenderStageChangeSize,
    EAlfModuleTestTypeRenderStageChangePosition,
    EAlfModuleTestTypeRenderStageChangeFlag,
    
    // Streamer hierarchy model component specific tests
    EAlfModuleTestTypeHierarchyModelChangeSize,
    EAlfModuleTestTypeHierarchyModelChangePosition,
    EAlfModuleTestTypeHierarchyModelChangeFlag,    
    
    // Server bridge component specific tests
    EAlfModuleTestTypeBridgeChangeSize,
    EAlfModuleTestTypeBridgeChangePosition,
    EAlfModuleTestTypeBridgeChangeFlag,
    
    // Do not use this value when creating item.
    // This is just meant for Find operations when all tests are accepted.
    EAlfModuleTestTypeAll
    };


/**
 * CAlfModuleTestItem
 * 
 * Provides key-value pair that is used in TAlfModuleTestMap.
 */
template< class T >
NONSHARABLE_CLASS( TAlfModuleTestItem )
    {
    
public:

    /**
     * Constructor to initialize variables.
     * 
     * @param aKey Key that identifies the item.
     *             In test cases this could be for example handle.
     * @param aTestType Defines for what this test item is meant for.
     */
    TAlfModuleTestItem( TInt aKey, const TAlfModuleTestType& aTestType, const T& aDefaultValue ):
        iKey( aKey ),
        iTestType( aTestType ),
        iValue( aDefaultValue ),
        iValueSetCount( 0 )
        {
        }

    
    /**
     * @param aObject Value to be compared.
     * @return ETrue if given object equals the value of this item.
     *         Else EFalse.
     */
    TBool Equals( const T& aValue, const TAlfModuleTestType& aTestType ) const
        {
        // Also, check that value has been set. If it has not been set,
        // then think objects as unequals.
        return ( iValueSetCount > 0 
                 && iValue == aValue 
                 && TestTypeMatch( aTestType ) );
        }

    
    /**
     * @return TInt Key that should be set during creation of this object.
     */
    TInt Key() const
        {
        return iKey;
        }

    /**
     * @see ValueSet to check if the value has already been set.
     * 
     * @return const T& Value that corresonds the key.
     */
    const T& Value() const
        {
        return iValue;
        }
    
    
    /**
     * @param aValue Value to be set for the key
     */
    void SetValue( const T& aValue )
        {
        iValue = aValue;
        ++iValueSetCount;
        }

    
    /**
     * @return TInt Informs how many times the value has been set. 
     */
    TInt ValueSetCount() const
        {
        return iValueSetCount;
        }
    
    /**
     * @return const TAlfModuleTestType& Defines what the test is for
     */
    const TAlfModuleTestType& TestType() const
        {
        return iTestType;
        }

    
    /**
     * @param aTestType
     * @return TBool ETrue if flag matches this item. Else EFalse.
     */
    TBool TestTypeMatch( const TAlfModuleTestType& aTestType ) const
        {
        return ( EAlfModuleTestTypeAll == aTestType
                 || iTestType == aTestType );
        }

    
    /**
     * Resets the item info
     */
    void Reset()
        {
        iValueSetCount = 0;
        }

    
private: // data    
    
    TInt iKey;
    TAlfModuleTestType iTestType;    
    T iValue;
    TInt iValueSetCount;
    
    };


/**
 * Class CAlfModuleTestMap
 * 
 * Provides map functionality for the key-value-pairs.
 * In test cases, this should most likely be used so, that 
 * first test case classes create items with certain keys, for example with handle values.
 * Then, define hooks are used in the code to update values that corresond the correct handles.
 * In the end, test case classes can check that items have correct values set and if the test
 * is passed.
 */
template< class T >
NONSHARABLE_CLASS( TAlfModuleTestMap )
    {
public:

    // Maximum item count in the map
    static const TInt KMaxArrayCount = 50;

    
    /**
     * Constructor to initialize variables.
     */
    TAlfModuleTestMap():
        iCount( 0 ),
        iSetValueCallCount( 0 )
        {            
        }

    
    /**
     * @param aKey
     * @param aTestType Informs what type of test is accepted. Others are skipped.
     * @return T* Ownership is not transferred.
     *            NULL if item is not found.
     */
    TAlfModuleTestItem< T >* Find( TInt aKey, const TAlfModuleTestType& aTestType )
        {
        // Try to find the item corresponding the given key.
        for ( TInt i = 0; i < iCount; ++i )
            {
            TAlfModuleTestItem< T >& testItem( iArray[ i ] );
            if ( testItem.Key() == aKey
                 && testItem.TestTypeMatch( aTestType ) )
                {
                return &( testItem );
                }
            }
        // Item corresponding the given key was not found.
        return NULL;
        }    
    
    
    /**
     * Function to append new item into the map.
     * 
     * @param aKey
     * @param aTestType Describes for what case the appended test item is created for.
     * @return TInt System wide error code.
     */    
    TInt Append( TInt aKey, const TAlfModuleTestType& aTestType, const T& aDefaultValue )
        {
        if ( iCount == KMaxArrayCount )
            {
            // Array already full.
            return KErrOverflow;
            }
        else if ( Find( aKey, aTestType ) )
            {
            // Key has already been inserted.
            return KErrAlreadyExists;
            }
        
        // Append new key value set into the array.
        iArray[ iCount ] = TAlfModuleTestItem< T >( aKey, aTestType, aDefaultValue );
        ++iCount;
        return KErrNone;        
        }

    
    /**
     * Sets the value for the item.
     * Item itself should already exist in the array before
     * setting its value here. See, Append function.
     * 
     * @param aKey
     * @param aValue
     * @return TInt System wide error code.
     */
    TInt SetValue( TInt aKey, const T& aValue, const TAlfModuleTestType& aTestType )
        {
        // Increase counter, because this function is called.
        ++iSetValueCallCount;
        TAlfModuleTestItem< T >* item( Find( aKey, aTestType ) );        
        if ( !item )
            {
            // Item was not found from the array.        
            return KErrNotFound;
            }        
        // Item exists. So, set its values.
        item->SetValue( aValue );
        return KErrNone;
        }

    
    /**
     * Resets the map
     */
    void Reset()
        {
        // Just reset the counter.
        // We do not bother to reset map items, because when counter is reseted
        // already set items and their info is left out of the scope.
        iCount = 0;
        iSetValueCallCount = 0;
        }
    
    
    /**
     * Checks if all the values of items in the array match the given value.
     * 
     * @param aValue Reference to the value that items are compared to.
     * @param aTestType Informs the test type whose items should be compared.
     */
    TInt CountEquals( const T& aValue, const TAlfModuleTestType& aTestType ) const
        {
        TInt count( 0 );
        for ( TInt i = 0; i < iCount; ++i )
            {
            if ( iArray[ i ].Equals( aValue, aTestType ) )
                {
                // Item matches
                ++count;            
                }
            }
        return count;
        }


    /**
     * @return TInt Number of map items
     */
    TInt ItemCount() const
        {
        return iCount;
        }


    /**
     * @return const TAlfModuleTestItem< T >& Reference to the map item
     */
    const TAlfModuleTestItem< T >& Item( TInt aIndex ) const
        {
        return iArray[ aIndex ];
        }

    
    /**
     * @return TInt Number of times SetValue function has been called
     *              since last reset. This information can be used
     *              to check if hooks have been used correct times during
     *              a test case. Notice, that this informs the number of
     *              function calls, not the number of times a value has actually
     *              set for some item.
     */
    TInt SetValueCallCount() const
        {
        return iSetValueCallCount;
        }
    
    
private: // data
    
    TAlfModuleTestItem< T > iArray[ KMaxArrayCount ];
    // Informs number of array items
    TInt iCount;
    // Informs how many times SetItem has been called since last reset.
    // Notice, that this informs the number of function calls, not the number
    // of times a value has actually set for some item.
    TInt iSetValueCallCount;
    
    };

    
/*
 *  Class CAlfModuleTestData
 */

NONSHARABLE_CLASS(CAlfModuleTestData) : public CBase
    {
public:
    void PrintState()
        {
        RDebug::Print(_L("*** ALF INTERNAL STATE ***"));
        RDebug::Print(_L("iTotalLayerCount[0]=%d"), iTotalLayerCount[0]);
        RDebug::Print(_L("iTotalLayerCount[1]=%d"), iTotalLayerCount[1]);
        RDebug::Print(_L("iCloneLayerCount=%d"), iCloneLayerCount);
        RDebug::Print(_L("iRsTotalNodeCount=%d"), iRsTotalNodeCount);
        RDebug::Print(_L("iRsWindowGroupNodeCount=%d"), iRsWindowGroupNodeCount);
        RDebug::Print(_L("iRsWindowNodeCount=%d"), iRsWindowNodeCount);
        RDebug::Print(_L("iRsAnimNodeCount=%d"), iRsAnimNodeCount);
        RDebug::Print(_L("iRsWindowNodeActivatedCount=%d"), iRsWindowNodeActivatedCount);
        RDebug::Print(_L("iRsNodeExtentChangedCount=%d"), iRsNodeExtentChangedCount);
        RDebug::Print(_L("iRsLatestNodeExtentRect= x:%d, y:%d, width=%d, height=%d"), 
                         iRsLatestNodeExtentRect.iTl.iX, iRsLatestNodeExtentRect.iTl.iY, 
                         iRsLatestNodeExtentRect.Width(), iRsLatestNodeExtentRect.Height());
        RDebug::Print(_L("iRsTotalNodeFlagChangedCount=%d"), iRsTotalNodeFlagChangedCount);
        RDebug::Print(_L("iRsTotalNodeAttributeChangedCount=%d"), iRsTotalNodeAttributeChangedCount);
        RDebug::Print(_L("iTotalNodeCount=%d"), iTotalNodeCount);
        RDebug::Print(_L("iWindowGroupNodeCount=%d"), iWindowGroupNodeCount);
        RDebug::Print(_L("iWindowNodeCount=%d"), iWindowNodeCount);
        RDebug::Print(_L("iAnimNodeCount=%d"), iAnimNodeCount);
        RDebug::Print(_L("iWindowNodeActivatedCount=%d"), iWindowNodeActivatedCount);
        RDebug::Print(_L("iNodeExtentChangedCount=%d"), iNodeExtentChangedCount);
        RDebug::Print(_L("iLatestNodeExtentRect= x:%d, y:%d, width=%d, height=%d"), 
                         iLatestNodeExtentRect.iTl.iX, iLatestNodeExtentRect.iTl.iY, 
                         iLatestNodeExtentRect.Width(), iLatestNodeExtentRect.Height());
        RDebug::Print(_L("iTotalNodeFlagChangedCount=%d"), iTotalNodeFlagChangedCount);
        RDebug::Print(_L("iTotalNodeAttributeChangedCount=%d"), iTotalNodeAttributeChangedCount);        
        RDebug::Print(_L("iTotalVisualCount=%d"), iTotalVisualCount);
        RDebug::Print(_L("iVisibleVisualCount=%d"), iVisibleVisualCount);
        RDebug::Print(_L("iActiveVisualCount=%d"), iActiveVisualCount);
        RDebug::Print(_L("iPassiveVisualCount=%d"), iPassiveVisualCount);
        RDebug::Print(_L("iTextureCount=%d"), iTextureCount);
        RDebug::Print(_L("iRenderBufferCount=%d"), iRenderBufferCount);
        RDebug::Print(_L("iTotalControlGroupCount=%d"), iTotalControlGroupCount);        
        RDebug::Print(_L("iVisualSizeChangedCount=%d"), iVisualSizeChangedCount);        
        RDebug::Print(_L("iVisualPositionChangedCount=%d"), iVisualPositionChangedCount);
        RDebug::Print(_L("iLatestVisualExtentRect= x:%d, y:%d, width=%d, height=%d"), 
                         iLatestVisualExtentRect.iTl.iX, iLatestVisualExtentRect.iTl.iY, 
                         iLatestVisualExtentRect.Width(), iLatestVisualExtentRect.Height());
        RDebug::Print(_L("iTotalVisualFlagChangedCount=%d"), iTotalVisualFlagChangedCount);
        RDebug::Print(_L("iTotalVisualAttributeChangedCount=%d"), iTotalVisualAttributeChangedCount);
        RDebug::Print(_L("iSizeMap =>"));
        PrintSizeMapState( iSizeMap );
        RDebug::Print(_L("iPositionMap =>"));
        PrintPositionMapState( iPositionMap );        
        RDebug::Print(_L("*** ALF INTERNAL STATE ***"));
        }

    
    void PrintSizeMapState( TAlfModuleTestMap< TSize > aMap )
        {
        RDebug::Print(_L("*** ALF INTERNAL SIZE MAP STATE -->"));
        RDebug::Print(_L("Map item count=%d, SetValue call count=%d"), 
                         aMap.ItemCount(), aMap.SetValueCallCount());
        for ( TInt i = 0; i < aMap.ItemCount(); ++i )
            {
            const TAlfModuleTestItem< TSize >& item( aMap.Item( i ) );
            RDebug::Print(_L("Map item %d, iKey=%d, iTestType=%d, iValueSetCount=%d"),
                             i, item.Key(), item.TestType(), item.ValueSetCount());
            RDebug::Print(_L("Map item index=%d, width=%d, height=%d"),
                             i, item.Value().iWidth, item.Value().iHeight);
            }
        RDebug::Print(_L("<-- ALF INTERNAL SIZE MAP STATE ***"));
        }

    
    void PrintPositionMapState( TAlfModuleTestMap< TPoint > aMap )
        {
        RDebug::Print(_L("*** ALF INTERNAL POSITION MAP STATE -->"));
        RDebug::Print(_L("Map item count=%d, SetValue call count=%d"), 
                         aMap.ItemCount(), aMap.SetValueCallCount());
        for ( TInt i = 0; i < aMap.ItemCount(); ++i )
            {
            const TAlfModuleTestItem< TPoint >& item( aMap.Item( i ) );
            RDebug::Print(_L("Map item %d, iKey=%d, iTestType=%d, iValueSetCount=%d"),
                             i, item.Key(), item.TestType(), item.ValueSetCount());
            RDebug::Print(_L("Map item index=%d, x=%d, y=%d"),
                             i, item.Value().iX, item.Value().iY);
            }
        RDebug::Print(_L("<-- ALF INTERNAL POSITION MAP STATE ***"));
        }    

    
public:
    TBool iIsEnabled;           // *** not yet implemented. For run-time enabling/disabling of the test system.  
    
    // Alf Render Stage
    TInt iScreenCount;          // *** not yet implemented
    TInt iTotalLayerCount[10];  // For each screen
    TInt iCloneLayerCount;      // ** not yet implemented
    TInt iRsTotalNodeCount;
    TInt iRsWindowGroupNodeCount;
    TInt iRsWindowNodeCount;
    TInt iRsAnimNodeCount;
    TInt iRsWindowNodeActivatedCount;    
    TInt iRsNodeExtentChangedCount;
    TRect iRsLatestNodeExtentRect;
    TInt iRsTotalNodeFlagChangedCount;
    TInt iRsTotalNodeAttributeChangedCount;
    // These are temporary variables for Alf Render Stage thread internal use only!
    TInt iARS_Temp1;
    TInt iARS_Temp2;
    TInt iARS_Temp3;
    TInt iARS_Temp4;
   
    // Alf Streamer
    TInt iTotalNodeCount;
    TInt iWindowGroupNodeCount;
    TInt iWindowNodeCount;
    TInt iAnimNodeCount;
    TInt iWindowNodeActivatedCount;
    TInt iNodeExtentChangedCount;
    TRect iLatestNodeExtentRect;
    TInt iTotalNodeFlagChangedCount;
    TInt iTotalNodeAttributeChangedCount;
    // These are temporary variables for Alf Streamer thread internal use only!
    TInt iAST_Temp1;
    TInt iAST_Temp2;
    TInt iAST_Temp3;
    TInt iAST_Temp4;
   
    // Alf Server
    TInt iTotalVisualCount;
    TInt iVisibleVisualCount;
    TInt iActiveVisualCount;
    TInt iPassiveVisualCount;
    TInt iTextureCount;         // *** not yet implemented
    TInt iRenderBufferCount;    // *** not yet implemented
    TInt iTotalControlGroupCount;
    TInt iVisualSizeChangedCount;
    TInt iVisualPositionChangedCount;
    TRect iLatestVisualExtentRect;
    TInt iTotalVisualFlagChangedCount;
    TInt iTotalVisualAttributeChangedCount;
    TInt iOrdinalChange;
    // These are temporary variables for Alf Server thread internal use only!
    TInt iASE_Temp1;
    TInt iASE_Temp2;
    TInt iASE_Temp3;
    TInt iASE_Temp4;

    // Map that contains integer items that can be specified for certain test cases.
    TAlfModuleTestMap< TInt > iIntMap;    
    // Map that contains size items that can be specified for certain test cases.
    TAlfModuleTestMap< TSize > iSizeMap;
    // Map that contains position items that can be specified for certain test cases.
    TAlfModuleTestMap< TPoint > iPositionMap;    

    };


/*
 *  Class CAlfModuleTestDataControl
 */
NONSHARABLE_CLASS(CAlfModuleTestDataControl) : public CBase
    {
public:
    /*
     * Destructor
     */
    ~CAlfModuleTestDataControl()
        {
        iModuleTestMutex.Close();
        iModuleTestChunk.Close();
        }

    /*
     * Open global chunk and mutex created elsewhere
     */
    TInt OpenGlobalObjects()
        {
        RDebug::Print(_L("CAlfModuleTestDataControl::OpenGlobalObjects()."));
        // Open global module testing chunk
        TBool isReadOnly = EFalse;
        TInt err = iModuleTestChunk.OpenGlobal(KAlfModuleTestChunkName, isReadOnly);
        if (!err)
            {
            // Create global module testing mutex
            err = iModuleTestMutex.OpenGlobal(KAlfModuleTestMutexName);
            if (!err)
                {
                iModuleTestData = reinterpret_cast<CAlfModuleTestData*>(iModuleTestChunk.Base());
                }
            }
        RDebug::Print(_L("CAlfModuleTestDataControl::OpenGlobalObjects. ret=%d"), err);
        return err;
        }

    /*
     * Lock access to global memory
     */
    void Lock() {iModuleTestMutex.Wait();}
 
    /*
     * Unlock access to global memory
     */
    void Unlock() {iModuleTestMutex.Signal();}
    
public:
    RChunk iModuleTestChunk;
    RMutex iModuleTestMutex;
    CAlfModuleTestData* iModuleTestData; // Not owned
    };

#endif

#endif // ALFMODULETEST_H

// End of File
