os/persistentdata/persistentstorage/sql/TEST/testexecute/SQLite/src/sqlfn.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/persistentstorage/sql/TEST/testexecute/SQLite/src/sqlfn.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,2365 @@
     1.4 +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// It would have been nice to create a new object every time we jump to
    1.18 +// a new config block but reporting (INFO_PRINTF and ERR_PRINTF) doesn't
    1.19 +// work from sub-objects. All in all the structure isn't what I'd like,
    1.20 +// perhaps I'm missing some TEF functionality which would get around this. 
    1.21 +// Various bits of repetition may be removed into utility class(es).
    1.22 +// Some utility methods probably should go into utility class(es).
    1.23 +// Unimplemented 8-bit methods, e.g Exec8.
    1.24 +// 
    1.25 +//
    1.26 +
    1.27 +#include "sqlfn.h"
    1.28 +#include "Te_SQL_SuiteDefs.h"
    1.29 +#include "common.h"
    1.30 +
    1.31 +// Contains code to perform functions on SQLite databases - what functions
    1.32 +// and in what order is determined by the content of the config (.ini) file.
    1.33 +
    1.34 +CSQLFnStep::~CSQLFnStep()
    1.35 +/**
    1.36 + * Destructor
    1.37 + */
    1.38 +    {
    1.39 +    // Get rid of the RFs object.. Note this isn't set up in the constructor
    1.40 +    // but in doTestStepL.
    1.41 +    irfs.Close();
    1.42 +
    1.43 +    // Get rid of the semaphore objects.
    1.44 +    isemA.Close();
    1.45 +    isemB.Close();
    1.46 +
    1.47 +    // Get rid of the hashes. These are originally set up in doTestStepL.
    1.48 +    delete ierrhsh;
    1.49 +    delete icoltypehsh;
    1.50 +    delete iactionhsh;
    1.51 +    delete icaphsh;
    1.52 +    delete ipolhsh;
    1.53 +    delete iobjhsh;
    1.54 +
    1.55 +    // Get rid of the config item.
    1.56 +    if(icfg)delete icfg;
    1.57 +    }
    1.58 +CSQLFnStep::CSQLFnStep()
    1.59 +    {
    1.60 +    // Create a global semaphore to be used by all instances of this framework
    1.61 +    // to be used for synchronising separate threads when 'CONCURRENT' is
    1.62 +    // used. If it already exists, then perhaps another thread already has it
    1.63 +    // which is fine - in that case just open it.
    1.64 +    TInt err = isemA.CreateGlobal(_L("SQLiteSemA"), 0);
    1.65 +    if(err == KErrAlreadyExists)
    1.66 +    	{
    1.67 +        err = isemA.OpenGlobal(_L("SQLiteSemA"));
    1.68 +    	}
    1.69 +    if(err != KErrNone)
    1.70 +    	{
    1.71 +		INFO_PRINTF2(_L("Error %d creating semaphore"), err);
    1.72 +		__ASSERT_ALWAYS(err == KErrNone, User::Invariant());
    1.73 +    	}
    1.74 +
    1.75 +	//
    1.76 +	// Second semaphore require for DEF140385.
    1.77 +	//
    1.78 +    err = isemB.CreateGlobal(_L("SQLiteSemB"), 0);
    1.79 +    if(err == KErrAlreadyExists)
    1.80 +    	{
    1.81 +        err = isemB.OpenGlobal(_L("SQLiteSemB"));
    1.82 +    	}
    1.83 +    if(err != KErrNone)
    1.84 +    	{
    1.85 +		INFO_PRINTF2(_L("Error %d creating semaphoreB"), err);
    1.86 +		__ASSERT_ALWAYS(err == KErrNone, User::Invariant());
    1.87 +    	}
    1.88 +    }
    1.89 +TVerdict CSQLFnStep::doTestStepPostambleL()
    1.90 +    {
    1.91 +    // Try to make sure that the database and statement resources have been
    1.92 +    // properly closed (in case of problems).
    1.93 +    isqlst.Close();
    1.94 +    isqldb.Close();
    1.95 +    return TestStepResult();
    1.96 +    }
    1.97 +TVerdict CSQLFnStep::doTestStepL()
    1.98 +/**
    1.99 + * @return - TVerdict code
   1.100 + * Override of base class pure virtual. Our implementation only gets called
   1.101 + * if the base class doTestStepPreambleL() did not leave. That being the case,
   1.102 + * the current test result value will be EPass.
   1.103 + */
   1.104 +    {
   1.105 +    // Create the RFs object so we can talk to the file-system when necessary.
   1.106 +    // Moved from the constructor to shut up leavescan.
   1.107 +    User::LeaveIfError(irfs.Connect());
   1.108 +    irfs.ShareProtected();
   1.109 +
   1.110 +    // Make sure the database and statement objects get cleaned up..
   1.111 +    CleanupClosePushL(isqldb);
   1.112 +    CleanupClosePushL(isqlst);
   1.113 +
   1.114 +    // Make sure that the icfg member is definitely unset when we start.
   1.115 +    icfg = NULL;
   1.116 +
   1.117 +    // Get the hashes we use to associate words with numbers (e.g
   1.118 +    // KErrNone with 0). If these fail due to lack of memory they will
   1.119 +    // PANIC, which is fine. If we're that short of memory nothing is
   1.120 +    // going to work anyway.
   1.121 +    ierrhsh = new CSQLErrHash();
   1.122 +    icoltypehsh = new CSQLColTypeHash();
   1.123 +    iactionhsh = new CSQLTEFAction();
   1.124 +    icaphsh = new CSQLCapability();
   1.125 +    ipolhsh = new CSQLPolicy();
   1.126 +    iobjhsh = new CSQLObject();
   1.127 +     
   1.128 +    // Set the test result to PASS to start with and call the main block..
   1.129 +    SetTestStepResult(EPass);    
   1.130 +    SQLDbStepL(ConfigSection());
   1.131 +
   1.132 +    // Clean up the database and statement objects.
   1.133 +    CleanupStack::PopAndDestroy(2, &isqldb);
   1.134 +
   1.135 +    return TestStepResult();
   1.136 +    }
   1.137 +// This is our 'main' function. It works out what method (e.g RSqlStatement::
   1.138 +// Close) the user wants (based on the configuration file) and then calls
   1.139 +// the appropriate wrapper function which runs the wanted method and reports
   1.140 +// on any unexpected errors.
   1.141 +void CSQLFnStep::SQLDbStepL(const TPtrC& acfgblk)
   1.142 +    {
   1.143 +    _LIT(KTestFunction, "SQLDbStep");
   1.144 +
   1.145 +    /*
   1.146 +     * Go through all of the actions defined in the configuration file
   1.147 +     * acting on each. The counter will keep incrementing until we
   1.148 +     * fail to find a config item called 'CreateNN', or 'OpenNN' etc.
   1.149 +     * The two arrays hold Parameter and Column indices for use in
   1.150 +     * any method that needs one. E.G..
   1.151 +     */
   1.152 +    TInt ended=0;
   1.153 +
   1.154 +    iasync = i8bit = EFalse;
   1.155 +    for(TInt count=0 ; ; count++)
   1.156 +        {
   1.157 +        TPtrC argument;
   1.158 +        TInt whatfun=Efn_undefined;
   1.159 +        for(TInt i=0 ; i < Efn_undefined ; i++)
   1.160 +            {
   1.161 +            // Construct something like 'ColumnInt37'
   1.162 +            TBuf<KStatementFunMaxLength> stfn(*(iactionhsh->GetStringFromNum(i)));
   1.163 +            stfn.AppendNum(count);
   1.164 +
   1.165 +            // Does it exist in the config file? If not try e.g 'ColumnReal37'
   1.166 +            if(!GetStringFromConfig(acfgblk, stfn, argument))
   1.167 +                continue;
   1.168 +
   1.169 +            whatfun = i;
   1.170 +            if(whatfun == Ectrl_endblock)
   1.171 +                ended = 1;
   1.172 +            // The GetString was successful, so we drop out anyway.
   1.173 +            break;
   1.174 +            }
   1.175 +        // If we hit an EndBlock marker or couldn't find any keyword with
   1.176 +        // the current counter number then drop out.
   1.177 +        if((whatfun == Efn_undefined) || (whatfun == Ectrl_endblock))
   1.178 +            break;
   1.179 +
   1.180 +        // If there's a comma in the argument, split it up. We do
   1.181 +        // this here (rather than, more logically, in the called methods)
   1.182 +        // because we'd end up repeating the 'CommaSeparated' call in
   1.183 +        // all of the wrapper methods. Also, we need the indices for
   1.184 +        // Column and Parameter index resolution.
   1.185 +        TInt arg1, arg2;
   1.186 +        TPtrC arg3;
   1.187 +        CommaSeparated(argument, arg1, arg2);
   1.188 +        CommaSeparated(argument, arg1, arg3);
   1.189 +
   1.190 +        TInt err=0;
   1.191 +        switch(whatfun)
   1.192 +            {
   1.193 +                case Efn_nop: break;
   1.194 +            // First the RSqlDatabase methods...
   1.195 +                case Efn_create:
   1.196 +                        Create(argument, acfgblk, count);
   1.197 +                        break;
   1.198 +                case Efn_createl:
   1.199 +                        CreateL_(argument, acfgblk, count);
   1.200 +                        break;
   1.201 +                case Efn_createsp:
   1.202 +                        CreateSP(argument, acfgblk, count);
   1.203 +                        break;
   1.204 +                case Efn_open:
   1.205 +                        Open(argument, acfgblk, count);
   1.206 +                        break;
   1.207 +                case Efn_openl:
   1.208 +                        OpenL_(argument, acfgblk, count);
   1.209 +                        break;
   1.210 +                case Efn_attach:
   1.211 +                        Attach(argument, acfgblk, count);
   1.212 +                        break;
   1.213 +                case Efn_detach:
   1.214 +                        Detach(argument, acfgblk, count);
   1.215 +                        break;
   1.216 +                case Efn_copy:
   1.217 +                        Copy(argument, acfgblk, count);
   1.218 +                        break;
   1.219 +                case Efn_close:
   1.220 +                        Close();
   1.221 +                        break;
   1.222 +                case Efn_delete:
   1.223 +                        Delete(argument, acfgblk, count);
   1.224 +                        break;
   1.225 +                case Efn_lasterrormessage:
   1.226 +                        LastErrorMessage(argument);
   1.227 +                        break;
   1.228 +                case Efn_exec:
   1.229 +                        Exec(argument, acfgblk, count);
   1.230 +                        break;
   1.231 +                case Efn_setisolationlevel:
   1.232 +                        SetIsolationLevel(argument, acfgblk, count);
   1.233 +                        break;
   1.234 +                case Efn_reservedrivespace:
   1.235 +                        ReserveDriveSpace(arg1, acfgblk, count);
   1.236 +                        break;
   1.237 +                case Efn_freereservedspace:
   1.238 +                        FreeReservedSpace();
   1.239 +                        break;
   1.240 +                case Efn_getreserveaccess:
   1.241 +                        GetReserveAccess(acfgblk, count);
   1.242 +                        break;
   1.243 +                case Efn_releasereserveaccess:
   1.244 +                        ReleaseReserveAccess();
   1.245 +                        break;
   1.246 +
   1.247 +            // Now the RSqlStatement methods...
   1.248 +                case Erstmt_prepare:
   1.249 +                        Prepare(argument, acfgblk, count);
   1.250 +                        break;
   1.251 +                case Erstmt_preparel:
   1.252 +                        PrepareL_(argument, acfgblk, count);
   1.253 +                        break;
   1.254 +                case Erstmt_close:
   1.255 +                        Close(1);
   1.256 +                        break;
   1.257 +                case Erstmt_atrow:
   1.258 +                        AtRow(argument);
   1.259 +                        break;
   1.260 +                case Erstmt_reset:
   1.261 +                        err = isqlst.Reset();
   1.262 +                        ReportOnError(KTestFunction, _L("Reset"), acfgblk,
   1.263 +                                                                 count, err);
   1.264 +                        break;
   1.265 +                case Erstmt_exec:
   1.266 +                        {
   1.267 +                            TBuf<KConfigItemMaxNameLength> apiname(_L("st_exec"));
   1.268 +                            if(!iasync)
   1.269 +                                err = isqlst.Exec();
   1.270 +                            else
   1.271 +                                {
   1.272 +                                TChar ch = 'A';
   1.273 +                                apiname.Append(ch);
   1.274 +                                TRequestStatus trs;
   1.275 +                                isqlst.Exec(trs);
   1.276 +                                User::WaitForRequest(trs);
   1.277 +                                err = trs.Int();
   1.278 +                                }
   1.279 +                            ReportOnError(KTestFunction, apiname,
   1.280 +                                                        acfgblk, count, err);
   1.281 +                        }
   1.282 +                        break;
   1.283 +                case Erstmt_next:
   1.284 +                        Next(argument, acfgblk, count);
   1.285 +                        break;
   1.286 +                case Erstmt_paramindex:
   1.287 +                            {
   1.288 +                            TInt pidx = ParamIndex(argument, acfgblk, count);
   1.289 +                            // The test designer will have to remember how many
   1.290 +                            // param indices have been stuck in this array..
   1.291 +                            if(pidx >= 0)ipidxs.Append(pidx);
   1.292 +                            }
   1.293 +                        break;
   1.294 +                case Erstmt_colindex:
   1.295 +                            {
   1.296 +                            TInt cidx = ColumnIndex(argument, acfgblk, count);
   1.297 +                            // The test designer will have to remember how many
   1.298 +                            // column indices have been stuck in this array..
   1.299 +                            if(cidx >= 0)icidxs.Append(cidx);
   1.300 +                            }
   1.301 +                        break;
   1.302 +                case Erstmt_coltype:
   1.303 +                        // ColumnType needs the ColumnIndex (the last arg)
   1.304 +                        // and also the expected result, which it will get from
   1.305 +                        // the config file. We have to deal with the ColumnIndex
   1.306 +                        // here because it lives in our scope, not that of the
   1.307 +                        // method we're calling..
   1.308 +                        // The test designer will have to remember how many
   1.309 +                        // column indices have been stuck in this array..
   1.310 +                        ColumnType(icidxs[arg1], arg3);
   1.311 +                        break;
   1.312 +                case Erstmt_colsize:
   1.313 +                        ColumnSize(icidxs[arg1], arg2);
   1.314 +                        break;
   1.315 +                case Erstmt_bindnull:
   1.316 +                        BindNull(ipidxs[arg1], acfgblk, count);
   1.317 +                        break;
   1.318 +                case Erstmt_bindint:
   1.319 +                        BindInt(ipidxs[arg1], arg2, acfgblk, count);
   1.320 +                        break;
   1.321 +                case Erstmt_bindint64:
   1.322 +                        BindInt64(ipidxs[arg1], arg3, acfgblk, count);
   1.323 +                        break;
   1.324 +                case Erstmt_bindreal:
   1.325 +                        {
   1.326 +                        TLex tl = arg3;
   1.327 +                        TReal tr;
   1.328 +                        tl.Val(tr);
   1.329 +                        BindReal(ipidxs[arg1], tr, acfgblk, count);
   1.330 +                        }
   1.331 +                        break;
   1.332 +                case Erstmt_bindtext:
   1.333 +                        BindText(ipidxs[arg1], arg3, acfgblk, count);
   1.334 +                        break;
   1.335 +                case Erstmt_bindbigtext:
   1.336 +                        // Not an RSqlStatement method, but calls BindText
   1.337 +                        // after reading from a file.
   1.338 +                        BindBigTextL(ipidxs[arg1], arg3, acfgblk, count);
   1.339 +                        break;
   1.340 +                case Erstmt_bindbinary:
   1.341 +                        BindBinaryL(ipidxs[arg1], arg3, acfgblk, count);
   1.342 +                        break;
   1.343 +                case Erstmt_isnull:
   1.344 +                        IsNull(icidxs[arg1], arg3);
   1.345 +                        break;
   1.346 +                case Erstmt_colint:
   1.347 +                        ColumnInt(icidxs[arg1], arg2);
   1.348 +                        break;
   1.349 +                case Erstmt_colint64:
   1.350 +                        ColumnInt64(icidxs[arg1], arg3);
   1.351 +                        break;
   1.352 +                case Erstmt_colreal:
   1.353 +                        {
   1.354 +                        TLex tl = arg3;
   1.355 +                        TReal tr2;
   1.356 +                        tl.Val(tr2);
   1.357 +                        ColumnReal(icidxs[arg1], tr2);
   1.358 +                        }
   1.359 +                        break;
   1.360 +                case Erstmt_coltextL:
   1.361 +                        ColumnTextL(icidxs[arg1], arg3, acfgblk, count);
   1.362 +                        break;
   1.363 +                case Erstmt_coltextP:
   1.364 +                        ColumnTextPL(icidxs[arg1], arg3, acfgblk, count);
   1.365 +                        break;
   1.366 +                case Erstmt_coltextD:
   1.367 +                        ColumnTextDL(icidxs[arg1], arg3, acfgblk, count);
   1.368 +                        break;
   1.369 +                case Erstmt_colbinL:
   1.370 +                        ColumnBinaryL(icidxs[arg1], arg3, acfgblk, count);
   1.371 +                        break;
   1.372 +                case Erstmt_colbinP:
   1.373 +                        ColumnBinaryPL(icidxs[arg1], arg3, acfgblk, count);
   1.374 +                        break;
   1.375 +                case Erstmt_colbinD:
   1.376 +                        ColumnBinaryDL(icidxs[arg1], arg3, acfgblk, count);
   1.377 +                        break;
   1.378 +
   1.379 +                case Esp_create:
   1.380 +                        SPCreate(acfgblk, count);
   1.381 +                        break;
   1.382 +                case Esp_createl:
   1.383 +                        SPCreate(argument, acfgblk, count);
   1.384 +                        break;
   1.385 +                case Esp_close:
   1.386 +                        SPClose();
   1.387 +                        break;
   1.388 +                case Esp_setdbpolicy:
   1.389 +                        SPSetDBPolicy(argument, acfgblk, count);
   1.390 +                        break;
   1.391 +                case Esp_setpolicy:
   1.392 +                        SPSetPolicy(argument, acfgblk, count);
   1.393 +                        break;
   1.394 +                case Esp_externalizel:
   1.395 +                        SPExternalize(argument, acfgblk, count);
   1.396 +                        break;
   1.397 +                case Esp_internalizel:
   1.398 +                        SPInternalize(argument, acfgblk, count);
   1.399 +                        break;
   1.400 +
   1.401 +                case Estreamwrite_bindtext:
   1.402 +                        SWBindTextL(ipidxs[arg1], arg3, acfgblk, count);
   1.403 +                        break;
   1.404 +                case Estreamwrite_bindbinary:
   1.405 +                        SWBindBinaryL(ipidxs[arg1], arg3, acfgblk, count);
   1.406 +                        break;
   1.407 +                case Estreamread_columntext:
   1.408 +                        SRColumnTextL(icidxs[arg1], arg3, acfgblk, count);
   1.409 +                        break;
   1.410 +                case Estreamread_columnbinary:
   1.411 +                        SRColumnBinaryL(icidxs[arg1], arg3, acfgblk, count);
   1.412 +                        break;
   1.413 +                case Edefineconfig:
   1.414 +                        {
   1.415 +                        if(icfg)
   1.416 +                            delete icfg;
   1.417 +                        TInt len = argument.Length();
   1.418 +                        if(len)
   1.419 +                            {
   1.420 +                            // At the time of writing, configuration strings
   1.421 +                            // are limited to 255 bytes.
   1.422 +                            TBuf8<256> arg;
   1.423 +                            arg.Copy(argument);
   1.424 +                            icfg = new TPtrC8(arg);
   1.425 +                            }
   1.426 +                        else
   1.427 +                            icfg = NULL;
   1.428 +                        }
   1.429 +                        break;
   1.430 +
   1.431 +            // Actions that aren't direct method calls..
   1.432 +                case Ectrl_newblock:
   1.433 +                        // Continue executing from another configuration
   1.434 +                        // block. Obviously this restarts the step
   1.435 +                        // counter at zero. It's unfortunate that we can't
   1.436 +                        // create a new test object here, that would be
   1.437 +                        // so much neater. But logging doesn't work in
   1.438 +                        // sub-objects (it could be bodged around but it
   1.439 +                        // really would be a bodge). A shame, we could have
   1.440 +                        // lots of member vars holding all this junk we're
   1.441 +                        // passing around. Note that because we don't create
   1.442 +                        // a new object we are playing with the same
   1.443 +                        // RSqlDatabase and RSqlStatement objects.
   1.444 +                        SQLDbStepL(argument);
   1.445 +                        break;
   1.446 +                case Ectrl_function:
   1.447 +                        // Pure virtual. Lives elsewhere..
   1.448 +                        ResolveTestFunctionL(acfgblk, count, argument);
   1.449 +                        break;
   1.450 +
   1.451 +                case Ectrl_waitA:
   1.452 +                        // Wait for the isem member semaphore to receive
   1.453 +                        // arg1 signals for this thread. Obviously this assumes
   1.454 +                        // there's another thread that's going to execute
   1.455 +                        // a 'Signal' at some point.
   1.456 +						for(TInt ii=0 ; ii<arg1 ; ++ii)
   1.457 +                            {
   1.458 +                            WaitA();
   1.459 +                            }
   1.460 +                        break;
   1.461 +                case Ectrl_waitB:
   1.462 +                        // Wait for the isemB member semaphore to receive
   1.463 +                        // arg1 signals for this thread. Obviously this assumes
   1.464 +                        // there's another thread that's going to execute
   1.465 +                        // a 'SignalB' at some point.
   1.466 +						for(TInt ii=0 ; ii<arg1 ; ++ii)
   1.467 +                            {
   1.468 +                            WaitB();
   1.469 +                            }
   1.470 +                        break;
   1.471 +                case Ectrl_signalA:
   1.472 +                        // E.G Signal37=6 to wake up six threads that are
   1.473 +                        // waiting on isem.
   1.474 +                        SignalA(arg1);
   1.475 +                        break;
   1.476 +                case Ectrl_signalB:
   1.477 +                        // E.G SignalB37=6 to wake up six threads that are
   1.478 +                        // waiting on isemB..
   1.479 +                        SignalB(arg1);
   1.480 +                        break;
   1.481 +                case Ectrl_sleep:
   1.482 +                        INFO_PRINTF2(_L("Sleeping for %d microseconds"), arg1);
   1.483 +                        User::After(arg1);
   1.484 +                        break;
   1.485 +                case Ectrl_eightbit:
   1.486 +                        if((argument == _L("On")) || (argument == _L("True")))
   1.487 +                            i8bit = ETrue;
   1.488 +                        else
   1.489 +                            i8bit = EFalse;
   1.490 +                        break;
   1.491 +                case Ectrl_async:
   1.492 +                        if((argument == _L("On")) || (argument == _L("True")))
   1.493 +                            iasync = ETrue;
   1.494 +                        else
   1.495 +                            iasync = EFalse;
   1.496 +                        break;
   1.497 +
   1.498 +            // Big problems if this stuff executes.
   1.499 +                case Efn_undefined:
   1.500 +                        SetTestStepResult(EFail);
   1.501 +                        INFO_PRINTF1(HTML_RED);
   1.502 +                        ERR_PRINTF1(_L("This should never happen. A"));
   1.503 +                        INFO_PRINTF1(HTML_COLOUR_OFF);
   1.504 +                        break;
   1.505 +                default:
   1.506 +                        SetTestStepResult(EFail);
   1.507 +                        INFO_PRINTF1(HTML_RED);
   1.508 +                        ERR_PRINTF1(_L("This should never happen. B"));
   1.509 +                        INFO_PRINTF1(HTML_COLOUR_OFF);
   1.510 +                        break;
   1.511 +            }
   1.512 +        // Let's get rid of any colour. Can get tangled in multi-threaded
   1.513 +        // tests.
   1.514 +        INFO_PRINTF1(HTML_COLOUR_OFF);
   1.515 +        }
   1.516 +    // If we get to this point and the 'ended' flag hasn't been set then
   1.517 +    // we haven't seen an 'EndBlockNN=' line in the config file. That
   1.518 +    // usually means the test has a missing <keyword><number> item
   1.519 +    // which is a test  failure.
   1.520 +    if(!ended)
   1.521 +        {
   1.522 +        SetTestStepResult(EFail);
   1.523 +        INFO_PRINTF1(HTML_RED);
   1.524 +        ERR_PRINTF2(_L("Put an 'EndBlock' marker at the end of all config blocks. This is intended to\nspot missing numbers (which cause the test to drop out) failing to generate a failure (%S)"), &acfgblk);
   1.525 +        INFO_PRINTF1(HTML_COLOUR_OFF);
   1.526 +        }
   1.527 +    }
   1.528 +
   1.529 +// ----------Methods to exercise RSqlDatabase methods ------------------------
   1.530 +
   1.531 +TBool CSQLFnStep::Create(const TPtrC& adbnm,
   1.532 +                         const TDesC &acfgblk, TInt acnnum)
   1.533 +    {
   1.534 +    _LIT(KTestFunction, "Create");
   1.535 +    INFO_PRINTF3(_L("%S: Database name is %S "), &KTestFunction, &adbnm);
   1.536 +
   1.537 +    // Try to create the database.
   1.538 +    TInt rc = isqldb.Create(adbnm, icfg);
   1.539 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
   1.540 +    if(rc == KErrNone) return ETrue;
   1.541 +    return EFalse;
   1.542 +    }
   1.543 +TBool CSQLFnStep::CreateL_(const TPtrC& adbnm,
   1.544 +                           const TDesC &acfgblk, TInt acnnum)
   1.545 +    {
   1.546 +    _LIT(KTestFunction, "CreateL");
   1.547 +    INFO_PRINTF3(_L("%S: Database name is %S "), &KTestFunction, &adbnm);
   1.548 +
   1.549 +    // Try to create the database. Trap any leave (we're actually duplicating
   1.550 +    // what is in the non-leaving Create method, but hey, this is black box
   1.551 +    // testing, we're not supposed to know that..)
   1.552 +    TInt rc=KErrNone;
   1.553 +    TRAP(rc, isqldb.CreateL(adbnm, icfg));
   1.554 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
   1.555 +    if(rc == KErrNone) return ETrue;
   1.556 +    return EFalse;
   1.557 +    }
   1.558 +
   1.559 +TBool CSQLFnStep::CreateSP(const TPtrC& adbnm, const TDesC &acfgblk, TInt acnnum)
   1.560 +    {
   1.561 +    _LIT(KTestFunction, "CreateSP");
   1.562 +    INFO_PRINTF3(_L("%S: Database name is %S "), &KTestFunction, &adbnm);
   1.563 +
   1.564 +    TInt rc = isqldb.Create(adbnm, isqlsp, icfg);
   1.565 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
   1.566 +    if(rc == KErrNone) return ETrue;
   1.567 +    return EFalse;
   1.568 +    }
   1.569 +    
   1.570 +TBool CSQLFnStep::Open(const TPtrC& adbnm,
   1.571 +                       const TDesC &acfgblk, TInt acnnum)
   1.572 +    {
   1.573 +    _LIT(KTestFunction, "Open");
   1.574 +    INFO_PRINTF3(_L("%S: Database name is %S "), &KTestFunction, &adbnm);
   1.575 +
   1.576 +    // Try to open the database.
   1.577 +    TInt rc = isqldb.Open(adbnm, icfg);
   1.578 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
   1.579 +    if(rc == KErrNone) return ETrue;
   1.580 +    return EFalse;
   1.581 +    }
   1.582 +TBool CSQLFnStep::OpenL_(const TPtrC& adbnm,
   1.583 +                         const TDesC &acfgblk, TInt acnnum)
   1.584 +    {
   1.585 +    _LIT(KTestFunction, "OpenL");
   1.586 +    INFO_PRINTF3(_L("%S: Database name is %S "), &KTestFunction, &adbnm);
   1.587 +
   1.588 +    // Try to open the database.
   1.589 +    TInt rc = KErrNone;
   1.590 +    TRAP(rc, isqldb.OpenL(adbnm, icfg));
   1.591 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
   1.592 +    if(rc == KErrNone) return ETrue;
   1.593 +    return EFalse;
   1.594 +    }
   1.595 +// Close the current database.
   1.596 +void CSQLFnStep::Close()
   1.597 +    {
   1.598 +//  _LIT(KTestFunction, "Close");
   1.599 +    isqldb.Close();
   1.600 +    return;
   1.601 +    }
   1.602 +void CSQLFnStep::Attach(const TPtrC &arg,
   1.603 +                        const TDesC &acfgblk, TInt acnnum)
   1.604 +    {
   1.605 +    _LIT(KTestFunction, "Attach");
   1.606 +    TPtrC sqldb, sqldbname;
   1.607 +    // Break arg into 'sqldb', the path/filename of the database to attach
   1.608 +    // and sqldbname, the name by which the database will be referred to
   1.609 +    // through this Attach.
   1.610 +    CommaSeparated(arg, sqldb, sqldbname);
   1.611 +    TInt rc = isqldb.Attach(sqldb, sqldbname);
   1.612 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
   1.613 +    return;
   1.614 +    }
   1.615 +void CSQLFnStep::Detach(const TPtrC &arg,
   1.616 +                        const TDesC &acfgblk, TInt acnnum)
   1.617 +    {
   1.618 +    _LIT(KTestFunction, "Detach");
   1.619 +    TInt rc = isqldb.Detach(arg);
   1.620 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
   1.621 +    return;
   1.622 +    }
   1.623 +void CSQLFnStep::Copy(const TPtrC &arg,
   1.624 +                      const TDesC &acfgblk, TInt acnnum)
   1.625 +    {
   1.626 +    _LIT(KTestFunction, "Copy");
   1.627 +    TPtrC sqldb1, sqldb2;
   1.628 +    CommaSeparated(arg, sqldb1, sqldb2);
   1.629 +    TInt rc = isqldb.Copy(sqldb1, sqldb2);
   1.630 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
   1.631 +    return;
   1.632 +    }
   1.633 +TBool CSQLFnStep::Delete(const TPtrC& adbnm,
   1.634 +                         const TDesC &acfgblk, TInt acnnum)
   1.635 +    {
   1.636 +    _LIT(KTestFunction, "Delete");
   1.637 +    INFO_PRINTF3(_L("%S: Database name is %S "), &KTestFunction, &adbnm);
   1.638 +
   1.639 +    // Try to delete the database.
   1.640 +    TInt rc = isqldb.Delete(adbnm);
   1.641 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
   1.642 +    if(rc == KErrNone) return ETrue;
   1.643 +    return EFalse;
   1.644 +    }
   1.645 +void CSQLFnStep::LastErrorMessage(const TPtrC& arg)
   1.646 +                
   1.647 +    {
   1.648 +    _LIT(KTestFunction, "LastErrorMessage");
   1.649 +
   1.650 +    TPtrC lem = isqldb.LastErrorMessage();
   1.651 +    if(arg.Length() == 0)
   1.652 +        {
   1.653 +        INFO_PRINTF3(_L("%S: '%S'"), &KTestFunction, &lem);
   1.654 +        return; // No particular error message was expected, so just return.
   1.655 +        }
   1.656 +    if(lem != arg)
   1.657 +        {
   1.658 +        SetTestStepResult(EFail);
   1.659 +        INFO_PRINTF1(HTML_RED);
   1.660 +        ERR_PRINTF4(_L("%S: Expected Message '%S', got '%S'"), &KTestFunction,
   1.661 +                                                                   &arg, &lem);
   1.662 +        INFO_PRINTF1(HTML_COLOUR_OFF);
   1.663 +        }
   1.664 +    else
   1.665 +        {
   1.666 +        INFO_PRINTF1(HTML_GREEN);
   1.667 +        INFO_PRINTF3(_L("%S: Got expected Message '%S'"), &KTestFunction, &arg);
   1.668 +        INFO_PRINTF1(HTML_COLOUR_OFF);
   1.669 +        }
   1.670 +    return;
   1.671 +    }
   1.672 +void CSQLFnStep::Exec(const TPtrC& arg,
   1.673 +                      const TDesC &acfgblk, TInt acnnum)
   1.674 +    {
   1.675 +    _LIT(KTestFunction, "Exec");
   1.676 +    TBuf<KConfigItemMaxNameLength> apiname(KTestFunction);
   1.677 +    TInt rc;
   1.678 +    if(i8bit == EFalse)
   1.679 +        {
   1.680 +        if(!iasync)
   1.681 +            rc = isqldb.Exec(arg);
   1.682 +        else
   1.683 +            {
   1.684 +            TChar ch = 'A';
   1.685 +            apiname.Append(ch);
   1.686 +            TRequestStatus trs;
   1.687 +            isqldb.Exec(arg, trs);
   1.688 +            User::WaitForRequest(trs);
   1.689 +            rc = trs.Int();
   1.690 +            }
   1.691 +        }
   1.692 +    else
   1.693 +        {
   1.694 +        apiname.AppendNum(8);
   1.695 +        RBuf8 b8;
   1.696 +        b8.Create(arg.Length());
   1.697 +        b8.Copy(arg);
   1.698 +        if(!iasync)
   1.699 +            rc = isqldb.Exec(b8);
   1.700 +        else
   1.701 +            {
   1.702 +            TChar ch = 'A';
   1.703 +            apiname.Append(ch);
   1.704 +            TRequestStatus trs;
   1.705 +            isqldb.Exec(b8, trs);
   1.706 +            User::WaitForRequest(trs);
   1.707 +            rc = trs.Int();
   1.708 +            }
   1.709 +        b8.Close();
   1.710 +        }
   1.711 +    ReportOnError(KTestFunction, apiname, acfgblk, acnnum, rc);
   1.712 +    return;
   1.713 +    }
   1.714 +void CSQLFnStep::SetIsolationLevel(const TPtrC& arg,
   1.715 +                                   const TDesC &acfgblk, TInt acnnum)
   1.716 +    {
   1.717 +    _LIT(KTestFunction, "SetIsolationLevel");
   1.718 +    // Get the expected error code..
   1.719 +    TPtrC experrS;
   1.720 +    TInt experr = ActionNoToErrEnum(acfgblk, acnnum, experrS);
   1.721 +
   1.722 +    INFO_PRINTF2(_L("SetIsolationLevel: %S"), &arg);
   1.723 +    RSqlDatabase::TIsolationLevel sil;
   1.724 +    if(arg == _L("EReadUncommitted"))
   1.725 +        sil = RSqlDatabase::EReadUncommitted;
   1.726 +    else if(arg == _L("EReadCommitted"))
   1.727 +        sil = RSqlDatabase::EReadCommitted;
   1.728 +    else if(arg == _L("ERepeatableRead"))
   1.729 +        sil = RSqlDatabase::ERepeatableRead;
   1.730 +    else if(arg == _L("ESerializable"))
   1.731 +        sil = RSqlDatabase::ESerializable;
   1.732 +    else
   1.733 +        {
   1.734 +        SetTestStepResult(EFail);
   1.735 +        INFO_PRINTF1(HTML_RED);
   1.736 +        ERR_PRINTF3(_L("%S: Unrecognized TIsolationLevel '%S'"), 
   1.737 +                                                    &KTestFunction, &arg);
   1.738 +        INFO_PRINTF1(HTML_COLOUR_OFF);
   1.739 +        return;
   1.740 +        }
   1.741 +
   1.742 +    TInt rc = isqldb.SetIsolationLevel(sil);
   1.743 +    TPtrC err;
   1.744 +    ErrEnumToString(rc,err);
   1.745 +    if(rc != experr)
   1.746 +        {
   1.747 +        SetTestStepResult(EFail);
   1.748 +        INFO_PRINTF1(HTML_RED);
   1.749 +        ERR_PRINTF3(_L("Unexpected SetIsolationLevel error %d/%S"), rc, &err);
   1.750 +        TPtrC lem = isqldb.LastErrorMessage();
   1.751 +        ERR_PRINTF2(_L(" - Last Error Message: %S"), &lem);
   1.752 +        INFO_PRINTF1(HTML_COLOUR_OFF);
   1.753 +        return;
   1.754 +        }
   1.755 +    else
   1.756 +        INFO_PRINTF2(_L("SetIsolation level, got error %S as expected"), &err);
   1.757 +    return;
   1.758 +    }
   1.759 +
   1.760 +void CSQLFnStep::ReserveDriveSpace(TInt ares,
   1.761 +                                   const TDesC& acfgblk, const TInt acnnum)
   1.762 +    {
   1.763 +    _LIT(KTestFunction, "ReserveDriveSpace");
   1.764 +
   1.765 +    // Try to reserve space..
   1.766 +    TInt rc = isqldb.ReserveDriveSpace(ares);
   1.767 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
   1.768 +    return;
   1.769 +    }
   1.770 +void CSQLFnStep::FreeReservedSpace()
   1.771 +    {
   1.772 +//    _LIT(KTestFunction, "FreeReservedSpace");
   1.773 +    isqldb.FreeReservedSpace();
   1.774 +    return;
   1.775 +    }
   1.776 +void CSQLFnStep::GetReserveAccess(const TDesC& acfgblk,
   1.777 +                                  const TInt acnnum)
   1.778 +    {
   1.779 +    _LIT(KTestFunction, "GetReserveAccess");
   1.780 +
   1.781 +    // Try to reserve space..
   1.782 +    TInt rc = isqldb.GetReserveAccess();
   1.783 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
   1.784 +    return;
   1.785 +    }
   1.786 +void CSQLFnStep::ReleaseReserveAccess()
   1.787 +    {
   1.788 +//    _LIT(KTestFunction, "ReleaseReserveSpace");
   1.789 +    isqldb.ReleaseReserveAccess();
   1.790 +    return;
   1.791 +    }
   1.792 +
   1.793 +// ----------Methods to exercise RSqlStatement methods ------------------------
   1.794 +//
   1.795 +// Execute a Close on the current RSqlStatement. This also clears out the
   1.796 +// arrays of RBufs and RBuf8s which are used for BindText and
   1.797 +// BindBinary (just a way of keeping the buffers in scope until the 
   1.798 +// Exec/Close happens) and loses all of the ParameterIndex and ColumnIndex's.
   1.799 +// The 'TInt' argument is just to differentiate between the RSqlDatabase
   1.800 +// Close wrapper, and this RSqlStatement Close wrapper.
   1.801 +void CSQLFnStep::Close(TInt)
   1.802 +    {
   1.803 +//    _LIT(KTestFunction, "St_Close");
   1.804 +
   1.805 +    // Close the RSqlStatement.
   1.806 +    isqlst.Close();
   1.807 +
   1.808 +    // Empty the arrays where we keep references to BindXXX buffers,
   1.809 +    // closing those buffers as we go.
   1.810 +    for(TInt count = iBindRBufarr.Count() - 1 ; count >= 0; count--)
   1.811 +        {
   1.812 +        iBindRBufarr[count].Close();
   1.813 +        iBindRBufarr.Remove(count);
   1.814 +        }
   1.815 +    for(TInt count = iBindRBuf8arr.Count() - 1 ; count >= 0 ; count--)
   1.816 +        {
   1.817 +        iBindRBuf8arr[count].Close();
   1.818 +        iBindRBuf8arr.Remove(count);
   1.819 +        }
   1.820 +    if((iBindRBuf8arr.Count() != 0) || (iBindRBufarr.Count() != 0))
   1.821 +        {
   1.822 +        User::Panic(_L("RBuf arrays not empty"), 512);
   1.823 +        }
   1.824 +
   1.825 +    // Empty the ParameterIndex and ColumnIndex arrays.
   1.826 +    while(ipidxs.Count()) ipidxs.Remove(0);
   1.827 +    while(icidxs.Count()) icidxs.Remove(0);
   1.828 +
   1.829 +    return;
   1.830 +    }
   1.831 +void CSQLFnStep::Next(TPtrC& arg,
   1.832 +                      const TDesC &acfgblk, TInt acnnum=-1)
   1.833 +    {
   1.834 +    _LIT(KTestFunction, "Next");
   1.835 +    TInt rc = isqlst.Next();
   1.836 +
   1.837 +    // If arg is not zero length it will be KSqlAtEnd/KSqlAtRow, turn that
   1.838 +    // into the enumeration.
   1.839 +    if(arg.Length())
   1.840 +        {
   1.841 +        TInt expn = ErrStringToEnum(arg);
   1.842 +        TPtrC errS;
   1.843 +        ErrEnumToString(rc, errS); // Convert the actual rc to a string.
   1.844 +        if(expn != rc)
   1.845 +            {
   1.846 +            SetTestStepResult(EFail);
   1.847 +            INFO_PRINTF1(HTML_RED);
   1.848 +            ERR_PRINTF7(_L("%S/%S: Got %S/%d, expected %S/%d"), &KTestFunction,
   1.849 +                                    &acfgblk, &errS, rc, &arg, expn );
   1.850 +            INFO_PRINTF1(HTML_COLOUR_OFF);
   1.851 +            }
   1.852 +        }
   1.853 +    ReportOnError(KTestFunction, _L("Next"), acfgblk, acnnum, rc);
   1.854 +    return;
   1.855 +    }
   1.856 +
   1.857 +// Call the RSqlStatement method 'AtRow'. This returns a boolean. This
   1.858 +// method expects the config file to contain a line resembling
   1.859 +// 'AtRow57=false'. The return value is checked against the config
   1.860 +// value and error/info is reported.
   1.861 +void CSQLFnStep::AtRow(const TPtrC &arg)
   1.862 +
   1.863 +    {
   1.864 +    _LIT(KTestFunction, "AtRow");
   1.865 +    TBuf<8> atrres(arg);
   1.866 +    atrres.LowerCase();
   1.867 +    TBool expected = EFalse;
   1.868 +    if(atrres == _L("false"))
   1.869 +        expected = EFalse;
   1.870 +    else if(atrres == _L("true"))
   1.871 +        expected = ETrue;
   1.872 +    else
   1.873 +        {
   1.874 +        SetTestStepResult(EFail);
   1.875 +        INFO_PRINTF1(HTML_RED);
   1.876 +        ERR_PRINTF3(_L("%S: expected config item to be true/false, got %S"),
   1.877 +                      &KTestFunction, &arg);
   1.878 +        INFO_PRINTF1(HTML_COLOUR_OFF);
   1.879 +        }
   1.880 +    TBool atr = isqlst.AtRow();
   1.881 +    if(atr != expected)
   1.882 +        {
   1.883 +        SetTestStepResult(EFail);
   1.884 +        INFO_PRINTF1(HTML_RED);
   1.885 +        ERR_PRINTF4(_L("%S: expected AtRow to return %S, got %d"),
   1.886 +                           &KTestFunction, &atrres, atr);
   1.887 +        INFO_PRINTF1(HTML_COLOUR_OFF);
   1.888 +        return;
   1.889 +        }
   1.890 +    else
   1.891 +        {
   1.892 +        INFO_PRINTF1(HTML_GREEN);
   1.893 +        INFO_PRINTF3(_L("%S: Got expected result, %S"), &KTestFunction, &atrres);
   1.894 +        INFO_PRINTF1(HTML_COLOUR_OFF);
   1.895 +        }
   1.896 +    return;
   1.897 +    }
   1.898 +// Call the RSqlStatement method 'Prepare'. This returns an int. This
   1.899 +// method expects the config file to contain a line resembling
   1.900 +// 'Prepare43=Create Table tbl3(f1 etc)'. The return value is checked
   1.901 +// against the expected error (in ReportOnError).
   1.902 +void CSQLFnStep::Prepare(const TPtrC &arg,
   1.903 +                         const TDesC &acfgblk, TInt acnnum=-1)
   1.904 +    {
   1.905 +    _LIT(KTestFunction, "Prepare");
   1.906 +    INFO_PRINTF3(_L("%S: Prepare command is %S"), &KTestFunction, &arg);
   1.907 +
   1.908 +    TInt rc;
   1.909 +    if(i8bit == EFalse)
   1.910 +        rc = isqlst.Prepare(isqldb, arg);
   1.911 +    else
   1.912 +        {
   1.913 +        RBuf8 b8;
   1.914 +        b8.Create(arg.Length());
   1.915 +        b8.Copy(arg);
   1.916 +        rc = isqlst.Prepare(isqldb, b8);
   1.917 +        b8.Close();
   1.918 +        }
   1.919 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
   1.920 +    }
   1.921 +void CSQLFnStep::PrepareL_(const TPtrC &arg,
   1.922 +                           const TDesC &acfgblk, TInt acnnum=-1)
   1.923 +    {
   1.924 +    _LIT(KTestFunction, "PrepareL");
   1.925 +    INFO_PRINTF3(_L("%S: PrepareL command is %S"), &KTestFunction, &arg);
   1.926 +
   1.927 +    TInt rc=KErrNone;
   1.928 +    if(i8bit == EFalse)
   1.929 +        {
   1.930 +        TRAP(rc, isqlst.PrepareL(isqldb, arg));
   1.931 +        }
   1.932 +    else
   1.933 +        {
   1.934 +        RBuf8 b8;
   1.935 +        b8.Create(arg.Length());
   1.936 +        b8.Copy(arg);
   1.937 +        TRAP(rc, isqlst.PrepareL(isqldb, b8));
   1.938 +        b8.Close();
   1.939 +        }
   1.940 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
   1.941 +    }
   1.942 +// Call the RSqlStatement method 'ParamIndex'. This returns an int. This
   1.943 +// method expects the config file to contain a line resembling
   1.944 +// 'ParamIndex12=:Frog'. The return value is returned.
   1.945 +TInt CSQLFnStep::ParamIndex(const TDesC &arg,
   1.946 +                            const TDesC &acfgblk, TInt acnnum=-1)
   1.947 +    {
   1.948 +    _LIT(KTestFunction, "ParameterIndex");
   1.949 +
   1.950 +    // If the test specifies ':?' was the parameter index, we'll assume that
   1.951 +    // ':?' was given in the SELECT (a nameless parameter), this always gives
   1.952 +    // '1' for the paramIndex.
   1.953 +    if(arg == _L(":?"))
   1.954 +        return 1;
   1.955 +
   1.956 +    // If arg resembles '23,*explicit*', then return the leading integer.
   1.957 +    // This is so we can call BindEtc with bad values for PANIC testing
   1.958 +    // or otherwise generate a specific parameter index.
   1.959 +    TInt pidx=0;
   1.960 +    TPtrC rhs;
   1.961 +    CommaSeparated(arg, pidx, rhs);
   1.962 +    if(rhs == _L("*explicit*"))
   1.963 +        {
   1.964 +        INFO_PRINTF3(_L("%S: Returning explicit Parameter Index %d"),
   1.965 +                                                      &KTestFunction, pidx);
   1.966 +        return pidx;
   1.967 +        }
   1.968 +
   1.969 +    // Ok, run ParameterIndex.
   1.970 +    pidx = isqlst.ParameterIndex(arg);
   1.971 +
   1.972 +    // ParameterIndex returns a non-negative integer on success. If the
   1.973 +    // return is negative, we have a problem. We cannot know what the
   1.974 +    // return is if the operation has succeeded, so checking the error
   1.975 +    // code is limited to required errors, i.e < 0.
   1.976 +    // ReportOnError will set test result to failure if the error doesn't
   1.977 +    // match our expected error.
   1.978 +    if(pidx < 0)
   1.979 +        ReportOnError(KTestFunction, _L("ParameterIndex"),
   1.980 +                       acfgblk, acnnum, pidx);
   1.981 +    return pidx;
   1.982 +    }
   1.983 +// Call the RSqlStatement method 'ColumnIndex'. This returns an int. This
   1.984 +// method expects the config file to contain a line resembling
   1.985 +// 'ColumnIndex12=Fld3'. The return value is returned.
   1.986 +TInt CSQLFnStep::ColumnIndex(const TPtrC& arg,
   1.987 +                             const TDesC &acfgblk, TInt acnnum=-1)
   1.988 +    {
   1.989 +    _LIT(KTestFunction, "ColumnIndex");
   1.990 +
   1.991 +    // If no column is specified then return zero - this may be necessary
   1.992 +    // if the test is for example counting lines in a table ...
   1.993 +    // >select count(*) from mytbl;
   1.994 +    // In this case obviously there is no namable column, but the Api just
   1.995 +    // requires that the index for ColumnInt will be zero.
   1.996 +    if(arg.Length() == 0) return 0;
   1.997 +
   1.998 +    // If arg resembles '23,*explicit*', then return the leading integer.
   1.999 +    // This is so we can call ColumnEtc with bad values for PANIC testing
  1.1000 +    // or otherwise generate a specific parameter index.
  1.1001 +    TInt colIndex=0;
  1.1002 +    TPtrC rhs;
  1.1003 +    CommaSeparated(arg, colIndex, rhs);
  1.1004 +    if(rhs == _L("*explicit*"))
  1.1005 +        {
  1.1006 +        INFO_PRINTF3(_L("%S: Returning explicit Column Index %d"),
  1.1007 +                                                      &KTestFunction, colIndex);
  1.1008 +        return colIndex;
  1.1009 +        }
  1.1010 +    colIndex = isqlst.ColumnIndex(arg);
  1.1011 +    // ColumnIndex returns a non-negative integer on success. If the
  1.1012 +    // return is negative, we have a problem. We cannot know what the
  1.1013 +    // return is if the operation has succeeded, so checking the error
  1.1014 +    // code is limited to required errors, i.e < 0.
  1.1015 +    // ReportOnError will set test result to failure if the error doesn't
  1.1016 +    // match our expected error.
  1.1017 +    if(colIndex < 0)
  1.1018 +        ReportOnError(KTestFunction, _L("ColumnIndex"),
  1.1019 +                       acfgblk, acnnum, colIndex);
  1.1020 +    return colIndex;
  1.1021 +    }
  1.1022 +// Call the RSqlStatement method 'ColumnType'.
  1.1023 +void CSQLFnStep::ColumnType(const TInt &acidx, const TPtrC &aexp)
  1.1024 +
  1.1025 +    {
  1.1026 +    _LIT(KTestFunction, "ColumnType");
  1.1027 +    TSqlColumnType gottype = isqlst.ColumnType(acidx);
  1.1028 +    TPtrC got(SqlColumnTypeToString(gottype));
  1.1029 +
  1.1030 +    if((aexp.Length() ==0) || (StringToSqlColumnType(aexp)==gottype))
  1.1031 +        {
  1.1032 +        INFO_PRINTF1(HTML_GREEN);
  1.1033 +        INFO_PRINTF3(_L("%S: Got Column type %S"), &KTestFunction, &got); 
  1.1034 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1035 +        return;
  1.1036 +        }
  1.1037 +
  1.1038 +    // If the expected type hasn't been specified then just display what
  1.1039 +    // we've got.
  1.1040 +    INFO_PRINTF1(HTML_RED);
  1.1041 +    ERR_PRINTF4(_L("%S: Got Column type %S, expected %S"),
  1.1042 +                          &KTestFunction, &got, &aexp);
  1.1043 +    SetTestStepResult(EFail);
  1.1044 +    INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1045 +    return;
  1.1046 +    }
  1.1047 +// Call the RSqlStatement method 'ColumnSize'. Check it against the
  1.1048 +// expected size specified in the config file.
  1.1049 +void CSQLFnStep::ColumnSize(const TInt& acolidx, const TInt &axexp)
  1.1050 +    {
  1.1051 +    _LIT(KTestFunction, "ColumnSize");
  1.1052 +    TInt csize = isqlst.ColumnSize(acolidx);
  1.1053 +
  1.1054 +    if((axexp != -1) && (axexp != csize))
  1.1055 +        {
  1.1056 +        INFO_PRINTF1(HTML_RED);
  1.1057 +        SetTestStepResult(EFail);
  1.1058 +        ERR_PRINTF4(_L("%S: Got Column size %d, expected %d"),
  1.1059 +                       &KTestFunction, csize, axexp);
  1.1060 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1061 +        return;
  1.1062 +        }
  1.1063 +    // If colsize is -1 display what we have.
  1.1064 +    INFO_PRINTF3(_L("%S: Got Column size %d"), &KTestFunction, csize); 
  1.1065 +
  1.1066 +    return;
  1.1067 +    }
  1.1068 +// Onto the Bind methods...
  1.1069 +void CSQLFnStep::BindNull(const TInt& apidx,
  1.1070 +                          const TDesC &acfgblk, const TInt acnnum=-1)
  1.1071 +    {
  1.1072 +    _LIT(KTestFunction, "BindNull");
  1.1073 +     
  1.1074 +    TInt err = isqlst.BindNull(apidx);
  1.1075 +    ReportOnError(KTestFunction, _L("BindNull"), acfgblk, acnnum, err);
  1.1076 +
  1.1077 +    return;
  1.1078 +    }
  1.1079 +void CSQLFnStep::BindInt(const TInt& apidx, const TInt& atob,
  1.1080 +                         const TDesC &acfgblk, const TInt acnnum=-1)
  1.1081 +    {
  1.1082 +    _LIT(KTestFunction, "BindInt");
  1.1083 +     
  1.1084 +    TInt err = isqlst.BindInt(apidx, atob);
  1.1085 +    ReportOnError(KTestFunction, _L("BindInt"), acfgblk, acnnum, err);
  1.1086 +
  1.1087 +    return;
  1.1088 +    }
  1.1089 +void CSQLFnStep::BindInt64(const TInt& apidx, const TPtrC& atob,
  1.1090 +                           const TDesC &acfgblk, const TInt acnnum=-1)
  1.1091 +    {
  1.1092 +    _LIT(KTestFunction, "BindInt64");
  1.1093 +    TInt64 bind;
  1.1094 +    TLex tl = atob;
  1.1095 +    tl.Val(bind);
  1.1096 +    TInt err = isqlst.BindInt64(apidx, bind);
  1.1097 +    ReportOnError(KTestFunction, _L("BindInt64"), acfgblk, acnnum, err);
  1.1098 +
  1.1099 +    return;
  1.1100 +    }
  1.1101 +void CSQLFnStep::BindReal(const TInt& apidx, const TReal& areal,
  1.1102 +                          const TDesC &acfgblk, const TInt acnnum=-1)
  1.1103 +    {
  1.1104 +    _LIT(KTestFunction, "BindReal");
  1.1105 +    TInt err = isqlst.BindReal(apidx, areal);
  1.1106 +    ReportOnError(KTestFunction, _L("BindReal"), acfgblk, acnnum, err);
  1.1107 +
  1.1108 +    return;
  1.1109 +    }
  1.1110 +// BindText from the config line...
  1.1111 +// May be modified to return a ref which we can keep on the
  1.1112 +// stack in the main loop. Then, when we hit a 'Next' that can be cleared.
  1.1113 +// This is necessary because there are scoping problems with text and
  1.1114 +// binarys - the SQL code expects buffers to remain in scope until
  1.1115 +// the Exec/Next.
  1.1116 +void CSQLFnStep::BindText(const TInt& apidx, const TPtrC& atxt,
  1.1117 +                          const TDesC &acfgblk, const TInt acnnum=-1)
  1.1118 +    {
  1.1119 +    _LIT(KTestFunction, "BindText");
  1.1120 +    TInt err = isqlst.BindText(apidx, atxt);
  1.1121 +    ReportOnError(KTestFunction, _L("BindText"), acfgblk, acnnum, err);
  1.1122 +
  1.1123 +    return;
  1.1124 +    }
  1.1125 +// An additional method to let us bind more than one line of text from
  1.1126 +// a config file...
  1.1127 +// If the Bind is successful the buffer which has been bound is appended
  1.1128 +// to the 'iBindRBufarr' array. This is necessary to keep it in scope until
  1.1129 +// the 'Next'/'Exec' actions.
  1.1130 +void CSQLFnStep::BindBigTextL(const TInt& apidx, const TPtrC& arg,
  1.1131 +                              const TDesC &acfgblk, const TInt acnnum=-1)
  1.1132 +    {
  1.1133 +    _LIT(KTestFunction, "BindBigText");
  1.1134 +    RBuf buf;
  1.1135 +
  1.1136 +    TInt fsize = FileSize(arg);
  1.1137 +    if(fsize < 0) return;  // This will have reported an error if necessary.
  1.1138 +    
  1.1139 +#ifdef _UNICODE
  1.1140 +    fsize >>= 1;  // We're assuming here that one character is two bytes..
  1.1141 +#endif
  1.1142 +
  1.1143 +    // Create a buffer big enough for the text in the file.
  1.1144 +    TInt err = buf.Create(fsize);
  1.1145 +    if(err != KErrNone)
  1.1146 +        {
  1.1147 +        SetTestStepResult(EFail);
  1.1148 +        INFO_PRINTF1(HTML_RED);
  1.1149 +        ERR_PRINTF3(_L("%S: Can't allocate file buffer %S"), &KTestFunction, &arg);
  1.1150 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1151 +        return;
  1.1152 +        }
  1.1153 +    // Don't push buf onto the cleanup stack. We'll keep a reference to it
  1.1154 +    // which get removed on RSqlStatement::Reset.
  1.1155 +
  1.1156 +    // Use an RFileReadStream because we need to worry about characters,
  1.1157 +    // not just bytes.
  1.1158 +    RFileReadStream rflrs;
  1.1159 +    if(rflrs.Open(irfs, arg, EFileRead) != KErrNone)
  1.1160 +        {
  1.1161 +        SetTestStepResult(EFail);
  1.1162 +        INFO_PRINTF1(HTML_RED);
  1.1163 +        ERR_PRINTF3(_L("%S: Can't open file %S"), &KTestFunction, &arg);
  1.1164 +        buf.Close();
  1.1165 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1166 +        return;
  1.1167 +        }
  1.1168 +    CleanupClosePushL(rflrs);
  1.1169 +    rflrs.ReadL(buf);
  1.1170 +
  1.1171 +    // Do the bind...
  1.1172 +    err = isqlst.BindText(apidx, buf);
  1.1173 +    ReportOnError(KTestFunction, _L("BindText"), acfgblk, acnnum, err);
  1.1174 +    // Drop out if it failed.
  1.1175 +    if(err != KErrNone)
  1.1176 +        {
  1.1177 +        CleanupStack::PopAndDestroy(1, &rflrs);
  1.1178 +        buf.Close();
  1.1179 +        return;
  1.1180 +        }
  1.1181 +    CleanupStack::PopAndDestroy(1, &rflrs);
  1.1182 +
  1.1183 +    // Tack the buffer onto the internal array. This keeps it in 
  1.1184 +    // scope until a RSqlStatement::Close is performed when it will get
  1.1185 +    // destroyed.
  1.1186 +    iBindRBufarr.Append(buf);
  1.1187 +
  1.1188 +    return;
  1.1189 +    }
  1.1190 +// If the Bind is successful the buffer which has been bound is appended
  1.1191 +// to the 'iBindRBuf8arr' array. This is necessary to keep it in scope until
  1.1192 +// the 'Next'/'Exec' actions.
  1.1193 +void CSQLFnStep::BindBinaryL(const TInt& apidx, const TDesC& arg,
  1.1194 +                              const TDesC &acfgblk, const TInt acnnum)
  1.1195 +    {
  1.1196 +    _LIT(KTestFunction, "BindBinary");
  1.1197 +    TInt fsize = FileSize(arg);
  1.1198 +    if(fsize < 0)
  1.1199 +        {
  1.1200 +        SetTestStepResult(EFail);
  1.1201 +        INFO_PRINTF1(HTML_RED);
  1.1202 +        ERR_PRINTF3(_L("%S: Can't find file %S"), &KTestFunction, &arg);
  1.1203 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1204 +        return;
  1.1205 +        }
  1.1206 +    // Create the buffer we're going to bind from. We'll keep a reference
  1.1207 +    // to this so it doesn't go out of scope (it mustn't
  1.1208 +    // until Exec/Reset) so don't put it on the cleanup stack.
  1.1209 +    RBuf8 ap;
  1.1210 +    TInt err = ap.Create(fsize);
  1.1211 +    ReportOnError(KTestFunction, _L("BufferCreate"), acfgblk, acnnum, err);
  1.1212 +    if(err != KErrNone) return;
  1.1213 +
  1.1214 +    // Now open the file specified in the argument.
  1.1215 +    RFile file;
  1.1216 +    TFileName fn = arg;
  1.1217 +    err = file.Open(irfs, fn, 0);
  1.1218 +    ReportOnError(KTestFunction, _L("FileOpen"), acfgblk, acnnum, err);
  1.1219 +    if(err != KErrNone)
  1.1220 +        {
  1.1221 +        ap.Close();
  1.1222 +        return;
  1.1223 +        }
  1.1224 +    CleanupClosePushL(file);
  1.1225 +
  1.1226 +    // Attempt to read from the file.
  1.1227 +    err = file.Read(ap, fsize);
  1.1228 +    ReportOnError(KTestFunction, _L("FileRead"), acfgblk, acnnum, err);
  1.1229 +    if(err != KErrNone)
  1.1230 +        {
  1.1231 +        CleanupStack::PopAndDestroy(1, &file);
  1.1232 +        ap.Close();
  1.1233 +        return;
  1.1234 +        }
  1.1235 +
  1.1236 +    // Do the bind...
  1.1237 +    err = isqlst.BindBinary(apidx, ap);
  1.1238 +    ReportOnError(KTestFunction, _L("BindBinary"), acfgblk, acnnum, err);
  1.1239 +
  1.1240 +    // Drop out if it failed.
  1.1241 +    if(err != KErrNone)
  1.1242 +        {
  1.1243 +        CleanupStack::PopAndDestroy(1, &file);
  1.1244 +        ap.Close();
  1.1245 +        return;
  1.1246 +        }
  1.1247 +
  1.1248 +    CleanupStack::PopAndDestroy(1, &file);
  1.1249 +
  1.1250 +    // Ok things seemed to have worked. Tack the buffer onto our internal
  1.1251 +    // RBuf8 array to keep it in scope. It will finally get trashed when
  1.1252 +    // we do the next RSqlStatement::Reset.
  1.1253 +    iBindRBuf8arr.Append(ap);
  1.1254 +
  1.1255 +    return;
  1.1256 +    }
  1.1257 +void CSQLFnStep::IsNull(const TInt& apidx, const TPtrC& atxt)
  1.1258 +    {
  1.1259 +    _LIT(KTestFunction, "IsNull");
  1.1260 +    TBuf<8> isn(atxt);
  1.1261 +    isn.LowerCase();
  1.1262 +    TBool expected;
  1.1263 +    if(isn == _L("false"))
  1.1264 +        expected = EFalse;
  1.1265 +    else if(isn == _L("true"))
  1.1266 +        expected = ETrue;
  1.1267 +    else
  1.1268 +        {
  1.1269 +        SetTestStepResult(EFail);
  1.1270 +        INFO_PRINTF1(HTML_RED);
  1.1271 +        ERR_PRINTF3(_L("%S: expected argument item to be true/false, got %S"),
  1.1272 +                     &KTestFunction, &atxt);
  1.1273 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1274 +        return;
  1.1275 +        }
  1.1276 +    if(isqlst.IsNull(apidx) != expected)
  1.1277 +        {
  1.1278 +        SetTestStepResult(EFail);
  1.1279 +        INFO_PRINTF1(HTML_RED);
  1.1280 +        ERR_PRINTF3(_L("%S: expected IsNull to return %S"), &KTestFunction,
  1.1281 +                            &atxt);
  1.1282 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1283 +        return;
  1.1284 +        }
  1.1285 +    else
  1.1286 +        {
  1.1287 +        INFO_PRINTF1(HTML_GREEN);
  1.1288 +        INFO_PRINTF3(_L("%S: Got expected result, %S"), &KTestFunction, &atxt);
  1.1289 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1290 +        }
  1.1291 +    return;
  1.1292 +    }
  1.1293 +void CSQLFnStep::ColumnInt(const TInt& acidx, const TInt& aint)
  1.1294 +    {
  1.1295 +    _LIT(KTestFunction, "ColumnInt");
  1.1296 +
  1.1297 +    TInt got = isqlst.ColumnInt(acidx);
  1.1298 +    if(got != aint)
  1.1299 +        {
  1.1300 +        SetTestStepResult(EFail);
  1.1301 +        INFO_PRINTF1(HTML_RED);
  1.1302 +        ERR_PRINTF4(_L("%S: expected ColumnInt to return %d, got %d"),
  1.1303 +                           &KTestFunction, aint, got);
  1.1304 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1305 +        return;
  1.1306 +        }
  1.1307 +    else
  1.1308 +        {
  1.1309 +        INFO_PRINTF1(HTML_GREEN);
  1.1310 +        INFO_PRINTF3(_L("%S: Got expected result, %d"), &KTestFunction,
  1.1311 +                           got);
  1.1312 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1313 +        }
  1.1314 +    return;
  1.1315 +    }
  1.1316 +void CSQLFnStep::ColumnInt64(const TInt& acidx, const TPtrC& aintS)
  1.1317 +    {
  1.1318 +    _LIT(KTestFunction, "ColumnInt64");
  1.1319 +
  1.1320 +    TLex tl(aintS);
  1.1321 +    TInt64 aint;
  1.1322 +    tl.Val(aint);
  1.1323 +    TInt64 got = isqlst.ColumnInt64(acidx);
  1.1324 +    if(got != aint)
  1.1325 +        {
  1.1326 +        SetTestStepResult(EFail);
  1.1327 +        INFO_PRINTF1(HTML_RED);
  1.1328 +        ERR_PRINTF3(_L("%S: expected ColumnInt to return %S"),
  1.1329 +                                   &KTestFunction, &aint);
  1.1330 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1331 +        return;
  1.1332 +        }
  1.1333 +    else
  1.1334 +        {
  1.1335 +        INFO_PRINTF1(HTML_GREEN);
  1.1336 +        INFO_PRINTF3(_L("%S: Got expected result, %ld"), &KTestFunction,
  1.1337 +                           got);
  1.1338 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1339 +        }
  1.1340 +    return;
  1.1341 +    }
  1.1342 +void CSQLFnStep::ColumnReal(const TInt& acidx, const TReal& areal)
  1.1343 +    {
  1.1344 +    _LIT(KTestFunction, "ColumnReal");
  1.1345 +
  1.1346 +    TReal got = isqlst.ColumnReal(acidx);
  1.1347 +    if(got != areal)
  1.1348 +        {
  1.1349 +        SetTestStepResult(EFail);
  1.1350 +        INFO_PRINTF1(HTML_RED);
  1.1351 +        ERR_PRINTF4(_L("%S: expected ColumnReal to return %f, got %f"),
  1.1352 +                           &KTestFunction, areal, got);
  1.1353 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1354 +        return;
  1.1355 +        }
  1.1356 +    else
  1.1357 +        {
  1.1358 +        INFO_PRINTF1(HTML_GREEN);
  1.1359 +        INFO_PRINTF3(_L("%S: Got expected result, %f"), &KTestFunction, got);
  1.1360 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1361 +        }
  1.1362 +    return;
  1.1363 +    }
  1.1364 +void CSQLFnStep::ColumnTextL(const TInt& acidx, const TPtrC& atxt,
  1.1365 +                             const TDesC &acfgblk, const TInt acnnum=-1)
  1.1366 +    {
  1.1367 +    _LIT(KTestFunction, "ColumnTextL");
  1.1368 +
  1.1369 +    TPtrC got = isqlst.ColumnTextL(acidx);
  1.1370 +    TInt err;
  1.1371 +
  1.1372 +    // First the simplest, does the text match the config text?
  1.1373 +    if(got == atxt)
  1.1374 +        {
  1.1375 +        INFO_PRINTF1(HTML_GREEN);
  1.1376 +        INFO_PRINTF3(_L("%S: Got expected result, %S"), &KTestFunction,
  1.1377 +                           &got);
  1.1378 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1379 +        return;
  1.1380 +        }
  1.1381 +
  1.1382 +    // Perhaps 'atxt' is a file, CompareTextAgainstFile will
  1.1383 +    // return KErrNotFound if it can't find the file.
  1.1384 +    if((err = CompareTextAgainstFileL(got, atxt)) == KErrNone)
  1.1385 +        {
  1.1386 +        INFO_PRINTF1(HTML_GREEN);
  1.1387 +        INFO_PRINTF3(_L("%S: Text match with file %S"), &KTestFunction,
  1.1388 +                           &atxt);
  1.1389 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1390 +        return;
  1.1391 +        }
  1.1392 +
  1.1393 +    ReportOnError(KTestFunction, _L("ColumnTextL"), acfgblk, acnnum, err);
  1.1394 +
  1.1395 +    return;
  1.1396 +    }
  1.1397 +void CSQLFnStep::ColumnTextPL(const TInt& acidx, const TPtrC &arg,
  1.1398 +                              const TDesC& acfgblk, const TInt acnnum=-1)
  1.1399 +    {
  1.1400 +    _LIT(KTestFunction, "ColumnTextP");
  1.1401 +
  1.1402 +    TPtrC got;
  1.1403 +    TInt err = isqlst.ColumnText(acidx, got);
  1.1404 +    ReportOnError(KTestFunction, _L("ColumnTextP"), acfgblk, acnnum, err);
  1.1405 +
  1.1406 +    // First the simplest, does the text match the config text?
  1.1407 +    if(got == arg)
  1.1408 +        {
  1.1409 +        INFO_PRINTF1(HTML_GREEN);
  1.1410 +        INFO_PRINTF3(_L("%S: Got expected result, %S"), &KTestFunction,
  1.1411 +                           &got);
  1.1412 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1413 +        return;
  1.1414 +        }
  1.1415 +
  1.1416 +    // Perhaps 'arg' is a file, CompareTextAgainstFile will
  1.1417 +    // return KErrNotFound if it can't find the file.
  1.1418 +    if((err = CompareTextAgainstFileL(got, arg)) == KErrNone)
  1.1419 +        {
  1.1420 +        INFO_PRINTF1(HTML_GREEN);
  1.1421 +        INFO_PRINTF3(_L("%S: Text match with file %S"), &KTestFunction,
  1.1422 +                           &arg);
  1.1423 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1424 +        return;
  1.1425 +        }
  1.1426 +
  1.1427 +    ReportOnError(KTestFunction, _L("ColumnTextP"), acfgblk, acnnum, err);
  1.1428 +    }
  1.1429 +void CSQLFnStep::ColumnTextDL(const TInt& acidx, const TPtrC &arg,
  1.1430 +                              const TDesC& acfgblk, const TInt acnnum=-1)
  1.1431 +    {
  1.1432 +    _LIT(KTestFunction, "ColumnTextD");
  1.1433 +// Masses of duplication.. We should have a common method to get around
  1.1434 +// this, but perhaps when time permits..
  1.1435 +
  1.1436 +    // How big is this item? This is measured in bytes, not characters.
  1.1437 +    TInt colsize = isqlst.ColumnSize(acidx);
  1.1438 +
  1.1439 +    // Allocate a buffer.
  1.1440 +    RBuf buf;
  1.1441 +    TInt err = buf.Create(colsize);
  1.1442 +    INFO_PRINTF3(_L("%S: colsize %d"), &KTestFunction, colsize);
  1.1443 +    if(err != KErrNone)
  1.1444 +        {
  1.1445 +        SetTestStepResult(EFail);
  1.1446 +        INFO_PRINTF1(HTML_RED);
  1.1447 +        ERR_PRINTF3(_L("%S: Failed to allocate %d"), &KTestFunction,
  1.1448 +                           colsize);
  1.1449 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1450 +        }
  1.1451 +    CleanupClosePushL(buf);
  1.1452 +
  1.1453 +    // Call ColumnText(TInt aColumnIndex, TDes& aDest);
  1.1454 +    err = isqlst.ColumnText(acidx, buf);
  1.1455 +    ReportOnError(KTestFunction, _L("ColumnTextD"), acfgblk, acnnum, err);
  1.1456 +    if(err != KErrNone)
  1.1457 +        {
  1.1458 +        CleanupStack::PopAndDestroy(1, &buf);
  1.1459 +        return;
  1.1460 +        }
  1.1461 +
  1.1462 +    // First the simplest, does the text match the config text?
  1.1463 +    if(buf == arg)
  1.1464 +        {
  1.1465 +        INFO_PRINTF1(HTML_GREEN);
  1.1466 +        INFO_PRINTF3(_L("%S: Got expected result, %S"), &KTestFunction,
  1.1467 +                           &buf);
  1.1468 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1469 +        CleanupStack::PopAndDestroy(1, &buf);
  1.1470 +        return;
  1.1471 +        }
  1.1472 +
  1.1473 +    // Perhaps 'arg' is a file, CompareTextAgainstFile will
  1.1474 +    // return KErrNotFound if it can't find the file.
  1.1475 +    if((err = CompareTextAgainstFileL(buf, arg)) == KErrNone)
  1.1476 +        {
  1.1477 +        INFO_PRINTF1(HTML_GREEN);
  1.1478 +        INFO_PRINTF3(_L("%S: Text match with file %S"), &KTestFunction,
  1.1479 +                           &arg);
  1.1480 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1481 +        CleanupStack::PopAndDestroy(1, &buf);
  1.1482 +        return;
  1.1483 +        }
  1.1484 +
  1.1485 +    ReportOnError(KTestFunction, _L("ColumnTextD"), acfgblk, acnnum, err);
  1.1486 +    CleanupStack::PopAndDestroy(1, &buf);
  1.1487 +    return;
  1.1488 +    }
  1.1489 +void CSQLFnStep::ColumnBinaryL(const TInt& acidx, const TPtrC &arg,
  1.1490 +                               const TDesC& acfgblk, const TInt acnnum=-1)
  1.1491 +    {
  1.1492 +    _LIT(KTestFunction, "ColumnBinaryL");
  1.1493 +
  1.1494 +    // Get the output from ColumnBinary.
  1.1495 +    TPtrC8 colb = isqlst.ColumnBinaryL(acidx);
  1.1496 +    INFO_PRINTF3(_L("%S: Got length %d"), &KTestFunction, colb.Length());
  1.1497 +    // If both are zero length, then we're expected nothing, which is a
  1.1498 +    // reasonable possibility.
  1.1499 +    if((colb.Length() == 0) && (arg.Length() == 0))
  1.1500 +        {
  1.1501 +        INFO_PRINTF1(HTML_GREEN);
  1.1502 +        INFO_PRINTF2(_L("%S: Got expected empty buffer."), &KTestFunction);
  1.1503 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1504 +        return;
  1.1505 +        }
  1.1506 +
  1.1507 +    // Compare ColumnBinary return against a file.
  1.1508 +    TInt err = CompareBinaryAgainstFileL(colb, arg);
  1.1509 +    ReportOnError(KTestFunction, _L("ColumnBinaryL"), acfgblk, acnnum, err);
  1.1510 +
  1.1511 +    return;
  1.1512 +    }
  1.1513 +void CSQLFnStep::ColumnBinaryPL(const TInt& acidx, const TPtrC &arg,
  1.1514 +                                const TDesC& acfgblk, const TInt acnnum=-1)
  1.1515 +    {
  1.1516 +    _LIT(KTestFunction, "ColumnBinaryP");
  1.1517 +
  1.1518 +    TInt csize = isqlst.ColumnSize(acidx);
  1.1519 +    INFO_PRINTF3(_L("%S: Colsize %d"), &KTestFunction, csize);
  1.1520 +#ifdef _UNICODE
  1.1521 +    if(isqlst.ColumnType(acidx) == ESqlText) csize <<= 1;
  1.1522 +#endif
  1.1523 +
  1.1524 +    RBuf8 data;
  1.1525 +    TInt err;
  1.1526 +    if((err = data.Create(csize)) != KErrNone)
  1.1527 +        {
  1.1528 +        ReportOnError(KTestFunction, _L("Createbuf"), acfgblk, acnnum, err);
  1.1529 +        return;
  1.1530 +        }
  1.1531 +    CleanupClosePushL(data);
  1.1532 +    err = isqlst.ColumnBinary(acidx, data);
  1.1533 +    ReportOnError(KTestFunction, _L("ColumnBinaryP"), acfgblk, acnnum, err);
  1.1534 +    if((data.Length()==0) && (arg.Length()==0))
  1.1535 +        {
  1.1536 +        INFO_PRINTF1(HTML_GREEN);
  1.1537 +        INFO_PRINTF2(_L("%S: Got expected empty buffer."), &KTestFunction);
  1.1538 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1539 +        CleanupStack::PopAndDestroy(1, &data);
  1.1540 +        return;
  1.1541 +        }
  1.1542 +    if(err != KErrNone)
  1.1543 +        {
  1.1544 +        CleanupStack::PopAndDestroy(1, &data);
  1.1545 +           return;
  1.1546 +        }
  1.1547 +
  1.1548 +    // Compare ColumnBinary return against a file.
  1.1549 +    err = CompareBinaryAgainstFileL(data, arg);
  1.1550 +    ReportOnError(KTestFunction, _L("FileCompare"), acfgblk, acnnum, err);
  1.1551 +    CleanupStack::PopAndDestroy(1, &data);
  1.1552 +    return;
  1.1553 +    }
  1.1554 +void CSQLFnStep::ColumnBinaryDL(const TInt& acidx, const TPtrC &arg,
  1.1555 +                                const TDesC& acfgblk, const TInt acnnum=-1)
  1.1556 +    {
  1.1557 +    _LIT(KTestFunction, "ColumnBinaryD");
  1.1558 +
  1.1559 +    // How big is this item?
  1.1560 +    TInt colsize = isqlst.ColumnSize(acidx);
  1.1561 +    INFO_PRINTF3(_L("%S: colsize %d"), &KTestFunction, colsize);
  1.1562 +#ifdef _UNICODE
  1.1563 +    if(isqlst.ColumnType(acidx) == ESqlText) colsize <<= 1;
  1.1564 +#endif
  1.1565 +
  1.1566 +    // Allocate a buffer.
  1.1567 +    RBuf8 buf;
  1.1568 +    TInt err = buf.Create(colsize);
  1.1569 +    if(err != KErrNone)
  1.1570 +        {
  1.1571 +        SetTestStepResult(EFail);
  1.1572 +        INFO_PRINTF1(HTML_RED);
  1.1573 +        ERR_PRINTF3(_L("%S: Failed to allocate %d bytes"), &KTestFunction,
  1.1574 +                           colsize);
  1.1575 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1576 +        }
  1.1577 +    CleanupClosePushL(buf);
  1.1578 +
  1.1579 +    // Call ColumnBinary(TInt aColumnIndex, TDes8& aDest);
  1.1580 +    err = isqlst.ColumnBinary(acidx, buf);
  1.1581 +    ReportOnError(KTestFunction, _L("ColumnBinaryD"), acfgblk, acnnum, err);
  1.1582 +    if(err != KErrNone)
  1.1583 +        {
  1.1584 +        CleanupStack::PopAndDestroy(1, &buf);
  1.1585 +        return;
  1.1586 +        }
  1.1587 +    if((buf.Length()==0) && (arg.Length()==0))
  1.1588 +        {
  1.1589 +        CleanupStack::PopAndDestroy(1, &buf);
  1.1590 +        INFO_PRINTF1(HTML_GREEN);
  1.1591 +        INFO_PRINTF2(_L("%S: Got expected empty buffer."), &KTestFunction);
  1.1592 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1593 +        return;
  1.1594 +        }
  1.1595 +
  1.1596 +    // Compare ColumnBinary return against a file.
  1.1597 +    err = CompareBinaryAgainstFileL(buf, arg);
  1.1598 +    ReportOnError(KTestFunction, _L("ColumnBinaryD"), acfgblk, acnnum, err);
  1.1599 +    CleanupStack::PopAndDestroy(1, &buf);
  1.1600 +
  1.1601 +    return;
  1.1602 +    }
  1.1603 +
  1.1604 +// The following four methods, SWBindText, SWBindBinary, SRColumnText and
  1.1605 +// SRColumnBinary are Stream-Write and Stream-Read methods.
  1.1606 +// In each case 'arg' specifies a file which is opened as a source (SW)
  1.1607 +// of data, or else as another stream (SR) to compare against.
  1.1608 +void CSQLFnStep::SWBindTextL(const TInt& apidx, const TPtrC &arg,
  1.1609 +                             const TDesC& acfgblk, const TInt acnnum=-1)
  1.1610 +    {
  1.1611 +    _LIT(KTestFunction, "SWBindText");
  1.1612 +    RSqlParamWriteStream sqlw;
  1.1613 +    // Get the WriteStream to stuff data down..
  1.1614 +    TInt err = sqlw.BindText(isqlst, apidx);
  1.1615 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, err);
  1.1616 +    if(err != KErrNone) return;
  1.1617 +    WriteFileToStreamL(sqlw, arg);
  1.1618 +    sqlw.Close();
  1.1619 +    return;
  1.1620 +    }
  1.1621 +void CSQLFnStep::SWBindBinaryL(const TInt& apidx, const TPtrC &arg,
  1.1622 +                               const TDesC& acfgblk, const TInt acnnum=-1)
  1.1623 +    {
  1.1624 +    _LIT(KTestFunction, "SWBindBinary");
  1.1625 +    RSqlParamWriteStream sqlw;
  1.1626 +    // Get the WriteStream to stuff data down..
  1.1627 +    TInt err = sqlw.BindBinary(isqlst, apidx);
  1.1628 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, err);
  1.1629 +    if(err != KErrNone) return;
  1.1630 +    WriteFileToStreamL(sqlw, arg);
  1.1631 +    sqlw.Close();
  1.1632 +    return;
  1.1633 +    }
  1.1634 +void CSQLFnStep::SRColumnTextL(const TInt& acidx, const TPtrC &arg,
  1.1635 +                              const TDesC& acfgblk, const TInt acnnum=-1)
  1.1636 +    {
  1.1637 +    _LIT(KTestFunction, "SRColumnText");
  1.1638 +
  1.1639 +    // First find out how much data is in this cell..
  1.1640 +    TInt dsize = isqlst.ColumnSize(acidx);
  1.1641 +    INFO_PRINTF3(_L("%S: ColumnSize is %d"), &KTestFunction, dsize);
  1.1642 +
  1.1643 +    RSqlColumnReadStream sqlr;
  1.1644 +    TInt err = sqlr.ColumnText(isqlst, acidx);
  1.1645 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, err);
  1.1646 +    if(err != KErrNone) return;
  1.1647 +    // Ok, we have a Read Stream..
  1.1648 +    CleanupClosePushL(sqlr);
  1.1649 +
  1.1650 +    // Compare it..
  1.1651 +    TInt rc = CompareTextStreamAgainstFileL(sqlr, dsize, arg);
  1.1652 +    if(rc)
  1.1653 +        {
  1.1654 +        SetTestStepResult(EFail);
  1.1655 +        INFO_PRINTF1(HTML_RED);
  1.1656 +        ERR_PRINTF3(_L("%S: Stream comparison failure, file %S"),
  1.1657 +                           &KTestFunction, &arg);
  1.1658 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1659 +        }
  1.1660 +    else
  1.1661 +        {
  1.1662 +        INFO_PRINTF1(HTML_GREEN);
  1.1663 +        INFO_PRINTF3(_L("%S: Stream comparison success, file %S"),
  1.1664 +                           &KTestFunction, &arg);
  1.1665 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1666 +        }
  1.1667 +    CleanupStack::PopAndDestroy(1,&sqlr);
  1.1668 +    return;
  1.1669 +    }
  1.1670 +void CSQLFnStep::SRColumnBinaryL(const TInt& acidx, const TPtrC &arg,
  1.1671 +                                 const TDesC& acfgblk, const TInt acnnum=-1)
  1.1672 +    {
  1.1673 +    _LIT(KTestFunction, "SRColumnBinary");
  1.1674 +
  1.1675 +    // First find out how much data is in this cell..
  1.1676 +    TInt dsize = isqlst.ColumnSize(acidx);
  1.1677 +    INFO_PRINTF3(_L("%S: Colsize is %d"), &KTestFunction, dsize);
  1.1678 +#ifdef _UNICODE
  1.1679 +    if(isqlst.ColumnType(acidx) == ESqlText) dsize <<= 1;
  1.1680 +#endif
  1.1681 +
  1.1682 +    // Get our RReadStream and check for errors.
  1.1683 +    RSqlColumnReadStream sqlr;
  1.1684 +    TInt err = sqlr.ColumnBinary(isqlst, acidx);
  1.1685 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, err);
  1.1686 +    if(err != KErrNone) return;
  1.1687 +    // Ok, we have a Read Stream..
  1.1688 +    CleanupClosePushL(sqlr);
  1.1689 +
  1.1690 +    // Compare it..
  1.1691 +    TInt rc = CompareBinaryStreamAgainstFileL(sqlr, dsize, arg);
  1.1692 +    if(rc)
  1.1693 +        {
  1.1694 +        SetTestStepResult(EFail);
  1.1695 +        INFO_PRINTF1(HTML_RED);
  1.1696 +        ERR_PRINTF3(_L("%S: Stream comparison failure, file %S"),
  1.1697 +                           &KTestFunction, &arg);
  1.1698 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1699 +        }
  1.1700 +    else
  1.1701 +        {
  1.1702 +        INFO_PRINTF1(HTML_GREEN);
  1.1703 +        INFO_PRINTF3(_L("%S: Stream comparison success, file %S"),
  1.1704 +                           &KTestFunction, &arg);
  1.1705 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1706 +        }
  1.1707 +    CleanupStack::PopAndDestroy(1,&sqlr);
  1.1708 +    return;
  1.1709 +    }
  1.1710 +
  1.1711 +TBool CSQLFnStep::SPCreate(const TDesC &acfgblk, const TInt acnnum)
  1.1712 +    {
  1.1713 +    _LIT(KTestFunction, "SPCreate");
  1.1714 +    
  1.1715 +    TSecurityPolicy defaultPolicy;
  1.1716 +    
  1.1717 +    // Try to create the SQLDB security policy.
  1.1718 +    TInt rc = isqlsp.Create(defaultPolicy);
  1.1719 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
  1.1720 +    if(rc == KErrNone) return ETrue;
  1.1721 +    return EFalse;
  1.1722 +    }
  1.1723 +
  1.1724 +TBool CSQLFnStep::SPCreate(const TPtrC&, const TDesC &acfgblk, const TInt acnnum)
  1.1725 +    {
  1.1726 +    _LIT(KTestFunction, "SPCreate");
  1.1727 +    
  1.1728 +    TSecurityPolicy defaultPolicy;
  1.1729 +    
  1.1730 +    // Try to create the SQLDB security policy.
  1.1731 +    TInt rc = KErrNone;
  1.1732 +    TRAP(rc, isqlsp.CreateL(defaultPolicy));
  1.1733 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
  1.1734 +    if(rc == KErrNone) return ETrue;
  1.1735 +    return EFalse;
  1.1736 +    }
  1.1737 +
  1.1738 +void CSQLFnStep::SPClose()
  1.1739 +    {
  1.1740 +    isqlsp.Close();
  1.1741 +    return;
  1.1742 +    }
  1.1743 +
  1.1744 +TBool CSQLFnStep::SPSetDBPolicy(const TPtrC& apol, const TDesC &acfgblk, const TInt acnnum)
  1.1745 +    {
  1.1746 +    _LIT(KTestFunction, "SPSetDBPolicy");
  1.1747 +
  1.1748 +    //extract the policy level and capability from the argument passed in
  1.1749 +    TPtrC level, cap;
  1.1750 +    CommaSeparated(apol, level, cap);
  1.1751 +
  1.1752 +    //create the security policy object with the supplied capability
  1.1753 +    TSecurityPolicy sp((TCapability)(icaphsh->GetNumFromString(cap)));
  1.1754 +
  1.1755 +    INFO_PRINTF2(_L("SetDBPolicy: %S"), &level);
  1.1756 +    INFO_PRINTF2(_L("Capabilities are: %S"), &cap);
  1.1757 +    
  1.1758 +    TInt rc = isqlsp.SetDbPolicy(((RSqlSecurityPolicy::TPolicyType)ipolhsh->GetNumFromString(level)), sp);
  1.1759 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
  1.1760 +    if(rc == KErrNone) return ETrue;
  1.1761 +    return EFalse;
  1.1762 +    }
  1.1763 +
  1.1764 +TBool CSQLFnStep::SPSetPolicy(const TPtrC& apol, const TDesC &acfgblk, const TInt acnnum)
  1.1765 +    {
  1.1766 +    _LIT(KTestFunction, "SPSetPolicy");
  1.1767 +
  1.1768 +    //extract the policy level and capability from the argument passed in
  1.1769 +    TPtrC arg, arg2, object, name, level, caps;
  1.1770 +    CommaSeparated(apol, object, arg);
  1.1771 +    CommaSeparated(arg, name, arg2);
  1.1772 +    CommaSeparated(arg2, level, caps);
  1.1773 +
  1.1774 +    //create the security policy object with the supplied capability
  1.1775 +    TSecurityPolicy sp((TCapability)(icaphsh->GetNumFromString(caps)));
  1.1776 +
  1.1777 +    INFO_PRINTF2(_L("SetPolicy: %S"), &level);
  1.1778 +    INFO_PRINTF2(_L("Capabilities are: %S"), &caps);
  1.1779 +    INFO_PRINTF2(_L("Object type is: %S"), &object);
  1.1780 +    INFO_PRINTF2(_L("Object name is: %S"), &name);
  1.1781 +    
  1.1782 +    TInt rc = isqlsp.SetPolicy(((RSqlSecurityPolicy::TObjectType)iobjhsh->GetNumFromString(object)), name, ((RSqlSecurityPolicy::TPolicyType)ipolhsh->GetNumFromString(level)), sp);
  1.1783 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
  1.1784 +    if(rc == KErrNone) return ETrue;
  1.1785 +    return EFalse;
  1.1786 +    }
  1.1787 +
  1.1788 +void CSQLFnStep::SPExternalize(const TPtrC &arg, const TDesC &acfgblk, const TInt acnnum)
  1.1789 +    {
  1.1790 +    _LIT(KTestFunction, "SPExternalize");
  1.1791 +    
  1.1792 +    RFileWriteStream rfws;
  1.1793 +
  1.1794 +    TInt err = rfws.Create(irfs, arg, EFileStream);
  1.1795 +    if(err != KErrNone)
  1.1796 +        {
  1.1797 +        SetTestStepResult(EFail);
  1.1798 +        INFO_PRINTF1(HTML_RED);
  1.1799 +        ERR_PRINTF4(_L("%S: Can't open file %S, err %d"), &KTestFunction, &arg,
  1.1800 +                         err );
  1.1801 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1802 +        return;
  1.1803 +        }
  1.1804 +    
  1.1805 +    TInt rc = KErrNone;
  1.1806 +    TRAP(rc, isqlsp.ExternalizeL(rfws));
  1.1807 +    TRAP(rc, rfws.CommitL());
  1.1808 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
  1.1809 +    rfws.Close();    
  1.1810 +    return;
  1.1811 +    }
  1.1812 +
  1.1813 +void CSQLFnStep::SPInternalize(const TPtrC &arg, const TDesC &acfgblk, const TInt acnnum)
  1.1814 +    {
  1.1815 +    _LIT(KTestFunction, "SPInternalize");
  1.1816 +    
  1.1817 +    RFileReadStream rfrs;
  1.1818 +    
  1.1819 +    TInt err = rfrs.Open(irfs, arg, EFileStream);
  1.1820 +    if(err != KErrNone)
  1.1821 +        {
  1.1822 +        SetTestStepResult(EFail);
  1.1823 +        INFO_PRINTF1(HTML_RED);
  1.1824 +        ERR_PRINTF3(_L("%S: Failed to open stream from file %S"), &KTestFunction, &arg);
  1.1825 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1826 +        return;
  1.1827 +        }
  1.1828 +    
  1.1829 +    TInt rc = KErrNone;
  1.1830 +    TRAP(rc, isqlsp.InternalizeL(rfrs));
  1.1831 +        
  1.1832 +    ReportOnError(KTestFunction, KTestFunction, acfgblk, acnnum, rc);
  1.1833 +    rfrs.Close();     
  1.1834 +    return;
  1.1835 +    }
  1.1836 +
  1.1837 +// - Utility functions... ---  we should remove these into a separate class -- 
  1.1838 +//
  1.1839 +// Stream functions - should we have a persistent stream? Here it goes
  1.1840 +// out of scope once the method completes, but what about a case where for
  1.1841 +// example we write to a cell, then write some more later to the same cell?
  1.1842 +//
  1.1843 +// Loads more duplication..
  1.1844 +TInt CSQLFnStep::CompareTextStreamAgainstFileL(RReadStream &as, TInt asiz,
  1.1845 +                                               const TPtrC &afile)
  1.1846 +    {
  1.1847 +    _LIT(KTestFunction, "CompareTextStreamAgainstFile");
  1.1848 +    // Get the file size. This is in bytes, so for Unicode will be
  1.1849 +    // out by a factor of two. Also, if created with notepad or similar
  1.1850 +    // will have a 'FEFF' two byte marker at the start (which SQLite
  1.1851 +    // strips when it sees it).
  1.1852 +    TInt fsize = FileSize(afile);
  1.1853 +    if(fsize < 0) return fsize;;
  1.1854 +    // We don't divide asiz by two: This will have originated in ColumnSize
  1.1855 +    // which returns the number of characters in a cell.
  1.1856 +    TInt textlen = asiz;
  1.1857 +#ifdef _UNICODE
  1.1858 +    fsize >>= 1;
  1.1859 +#endif
  1.1860 +
  1.1861 +    // If fsize is 1 different (2 bytes) from textlen, then we'll expect
  1.1862 +    // a unicode marker. If not 1 or zero give up straight away.
  1.1863 +    TInt diff = fsize - textlen;
  1.1864 +    TInt ucmark = (diff == 1);
  1.1865 +    if((diff>1) || (diff<0))
  1.1866 +        {
  1.1867 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1868 +        ERR_PRINTF4(_L("%S Size mismatch. Expected %d, got %d"),
  1.1869 +                                                &KTestFunction, fsize, textlen);
  1.1870 +        SetTestStepResult(EFail);
  1.1871 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1872 +        return KTEFSQLSizeError;
  1.1873 +        }
  1.1874 +
  1.1875 +    // Open the reference file specified in the argument.
  1.1876 +    // Use an RFileReadStream because we need to worry about characters,
  1.1877 +    // not just bytes.
  1.1878 +    RFileReadStream rflrs;
  1.1879 +    TInt err = rflrs.Open(irfs, afile, EFileRead);
  1.1880 +    if(err != KErrNone)
  1.1881 +        return err;
  1.1882 +    CleanupClosePushL(rflrs);
  1.1883 +
  1.1884 +    // Dumps the FEFF marker bytes for unicode files.
  1.1885 +    // SQLite does the same for text.
  1.1886 +    if(ucmark)
  1.1887 +        {
  1.1888 +        TInt16 mark = rflrs.ReadInt16L();  // byte order?
  1.1889 +        if((mark != (TInt16)0xfeff) && (mark != (TInt16)0xfffe))
  1.1890 +            {
  1.1891 +            CleanupStack::PopAndDestroy(1, &rflrs);
  1.1892 +            return KTEFSQLSizeError;
  1.1893 +            }
  1.1894 +        }
  1.1895 +
  1.1896 +    // For each 32768 chars in the text buffer...
  1.1897 +    const TInt slice = 32768;
  1.1898 +    RBuf fbuf, abuf;
  1.1899 +    err = fbuf.Create(slice);
  1.1900 +    if(err == KErrNone) err = abuf.Create(slice);
  1.1901 +    if(err != KErrNone)
  1.1902 +        {
  1.1903 +        CleanupStack::PopAndDestroy(1, &rflrs);
  1.1904 +        return KErrNoMemory;
  1.1905 +        }
  1.1906 +    CleanupClosePushL(fbuf);
  1.1907 +    CleanupClosePushL(abuf);
  1.1908 +
  1.1909 +    TInt rc = KErrNone;
  1.1910 +    for(TInt pos=0; pos < textlen ; pos += slice)
  1.1911 +        {
  1.1912 +        TInt toread = textlen - pos;
  1.1913 +        if(toread > slice)
  1.1914 +            toread = slice;
  1.1915 +
  1.1916 +        // Read 'toread' characters from the file and from the passed in
  1.1917 +        // data.
  1.1918 +        as.ReadL(abuf, toread);
  1.1919 +        TPtrC txtslice = abuf.Left(toread);
  1.1920 +        rflrs.ReadL(fbuf, toread);
  1.1921 +        TPtrC fileslice = fbuf.Left(toread);
  1.1922 +
  1.1923 +        // Compare ..
  1.1924 +        if (fileslice != txtslice)
  1.1925 +            { 
  1.1926 +            rc = KTEFSQLSizeError;
  1.1927 +            break;
  1.1928 +            }
  1.1929 +        }
  1.1930 +    CleanupStack::PopAndDestroy(3, &rflrs);
  1.1931 +    return rc;
  1.1932 +    }
  1.1933 +
  1.1934 +// Loads more duplication..
  1.1935 +TInt CSQLFnStep::CompareBinaryStreamAgainstFileL(RReadStream &as, TInt asiz,
  1.1936 +                                                const TPtrC &afile)
  1.1937 +    {
  1.1938 +    _LIT(KTestFunction, "CompareBinaryStreamAgainstFile");
  1.1939 +    // Get the file size. This is in bytes.
  1.1940 +    TInt fsize = FileSize(afile);
  1.1941 +    if(fsize < 0) return fsize;;
  1.1942 +
  1.1943 +    // If sizes differ give up immediately.
  1.1944 +    if(fsize - asiz)
  1.1945 +        {
  1.1946 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1947 +        ERR_PRINTF4(_L("%S Size mismatch. Expected %d, got %d"),
  1.1948 +                                                &KTestFunction, fsize, asiz);
  1.1949 +        SetTestStepResult(EFail);
  1.1950 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.1951 +        return KTEFSQLSizeError;
  1.1952 +        }
  1.1953 +
  1.1954 +    // Open the reference file specified in the argument.
  1.1955 +    // Use an RFileReadStream because we need to worry about characters,
  1.1956 +    // not just bytes.
  1.1957 +    RFileReadStream rflrs;
  1.1958 +    TInt err = rflrs.Open(irfs, afile, EFileRead);
  1.1959 +    if(err != KErrNone) return err;
  1.1960 +    CleanupClosePushL(rflrs);
  1.1961 +
  1.1962 +    // For each 32768 chars in the text buffer...
  1.1963 +    const TInt slice = 32768;
  1.1964 +    RBuf8 fbuf, abuf;
  1.1965 +    err = fbuf.Create(slice);
  1.1966 +    if(err == KErrNone) err = abuf.Create(slice);
  1.1967 +    if(err != KErrNone)
  1.1968 +        {
  1.1969 +        CleanupStack::PopAndDestroy(1, &rflrs);
  1.1970 +        return err;
  1.1971 +        }
  1.1972 +    CleanupClosePushL(fbuf);
  1.1973 +    CleanupClosePushL(abuf);
  1.1974 +
  1.1975 +    TInt rc = KErrNone;
  1.1976 +    for(TInt pos=0; pos < asiz ; pos += slice)
  1.1977 +        {
  1.1978 +        TInt toread = asiz - pos;
  1.1979 +        if(toread > slice)
  1.1980 +            toread = slice;
  1.1981 +
  1.1982 +        // Read 'toread' characters from the file and from the passed in
  1.1983 +        // data. Do we really need to chop out only the read bits for
  1.1984 +        // comparison? Wouldn't comparing fbuf and abuf work?
  1.1985 +        rflrs.ReadL(fbuf, toread);
  1.1986 +        TPtr8 fslice = fbuf.LeftTPtr(toread);
  1.1987 +        as.ReadL(abuf, toread);
  1.1988 +        TPtr8 aslice = abuf.LeftTPtr(toread);
  1.1989 +
  1.1990 +        // Compare .. (does this compare only what's been read?)
  1.1991 +        if (fslice != aslice)
  1.1992 +            { 
  1.1993 +            rc = KTEFSQLSizeError;
  1.1994 +            break;
  1.1995 +            }
  1.1996 +        }
  1.1997 +    CleanupStack::PopAndDestroy(3, &rflrs);
  1.1998 +    return rc;
  1.1999 +    }
  1.2000 +void CSQLFnStep::WriteFileToStreamL(RWriteStream &as1, const TPtrC &afile)
  1.2001 +    {
  1.2002 +    _LIT(KTestFunction, "WriteFileToStream");
  1.2003 +    // Open the reference file specified in the argument.
  1.2004 +    RFileReadStream rflrs;
  1.2005 +    TInt err = rflrs.Open(irfs, afile, EFileRead);
  1.2006 +    // Do we want to return anything?
  1.2007 +    if(err != KErrNone)
  1.2008 +        {
  1.2009 +        SetTestStepResult(EFail);
  1.2010 +        INFO_PRINTF1(HTML_RED);
  1.2011 +        ERR_PRINTF3(_L("%S: Failed to open stream from file %S"),
  1.2012 +                           &KTestFunction, &afile);
  1.2013 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.2014 +        return;
  1.2015 +        }
  1.2016 +    CleanupClosePushL(rflrs);
  1.2017 +    as1.WriteL(rflrs);
  1.2018 +    CleanupStack::PopAndDestroy(1, &rflrs);
  1.2019 +    return;
  1.2020 +    }
  1.2021 +
  1.2022 +TInt CSQLFnStep::CompareBinaryAgainstFileL(const TDesC8 &abuf,
  1.2023 +                                          const TFileName& afile)
  1.2024 +    {
  1.2025 +    _LIT(KTestFunction, "CompareBinaryAgainstFile");
  1.2026 +    // Get the file size.
  1.2027 +    TInt fsize = FileSize(afile);
  1.2028 +    if(fsize < 0) return fsize;
  1.2029 +    // How much binary do we have?
  1.2030 +    TInt binlen = abuf.Length();
  1.2031 +
  1.2032 +    INFO_PRINTF4(_L("%S: Filelen %d, Binlen %d"), &KTestFunction, fsize, binlen);
  1.2033 +
  1.2034 +    // If sizes differ drop out immediately.
  1.2035 +    if(fsize - binlen)
  1.2036 +        return KTEFSQLSizeError;
  1.2037 +
  1.2038 +    // Open the reference file specified in the argument.
  1.2039 +    // Use an RFileReadStream because we need to worry about characters,
  1.2040 +    // not just bytes.
  1.2041 +    RFileReadStream rflrs;
  1.2042 +    TInt err = rflrs.Open(irfs, afile, EFileRead);
  1.2043 +    if(err != KErrNone)
  1.2044 +        return err;
  1.2045 +    CleanupClosePushL(rflrs);
  1.2046 +
  1.2047 +    // For each 32768 chars in the text buffer...
  1.2048 +    const TInt slice = 32768;
  1.2049 +    RBuf8 fbuf;
  1.2050 +    fbuf.Create(slice);
  1.2051 +    CleanupClosePushL(fbuf);
  1.2052 +
  1.2053 +    TInt rc = KErrNone;
  1.2054 +    for(TInt pos=0; pos < binlen ; pos += slice)
  1.2055 +        {
  1.2056 +        TInt toread = binlen - pos;
  1.2057 +        if(toread > slice)
  1.2058 +            toread = slice;
  1.2059 +
  1.2060 +        // Read 'toread' bytes from the file and from the passed in
  1.2061 +        // data.
  1.2062 +        rflrs.ReadL(fbuf, toread);
  1.2063 +        TPtrC8 fileslice = fbuf.Left(toread);
  1.2064 +        TPtrC8 binslice = abuf.Mid(pos, toread);
  1.2065 +
  1.2066 +        // Compare ..
  1.2067 +        if (fileslice != binslice)
  1.2068 +            { 
  1.2069 +            rc = KTEFSQLSizeError;
  1.2070 +            break;
  1.2071 +            }
  1.2072 +        }
  1.2073 +
  1.2074 +    INFO_PRINTF2(_L("%S: Comparison successful"), &KTestFunction);
  1.2075 +    CleanupStack::PopAndDestroy(2, &rflrs);
  1.2076 +    return rc;
  1.2077 +    }
  1.2078 +
  1.2079 +// Tested and working..
  1.2080 +TInt CSQLFnStep::CompareTextAgainstFileL(const TDesC &atxt,
  1.2081 +                                        const TFileName& afile)
  1.2082 +    {
  1.2083 +    // Get the file size. This is in bytes, so for Unicode will be
  1.2084 +    // out by a factor of two. Also, if created with notepad or similar
  1.2085 +    // will have a 'FEFF' two byte marker at the start (which SQLite
  1.2086 +    // strips when it sees it).
  1.2087 +    TInt fsize = FileSize(afile);
  1.2088 +    if(fsize < 0) return fsize;
  1.2089 +#ifdef _UNICODE
  1.2090 +    fsize >>= 1;
  1.2091 +#endif
  1.2092 +    // How much text do we have?
  1.2093 +    TInt textlen = atxt.Length();
  1.2094 +
  1.2095 +    // If fsize is 1 different (2 bytes) from textlen, then we'll expect
  1.2096 +    // a unicode marker. If not 1 or zero give up straight away.
  1.2097 +    TInt diff = fsize - textlen;
  1.2098 +    TInt ucmark = (diff == 1);
  1.2099 +    if((diff>1) || (diff<0))
  1.2100 +        {
  1.2101 +        ERR_PRINTF3(_L("FSIZE is %d, textlen is %d"), fsize, textlen);
  1.2102 +        return KTEFSQLSizeError;
  1.2103 +        }
  1.2104 +
  1.2105 +    // Open the reference file specified in the argument.
  1.2106 +    // Use an RFileReadStream because we need to worry about characters,
  1.2107 +    // not just bytes.
  1.2108 +    RFileReadStream rflrs;
  1.2109 +    TInt err = rflrs.Open(irfs, afile, EFileRead);
  1.2110 +    if(err != KErrNone)
  1.2111 +        return err;
  1.2112 +    CleanupClosePushL(rflrs);
  1.2113 +
  1.2114 +    // Dumps the FEFF marker bytes for unicode files.
  1.2115 +    // SQLite does the same for text.
  1.2116 +    if(ucmark)
  1.2117 +        {
  1.2118 +        TInt16 mark = rflrs.ReadInt16L();  // byte order?
  1.2119 +        if((mark != (TInt16)0xfeff) && (mark != (TInt16)0xfffe))
  1.2120 +            {
  1.2121 +            CleanupStack::PopAndDestroy(1, &rflrs);
  1.2122 +            return KTEFSQLSizeError;
  1.2123 +            }
  1.2124 +        }
  1.2125 +
  1.2126 +    // For each 32768 chars in the text buffer...
  1.2127 +    const TInt slice = 32768;
  1.2128 +    RBuf fbuf;
  1.2129 +    fbuf.Create(slice);
  1.2130 +    CleanupClosePushL(fbuf);
  1.2131 +
  1.2132 +    TInt rc = KErrNone;
  1.2133 +    for(TInt pos=0; pos < textlen ; pos += slice)
  1.2134 +        {
  1.2135 +        TInt toread = textlen - pos;
  1.2136 +        if(toread > slice)
  1.2137 +            toread = slice;
  1.2138 +
  1.2139 +        // Read 'toread' characters from the file and from the passed in
  1.2140 +        // data.
  1.2141 +        rflrs.ReadL(fbuf, toread);
  1.2142 +        TPtrC txtslice = atxt.Mid(pos, toread);
  1.2143 +
  1.2144 +        // Compare ..
  1.2145 +        if (fbuf != txtslice)
  1.2146 +            { 
  1.2147 +            rc = KTEFSQLSizeError;
  1.2148 +            break;
  1.2149 +            }
  1.2150 +        }
  1.2151 +    CleanupStack::PopAndDestroy(2, &rflrs);
  1.2152 +    return rc;
  1.2153 +    }
  1.2154 +
  1.2155 +// Get the expected error code for the current action. Assume KErrNone if it
  1.2156 +// isn't in the config file. We might have (in the config file)
  1.2157 +// ExpectedError27=KSqlErrPermission
  1.2158 +int CSQLFnStep::ActionNoToErrEnum(const TDesC& acfgsec, const TInt aActionNum,
  1.2159 +                                  TPtrC& aes)
  1.2160 +    {
  1.2161 +    TBuf<KConfigItemMaxNameLength> cnfgerr(_L("ExpectedError"));
  1.2162 +    if(aActionNum != -1) cnfgerr.AppendNum(aActionNum);
  1.2163 +    if(!GetStringFromConfig(acfgsec, cnfgerr, aes))
  1.2164 +        aes.Set(_L("KErrNone"));
  1.2165 +    return(ErrStringToEnum(aes));
  1.2166 +}
  1.2167 +TInt CSQLFnStep::ErrStringToEnum(TPtrC &aerr)
  1.2168 +    {
  1.2169 +    return(ierrhsh->GetNumFromString(aerr));
  1.2170 +    }
  1.2171 +void CSQLFnStep::ErrEnumToString(const TInt &aerr, TPtrC &aptrstr)
  1.2172 +    {
  1.2173 +    aptrstr.Set(*(ierrhsh->GetStringFromNum(aerr)));
  1.2174 +    return;
  1.2175 +    }
  1.2176 +const TPtrC CSQLFnStep::SqlColumnTypeToString(TSqlColumnType &asqltype)
  1.2177 +    {
  1.2178 +    return *icoltypehsh->GetStringFromNum(asqltype);
  1.2179 +    }
  1.2180 +TSqlColumnType CSQLFnStep::StringToSqlColumnType(const TDesC &atype)
  1.2181 +    {
  1.2182 +    return (TSqlColumnType) icoltypehsh->GetNumFromString(atype);
  1.2183 +    }
  1.2184 +/*
  1.2185 + * A helper function to report on an error. This won't say anything if the
  1.2186 + * error received (aerr) is equal to the error expected as defined in the
  1.2187 + * configuration file.
  1.2188 + */
  1.2189 +void CSQLFnStep::ReportOnError(const TDesC &afnnam, const TDesC &apinam,
  1.2190 +                                const TDesC &acfgblk, const TInt acfgno,
  1.2191 +                                const TInt aerr)
  1.2192 +    {
  1.2193 +    // Get the expected error.
  1.2194 +    TPtrC experrS;
  1.2195 +    TInt experr = ActionNoToErrEnum(acfgblk, acfgno, experrS);
  1.2196 +
  1.2197 +    // Some methods such as Exec and Next return a positive value on
  1.2198 +    // success. If we're not expecting an error and the actual error code
  1.2199 +    // is positive just return, everything is cool.
  1.2200 +    if((experr == KErrNone) && (aerr >= 0))
  1.2201 +        return;
  1.2202 +
  1.2203 +    // Is the actual error the same as the expected error?
  1.2204 +    if(aerr != experr)
  1.2205 +        {
  1.2206 +        INFO_PRINTF1(HTML_RED);
  1.2207 +        SetTestStepResult(EFail);
  1.2208 +        TPtrC errS;
  1.2209 +        ErrEnumToString(aerr, errS); // Convert the actual error to a string.
  1.2210 +
  1.2211 +        ERR_PRINTF7(_L("%S: %S gave error %d/%S, expected %d/%S"),
  1.2212 +                        &afnnam, &apinam, aerr, &errS, experr, &experrS);
  1.2213 +        // Run 'LastErrorMessage' if we unexpectedly have 'KSqlErrGeneral',
  1.2214 +        // often what it has to say is very helpful.
  1.2215 +        if(aerr == KSqlErrGeneral)
  1.2216 +            LastErrorMessage(_L(""));
  1.2217 +
  1.2218 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.2219 +        }
  1.2220 +    else if(aerr != KErrNone)
  1.2221 +        {
  1.2222 +        INFO_PRINTF1(HTML_GREEN);
  1.2223 +        INFO_PRINTF5(_L("%S: %S got expected error %d/%S"), &afnnam, &apinam,
  1.2224 +                              aerr, &experrS);
  1.2225 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.2226 +        }
  1.2227 +    return;
  1.2228 +    }
  1.2229 +TBool CSQLFnStep::FromConfig(const TDesC &afnnam, const TDesC &acfgblk,
  1.2230 +                             const TDesC &acfgname, TPtrC &acfgval)
  1.2231 +    {
  1.2232 +    if(!GetStringFromConfig(acfgblk, acfgname, acfgval))
  1.2233 +        {
  1.2234 +        INFO_PRINTF1(HTML_RED);
  1.2235 +        ERR_PRINTF4(_L("%S: Failed to get %S:%S parameter."), &afnnam, &acfgblk,
  1.2236 +                                                              &acfgname);
  1.2237 +        SetTestStepResult(EFail);
  1.2238 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.2239 +        return EFalse;
  1.2240 +        }
  1.2241 +    return ETrue;
  1.2242 +    }
  1.2243 +TBool CSQLFnStep::FromConfig(const TDesC &afnnam, const TDesC &acfgblk,
  1.2244 +                             const TDesC &acfgname, TInt &acfgval)
  1.2245 +    {
  1.2246 +    if(!GetIntFromConfig(acfgblk, acfgname, acfgval))
  1.2247 +        {
  1.2248 +        INFO_PRINTF1(HTML_RED);
  1.2249 +        ERR_PRINTF4(_L("%S: Failed to get %S:%S parameter."), &afnnam, &acfgblk,
  1.2250 +                           &acfgname);
  1.2251 +        SetTestStepResult(EFail);
  1.2252 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.2253 +        return EFalse;
  1.2254 +        }
  1.2255 +    return ETrue;
  1.2256 +    }
  1.2257 +TBool CSQLFnStep::FromConfig(const TDesC &afnnam, const TDesC &acfgblk,
  1.2258 +                             const TDesC &acfgname, TReal &acfgval)
  1.2259 +    {
  1.2260 +    TPtrC gotS;
  1.2261 +    if(!GetStringFromConfig(acfgblk, acfgname, gotS))
  1.2262 +        {
  1.2263 +        INFO_PRINTF1(HTML_RED);
  1.2264 +        ERR_PRINTF4(_L("%S: Failed to get %S:%S parameter."), &afnnam, &acfgblk,
  1.2265 +                                                              &acfgname);
  1.2266 +        SetTestStepResult(EFail);
  1.2267 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.2268 +        return EFalse;
  1.2269 +        }
  1.2270 +    TLex tl = gotS;
  1.2271 +    if(tl.Val(acfgval) != KErrNone)
  1.2272 +        {
  1.2273 +        ERR_PRINTF5(_L("%S:%S Failed to convert %S:%S to real."),
  1.2274 +                           &afnnam, &acfgblk, &acfgname, &gotS);
  1.2275 +        return EFalse;
  1.2276 +        }
  1.2277 +
  1.2278 +    return ETrue;
  1.2279 +    }
  1.2280 +// Looking for, e.g, "9876,1234" 
  1.2281 +void CSQLFnStep::CommaSeparated(const TPtrC& ainp, TInt &aint, TInt &aint2)
  1.2282 +    {
  1.2283 +//    _LIT(KTestFunction, "CommaSeparated");
  1.2284 +
  1.2285 +    // Read in what kind of binds we'll be doing..
  1.2286 +    TInt origlen = ainp.Length();
  1.2287 +    TChar comma(',');
  1.2288 +    TInt comoffset = ainp.Locate(comma);
  1.2289 +    if(comoffset != KErrNotFound)
  1.2290 +        {
  1.2291 +        TPtrC left = ainp.Left(comoffset);
  1.2292 +        TLex tl(left);
  1.2293 +        tl.Val(aint);
  1.2294 +        TInt rightlen = origlen - comoffset - 1;
  1.2295 +        TPtrC right = ainp.Right(rightlen);
  1.2296 +        tl = right;
  1.2297 +        tl.Val(aint2);
  1.2298 +        }
  1.2299 +    else
  1.2300 +        {
  1.2301 +        TLex tl(ainp);
  1.2302 +        tl.Val(aint);
  1.2303 +        aint2=-1;
  1.2304 +        }
  1.2305 +    }
  1.2306 +// Looking for, e.g, "9876,some words"
  1.2307 +void CSQLFnStep::CommaSeparated(const TPtrC& ainp, TInt &aint, TPtrC &astr)
  1.2308 +    {
  1.2309 +//    _LIT(KTestFunction, "CommaSeparated");
  1.2310 +
  1.2311 +    TInt origlen = ainp.Length();
  1.2312 +    TChar comma(',');
  1.2313 +    TInt comoffset = ainp.Locate(comma);
  1.2314 +    if(comoffset != KErrNotFound)
  1.2315 +        {
  1.2316 +        TPtrC left = ainp.Left(comoffset);
  1.2317 +        TLex tl(left);
  1.2318 +        tl.Val(aint);
  1.2319 +        TInt rightlen = origlen - comoffset - 1;
  1.2320 +        astr.Set(ainp.Right(rightlen));
  1.2321 +        }
  1.2322 +    else
  1.2323 +        {
  1.2324 +        TLex tl(ainp);
  1.2325 +        tl.Val(aint);
  1.2326 +        astr.Set(_L(""));
  1.2327 +        }
  1.2328 +    }
  1.2329 +void CSQLFnStep::CommaSeparated(const TPtrC& ainp, TPtrC &aleft, TPtrC &aright)
  1.2330 +    {
  1.2331 +//    _LIT(KTestFunction, "CommaSeparated");
  1.2332 +    aleft.Set(ainp);
  1.2333 +    aright.Set(_L(""));
  1.2334 +
  1.2335 +    TInt origlen = ainp.Length();
  1.2336 +    TChar comma(',');
  1.2337 +    TInt comoffset = ainp.Locate(comma);
  1.2338 +    if(comoffset != KErrNotFound)
  1.2339 +        {
  1.2340 +        aleft.Set(ainp.Left(comoffset));
  1.2341 +        TInt rightlen = origlen - comoffset - 1;
  1.2342 +        aright.Set(ainp.Right(rightlen));
  1.2343 +        }
  1.2344 +    else
  1.2345 +        return;
  1.2346 +    }
  1.2347 +TInt CSQLFnStep::FileSize(const TPtrC &afile)
  1.2348 +    {
  1.2349 +    // First open the file specified in the argument.
  1.2350 +    // This lot gets duplicated a lot.
  1.2351 +    RFile file;
  1.2352 +    TFileName fn = afile;
  1.2353 +    TInt err;
  1.2354 +    if((err = file.Open(irfs, fn, 0)) != KErrNone)
  1.2355 +        {
  1.2356 +        INFO_PRINTF1(HTML_RED);
  1.2357 +        ERR_PRINTF3(_L("Cannot open %S to get filesize, err %d"), &afile, err);
  1.2358 +        SetTestStepResult(EFail);
  1.2359 +        INFO_PRINTF1(HTML_COLOUR_OFF);
  1.2360 +
  1.2361 +        return err;
  1.2362 +        }
  1.2363 +    TInt fsize;
  1.2364 +    file.Size(fsize);
  1.2365 +    file.Close();
  1.2366 +    return fsize;
  1.2367 +    }
  1.2368 +