//--------------------------------------------------------------------------- #pragma warn -com #include #pragma warn +com #include #pragma hdrstop #include "time.h" #include "pcreposix.h" #include "About.h" #include "DataModule.h" #include "DefinedVariable.h" #include "DefinedVariableTable.h" #include "EvaluationContext.h" #include "FieldExpression.h" #include "FileCtrl.hpp" #include "GenerationProperties.h" #include "ICryptographicServerProxy.h" #include "IHash.h" #include "InitProgress.h" #include "IMessageDigest.h" #include "ISecurityWrapperFactory.h" #include "Iteration.h" #include "IXmlSchemaWrapperElement.h" #include "Login.h" #include "Main.h" #include "ParameterScope.h" #include "Registry.hpp" #include "ScenarioParameters.h" #include "Sequence.h" #include "SequenceCollection.h" #include "TestScenario.h" #include "TestScenarioProperties.h" #include "TestScenarioTemplate.h" #include "TimeEstimate.h" #include "TransactionFieldTemplate.h" #include "TransactionConfig.h" #include "TransactionSpecification.h" #include "TransactionSpecificationValue.h" #include "TransactionSpecificationValueKey.h" #include "TransactionStream.h" #include "TransactionTemplateCollection.h" #include "Utilities.h" #include #include //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "Grids_ts" #pragma link "TSDBGrid" #pragma link "TSGrid" #pragma link "TXMLSchema" #pragma link "AdvGrid" #pragma link "BaseGrid" #pragma link "DBAdvGrd" #pragma link "DBAdvNavigator" #pragma link "AdvPageControl" #pragma link "AsgFindDialog" #pragma link "DBAdvGrd" #pragma link "DBAdvGrid" #pragma resource "*.dfm" TMainForm *MainForm; #define TDBADVGRID_FIXED 0 #define INCLUDE_PARENTS TDBADVGRID_FIXED const char *TMainForm::g_headerStructure = "SysHdr_t"; const int TMainForm::g_messagePanel = 0; /** * Process paint message. */ void ProcessPaintMessages( HWND Handle ) { MSG msg; while ( PeekMessage( &msg, Handle, WM_PAINT, WM_PAINT, PM_REMOVE ) ) { DispatchMessage( &msg ); } } //--------------------------------------------------------------------------- const bool __fastcall TMainForm::openSecurityFactory( const char * library ) { STARTUPINFO si; PROCESS_INFORMATION pi; memset (&pi, 0, sizeof(pi)); memset (&si, 0, sizeof(si)); si.cb = sizeof(si); si.dwFlags |=STARTF_USESHOWWINDOW; si.wShowWindow|=SW_SHOWNORMAL; if ( ! CreateProcess( "C:\\WINDOWS\\system32\\cmd.exe ", "/c C:..\\..\\ERGsec\\scripts\\exprc_cryptoserver.bat" , NULL, NULL, true, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) { MessageBox(0, "Could not launch crypto server. \n The UD will not have a proper MAC.", "Error", MB_ICONSTOP); } #if 0 else { AnsiString message; message.sprintf("process id is %d ", pi.dwProcessId); MessageDlg(message, mtError, TMsgDlgButtons() << mbOK, 0) ; } #endif m_securityWrapper = ::LoadLibrary( library ); if ( m_securityWrapper ) { m_getSecurityWrapperFactory = reinterpret_cast< getSecurityWrapperFactory_t >( ::GetProcAddress( m_securityWrapper, "getSecurityWrapperFactory" ) ); if ( m_getSecurityWrapperFactory ) { m_securityWrapperFactory = &m_getSecurityWrapperFactory(); if ( m_securityWrapperFactory ) { return ( m_securityWrapperFactory->start() ); } } } return ( false ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::closeSecurityFactory() { if ( m_securityWrapperFactory ) { m_securityWrapperFactory->stop(); m_securityWrapperFactory = 0; } m_getSecurityWrapperFactory = 0; if ( m_securityWrapper ) { ::FreeLibrary( m_securityWrapper ); m_securityWrapper = 0; } } //--------------------------------------------------------------------------- __fastcall TMainForm::TMainForm(TComponent* Owner) : TForm(Owner), m_progressBar( 0 ), m_securityWrapper( 0 ), m_getSecurityWrapperFactory( 0 ), m_securityWrapperFactory( 0 ), //m_transferManager( 0 ), m_Registry( 0 ), m_currentiteration (25), m_currentproject("SLS") { //TestCasesTabSheet->TabVisible = false; //TestScenariosTabSheet->TabVisible = false; m_Registry = new TRegistry; m_Registry->RootKey = HKEY_CURRENT_USER; if (! m_Registry->OpenKey("\\Software\\ERG\\TxnTestManager", true) ) { m_Registry->CloseKey(); delete m_Registry; m_Registry = NULL; } else { // read in project from the registry if (m_Registry->ValueExists("MRUProjectCode")) { m_currentproject = m_Registry->ReadString("MRUProjectCode"); } // read in iteration from the registry if (m_Registry->ValueExists("MRUProjectIteration")) { m_currentiteration = m_Registry->ReadInteger("MRUProjectIteration"); } } m_progressBar = new ProgressBar( MainStatusBar ); /* eventually get this from the registry */ m_engineering_mode = true; openSecurityFactory(); } //--------------------------------------------------------------------------- __fastcall TMainForm::~TMainForm() { closeSecurityFactory(); delete m_progressBar; m_progressBar = 0; //delete m_transferManager; //m_transferManager = 0; delete m_Registry; m_Registry = 0; } //--------------------------------------------------------------------------- void __fastcall TMainForm::FormShow(TObject *Sender) { #ifdef LOGGING_ACTIVE ProgrammerLogging::start("TxnTestManager.ini"); #endif bool retryLogin; do { retryLogin = false; if (LoginForm->ShowModal() == mrOk) { try { // Initialise Startup TabSheets TestsPageControl->ActivePage = TestCaseTabSheet; TestParametersPageControl->ActivePage = IterationParametersTabSheet; // Initialise the Database connection Data_Module->IntegrationDBConnection->Connected = false; AnsiString connectionString; connectionString.sprintf( "Provider=OraOLEDB.Oracle.1;Data Source=%s", LoginForm->DatabaseEdit->Text ); Data_Module->IntegrationDBConnection->ConnectionString = connectionString; Data_Module->IntegrationDBConnection->Open(LoginForm->UsernameEdit->Text, LoginForm->PasswordEdit->Text); if (!Data_Module->IntegrationDBConnection->Connected) { MessageDlg("Failed to connect to datasource with specified username and password.", mtError, TMsgDlgButtons() << mbOK, 0); retryLogin = true; } else { // we have a databse connection so use it // but first display the database name on the bottom ight hand corner MainStatusBar->Panels->Items[ 2 ]->Alignment = taRightJustify ; MainStatusBar->Panels->Items[ 2 ]->Text = LoginForm->DatabaseEdit->Text + " "; MASSTxnsQuery->Active = false; TestCaseQuery->Active = false; TxnSpecQuery->Active = false; TxnValuesQuery->Active = false; TxnHdrValuesQuery->Active = false; IterationParamsQuery->Active = false; SequenceGeneratorQuery->Active = false; // TxnStepsQuery->Active = true; ?? can't do yet as we don't have a default scenario srand( static_cast< unsigned >( time( 0 ) ) ); int first_rand_seed = rand(); srand( first_rand_seed << (first_rand_seed & 0x00FF) ); // int first_rand = rand(); // Locate the XML SWIS Schema XMLSchema->Active = true; vector schemas; if (XMLSchema->GetSchemas(schemas)) { vector::iterator itr = schemas.begin(); while (itr != schemas.end()) { AnsiString xml_schema = (*itr).c_str(); if (xml_schema.Pos(MASSUDWriter) == 1) { m_xml_schemas.push_back(xml_schema.c_str()); } ++itr; } } if (m_xml_schemas.size() == 0) { MessageDlg("Failed to locate any MASS UD Writer XMLs\n" "Check XMLSchema.ini file", mtError, TMsgDlgButtons() << mbOK, 0); } // use the iteration held in the registry to complete the preparation for the form LoadIteration(Sender); bool allow; TestCaseGridRowChanging(Sender, 0, 1, allow = true ); MASSTxnTabSheet->Visible = false; //InitialiseUdTransferManager(); } } catch( EOleException & e ) { AnsiString msg = "Failed to connect to datasource with specified username and password.\n" + e.Message + "."; MessageDlg(msg, mtError, TMsgDlgButtons() << mbOK, 0); retryLogin = true; } catch(...) { Close(); } } else { Close(); } } while( retryLogin ); } //--------------------------------------------------------------------------- const bool __fastcall TMainForm::findSchema( std::string & handle, const AnsiString & projectCode, const int & iteration ) { std::string project; std::string majorVersion; for ( std::vector< std::string >::const_iterator where = m_xml_schemas.begin(); where != m_xml_schemas.end(); ++where ) { if ( XMLSchema->GetAttributeProperty( *where, "project", project ) && ( projectCode == AnsiString( project.c_str() ).UpperCase() ) ) { if ( ( XMLSchema->GetAttributeProperty( *where, "majorversion", majorVersion ) ) && ( iteration == atoi( majorVersion.c_str() ) ) ) { handle = *where; return ( true ); } } } handle.erase(); return ( false ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::LoadIteration(TObject *Sender) { AnsiString sql_statement; if (!findSchema( m_schema_handle, m_currentproject.UpperCase(), m_currentiteration )) { AnsiString message; message.sprintf("Failed to match project %s and iteration %d in schema xml file", m_currentproject, m_currentiteration); MessageDlg(message, mtError, TMsgDlgButtons() << mbOK, 0); } buildTransactionTemplates( m_transactionTemplates, m_currentproject, m_currentiteration ); ApplyTemplates->Enabled = ( m_transactionTemplates.getTemplateCount() > 0 ); // Load the Project/Iterations MASS Txns MASSTxnsQuery->Close(); sql_statement=""; sql_statement.sprintf("SELECT * FROM MASS_TXNS WHERE PROJECTCODE='%s' AND ITERATION=%d AND ENABLED = 'Y' ORDER BY NAME,UDTYPE,UDSUBTYPE", m_currentproject.c_str(), m_currentiteration); MASSTxnsQuery->SQL->Text = sql_statement; MASSTxnsQuery->Open(); InitialiseMASSTxns(); // Refresh the TestCases if (TestCaseQuery->Active) { TestCaseQuery->Close(); } TestCaseQuery->Open(); // Load the Project/Iterations Iteration Parameters IterationParamsQuery->Close(); sql_statement=""; sql_statement.sprintf("SELECT * FROM ITERATION_PARAMS " "WHERE PROJECT_CODE='%s' AND ITERATION=%d" "AND TESTSCENARIO_NO IS NULL AND SUPPORTED <> 0" "ORDER BY NAME", m_currentproject.c_str(), m_currentiteration); IterationParamsQuery->SQL->Text = sql_statement; IterationParamsQuery->Open(); SequenceGeneratorQuery->Close(); sql_statement=""; sql_statement.sprintf("SELECT * FROM SEQGEN " "WHERE PROJECT_CODE='%s' AND ITERATION=%d" "ORDER BY SEQNAME", m_currentproject.c_str(), m_currentiteration); SequenceGeneratorQuery->SQL->Text = sql_statement; SequenceGeneratorQuery->Open(); #if 0 // TxnHdr not supported in TSB // Load the Project/Iterations TXNHDR Parameters TxnHdrValuesQuery->Close(); sql_statement=""; sql_statement.sprintf("SELECT * FROM TXNHDR_VALUES " "WHERE PROJECT_CODE='%s' AND ITERATION=%d", m_currentproject.c_str(), m_currentiteration); TxnHdrValuesQuery->SQL->Text = sql_statement; TxnHdrValuesQuery->Open(); #endif } //--------------------------------------------------------------------------- void __fastcall TMainForm::LoadTestCaseNodes(TTreeNode *testcase_node) { bool initially_expanded = testcase_node->Expanded; TestCaseTreeView->Items->BeginUpdate(); testcase_node->DeleteChildren(); TADOQuery *txnquery = new TADOQuery(this); txnquery->Connection = Data_Module->IntegrationDBConnection; AnsiString sql_statement; sql_statement.sprintf("SELECT MASS_TXNS.NAME,TRANSACTION_SPECIFICATION.TXNSPEC_NO " "FROM MASS_TXNS,TRANSACTION_SPECIFICATION " "WHERE TRANSACTION_SPECIFICATION.TESTSCENARIO_NO=%d " "AND MASS_TXNS.PROJECTCODE=TRANSACTION_SPECIFICATION.PROJECT_CODE " "AND MASS_TXNS.ITERATION=TRANSACTION_SPECIFICATION.ITERATION " "AND MASS_TXNS.UDTYPE=TRANSACTION_SPECIFICATION.UDTYPE " "AND MASS_TXNS.UDSUBTYPE=TRANSACTION_SPECIFICATION.UDSUBTYPE " "ORDER BY TRANSACTION_SPECIFICATION.SEQ_NO", (int)testcase_node->Data); txnquery->SQL->Text = sql_statement; txnquery->Open(); while (!txnquery->Eof) { AnsiString txnname = txnquery->FieldByName("NAME")->AsString; int txnspec_no = txnquery->FieldByName("TXNSPEC_NO")->AsInteger; TestCaseTreeView->Items->AddChildObject(testcase_node, txnname.c_str(), (TObject *)txnspec_no); txnquery->Next(); } delete txnquery; if (initially_expanded) { testcase_node->Expand(true); } /* else { testcase_node->Collapse(true); } */ TestCaseTreeView->Items->EndUpdate(); } //--------------------------------------------------------------------------- void __fastcall TMainForm::EditTestCaseExecute(TObject *Sender) { // } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseTreeViewEnter(TObject *Sender) { // if (!TestScenariosTabSheet->TabVisible) // { // TestScenariosTabSheet->TabVisible = true; // TestCasesTabSheet->TabVisible = false; // } // MainPageControl->ActivePage = ScenarioStepsTabSheet; } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseQueryAfterPost(TDataSet *DataSet) { if (TestCaseQuery->Active) { TestCaseQuery->Close(); } TestCaseQuery->Open(); } //--------------------------------------------------------------------------- void __fastcall TMainForm::TxnStepsQueryAfterPost(TDataSet *DataSet) { /* This routine was added to copy the exisiting TestCaseQuery behaviour but I am not sure if it is needed. */ // if (TxnStepsQuery->Active) // { // TxnStepsQuery->Close(); // } // TxnStepsQuery->Open(); // MainStatusBar->Panels->Items[ g_messagePanel ]->Text = "posting txn steps"; // Application->ProcessMessages(); } //--------------------------------------------------------------------------- void __fastcall TMainForm::TxnStepsNewRow(TDataSet *DataSet) { /* AnsiString message; message = "Record " + IntToStr(TxnStepsQuery->RecNo) + " of " + IntToStr(TxnStepsQuery->RecordCount); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); */ } //--------------------------------------------------------------------------- void __fastcall TMainForm::StepsGridNewRow (TObject *Sender, int ARow) { /* AnsiString message; message = "new grid row at " + IntToStr(ARow); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); */ } //--------------------------------------------------------------------------- void __fastcall TMainForm::StepsGridRowChanging(TObject *Sender, int OldRow, int NewRow, bool &Allow) { /* AnsiString message; message = "chnaged grid row at " + IntToStr(NewRow); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); //Application->MessageBox(message.c_str(),"hello box",NULL); */ // TestCaseGridRowChanging(Sender, 0, 1, Allow); } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- void __fastcall TMainForm::loadLegacyParameters( TransactionTemplateCollection & templates, const AnsiString & project, const int & iteration ) { TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "NAME," "FIELDVALUE," "TESTSCENARIO_NO " "FROM " "ITERATION_PARAMS " "WHERE " "PROJECT_CODE=\'%s\' AND " "ITERATION=%d ", project.c_str(), iteration ); query->SQL->Text = sqlStatement; query->Open(); AnsiString fieldName; int scenario = 0; AnsiString xpath; AnsiString value; while ( !query->Eof ) { fieldName = query->FieldByName( "NAME" )->AsString; scenario = query->FieldByName( "TESTSCENARIO_NO" )->AsInteger; value = query->FieldByName( "FIELDVALUE" )->AsString; if ( !value.IsEmpty() ) { if ( value[ 1 ] == '=' ) { value.Delete( 1, 1 ); } if ( !value.IsEmpty() ) { switch ( value[ 1 ] ) { case '@': value[ 1 ] = '='; if ( FieldExpression::isFunctor( value.c_str() + 1 ) ) { value += "()"; } break; default: break; } } } if ( !fieldName.IsEmpty() ) { switch ( fieldName[ 1 ] ) { case '$': xpath.sprintf( ".*/%s", fieldName.c_str() + 1 ); templates.getTestScenario( scenario ).getField( xpath.c_str() ). setValue( value.c_str() ); break; case '@': // We don't worry about variables here. break; default: break; } } query->Next(); } } __finally { delete query; query = 0; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::buildTransactionTemplates( TransactionTemplateCollection & templates, const AnsiString & project, const int & iteration ) { templates.clear(); //loadLegacyHeaderValues( templates, project, iteration ); loadLegacyParameters( templates, project, iteration ); // Now apply our current templates, which override the legacy templates. /* KI note: it seems that the 'legacy' routines are in fact the real thing and the comment above is no longer appropriate. Only guessing though at this stage. If it turns out to be the case then I'll rename the legacy routines accordingly */ } //--------------------------------------------------------------------------- void __fastcall TMainForm::UseCaseDBGridEnter(TObject *Sender) { // TestCasesTabSheet->TabVisible = true; // ScenarioStepsTabSheet->TabVisible = true; MainPageControl->ActivePage = ScenarioStepsTabSheet; // TestScenariosTabSheet->TabVisible = false; // TestScenariosTabSheet->Enabled = false; } //--------------------------------------------------------------------------- void __fastcall TMainForm::IterationParamsQueryAfterInsert( TDataSet *DataSet) { DataSet->FieldByName("PROJECT_CODE")->AsString = m_currentproject; DataSet->FieldByName("ITERATION")->AsInteger = m_currentiteration; } //--------------------------------------------------------------------------- void __fastcall TMainForm::readTransactionSpecifications( TransactionSpecification & transaction, const int & transactionSpecification ) { TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "XPATH," "FIELDVALUE," "OBSOLETE " "FROM " "TXNSPEC_VALUES " "WHERE " "TXNSPEC_NO=%d", transactionSpecification ); query->SQL->Text = sqlStatement; query->Open(); while ( !query->Eof ) { transaction.addValue( query->FieldByName( "XPATH" )->AsString.c_str(), query->FieldByName( "FIELDVALUE" )->AsString.c_str(), query->FieldByName( "OBSOLETE" )->AsBoolean ); query->Next(); } } __finally { delete query; query = 0; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::buildTransactionsForIteration( TransactionCache & transactionCache, ProgressBar & progressBar, const std::string & schema, const std::string & project, const int & iteration ) { TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "TXNSPEC_NO," "NAME," "TESTSCENARIO_NO " "FROM " "TRANSACTION_SPECIFICATION," "MASS_TXNS " "WHERE " "TRANSACTION_SPECIFICATION.PROJECT_CODE=\'%s\' AND " "TRANSACTION_SPECIFICATION.ITERATION=%d AND " "TRANSACTION_SPECIFICATION.PROJECT_CODE = MASS_TXNS.PROJECTCODE AND " "TRANSACTION_SPECIFICATION.ITERATION = MASS_TXNS.ITERATION AND " "TRANSACTION_SPECIFICATION.UDTYPE = MASS_TXNS.UDTYPE AND " "TRANSACTION_SPECIFICATION.UDSUBTYPE = MASS_TXNS.UDSUBTYPE " "ORDER BY " "TESTSCENARIO_NO," "TXNSPEC_NO", project.c_str(), iteration ); query->SQL->Text = sqlStatement; query->Open(); AnsiString xpath; AnsiString message; while ( !query->Eof ) { if ( !m_transactionCache.isContained( query->FieldByName( "TXNSPEC_NO" )->AsInteger ) ) { message.sprintf( " Building %s ...", query->FieldByName( "NAME" )->AsString.c_str() ); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); buildTransactionSpecificationValues( transactionCache, query->FieldByName( "TESTSCENARIO_NO" )->AsInteger, query->FieldByName( "TXNSPEC_NO" )->AsInteger, query->FieldByName( "NAME" )->AsString.c_str(), g_headerStructure, schema, iteration ); } else { message.sprintf( " Using cached %s ...", query->FieldByName( "NAME" )->AsString.c_str() ); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); } progressBar.increment(); query->Next(); } } __finally { delete query; query = 0; MainStatusBar->Panels->Items[ g_messagePanel ]->Text = ""; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::buildTransactionsForScenario( TransactionCache & transactionCache, ProgressBar & progressBar, const int & scenario, const std::string & schema, const int & iteration ) { TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "TXNSPEC_NO," "NAME " "FROM " "TRANSACTION_SPECIFICATION," "MASS_TXNS " "WHERE " "TRANSACTION_SPECIFICATION.TESTSCENARIO_NO=%d AND " "TRANSACTION_SPECIFICATION.PROJECT_CODE = MASS_TXNS.PROJECTCODE AND " "TRANSACTION_SPECIFICATION.ITERATION = MASS_TXNS.ITERATION AND " "TRANSACTION_SPECIFICATION.UDTYPE = MASS_TXNS.UDTYPE AND " "TRANSACTION_SPECIFICATION.UDSUBTYPE = MASS_TXNS.UDSUBTYPE " "ORDER BY " "TXNSPEC_NO", scenario ); query->SQL->Text = sqlStatement; query->Open(); AnsiString xpath; AnsiString message; while ( !query->Eof ) { if ( !m_transactionCache.isContained( query->FieldByName( "TXNSPEC_NO" )->AsInteger ) ) { message.sprintf( " Building %s ...", query->FieldByName( "NAME" )->AsString.c_str() ); buildTransactionSpecificationValues( transactionCache, scenario, query->FieldByName( "TXNSPEC_NO" )->AsInteger, query->FieldByName( "NAME" )->AsString.c_str(), g_headerStructure, schema, iteration ); } else { message.sprintf( " Using cached %s ...", query->FieldByName( "NAME" )->AsString.c_str() ); } MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); progressBar.increment(); query->Next(); } } __finally { delete query; query = 0; MainStatusBar->Panels->Items[ g_messagePanel ]->Text = ""; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::buildTransactionSpecificationValues( TransactionCache & transactionCache, const int & testScenario, const int & transactionSpecification, const std::string & transactionStructureName, const std::string & headerStructureName, const std::string & schema, const int & iteration ) { /** * Ensure that for each transactionSpecification and iteration we do this * only on startup and whenever we import a schema. */ int ordinal = 0; TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; std::string structureHandle; std::string headerHandle; try { if ( XMLSchema->Create( schema.c_str(), transactionStructureName.c_str(), iteration, structureHandle, 0 ) ) { if ( XMLSchema->Create( schema.c_str(), headerStructureName.c_str(), iteration, headerHandle, 0 ) ) { try { // KI note. this txn had to be lost as there was an overlapping txn in progress // Data_Module->IntegrationDBConnection->BeginTrans(); TransactionSpecification & transaction = transactionCache.getTransactionSpecification( transactionSpecification ); readTransactionSpecifications( transaction, transactionSpecification ); buildTransactionSpecificationValues( *query, transactionStructureName, testScenario, transactionSpecification, structureHandle, ordinal = 0, transaction ); buildTransactionSpecificationValues( *query, headerStructureName, testScenario, transactionSpecification, headerHandle, ordinal = 0, transaction ); // Data_Module->IntegrationDBConnection->CommitTrans(); } catch ( const std::exception & exception ) { std::stringstream stream; stream << "Cannot build transaction specification values for \"" \ << transactionStructureName \ << "\". " \ << exception.what(); MessageDlg( stream.str().c_str(), mtError, TMsgDlgButtons() << mbOK, 0 ); transactionCache.deleteTransactionSpecification( transactionSpecification ); // Data_Module->IntegrationDBConnection->RollbackTrans(); // see comment above } catch ( ... ) { std::stringstream stream; stream << "Cannot build transaction specification values for \"" \ << transactionStructureName \ << "\"."; MessageDlg( stream.str().c_str(), mtError, TMsgDlgButtons() << mbOK, 0 ); transactionCache.deleteTransactionSpecification( transactionSpecification ); // Data_Module->IntegrationDBConnection->RollbackTrans(); // see comment above throw; } } else { std::stringstream stream; stream << "Cannot create structure \"" << headerStructureName << "\" for iteration " << iteration << ". Is \"" << XMLSchema->Profile.c_str() << "\" configured correctly?"; MessageDlg( stream.str().c_str(), mtError, TMsgDlgButtons() << mbOK, 0 ); } } else { std::stringstream stream; stream << "Cannot create structure \"" << transactionStructureName << "\" for iteration " << iteration << ". Is \"" << XMLSchema->Profile.c_str() << "\" configured correctly?"; MessageDlg( stream.str().c_str(), mtError, TMsgDlgButtons() << mbOK, 0 ); } } __finally { XMLSchema->Destroy( headerHandle ); XMLSchema->Destroy( structureHandle ); } } __finally { delete query; query = 0; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::buildTransactionSpecificationFieldValue( TADOQuery & query, const std::string & rootStructure, const std::string & fieldHandle, const int & testScenario, const int & transactionSpecification, int & ordinal, const & childCount, TransactionSpecification & transactions, const int & subscript ) { std::string tagValue; // If we get a tag, then use it. Otherwise, tough luck. if ( !XMLSchema->GetAttributeProperty( fieldHandle, "tag", tagValue ) || tagValue.length() > 0 ) { std::string fieldName; std::string xPath; if ( XMLSchema->GetAttributeProperty( fieldHandle, "name", fieldName ) && XMLSchema->GetAttributeProperty( fieldHandle, "xpath", xPath ) ) { /** * Build the full xpath as the schema reports only the path * relative to the root structure. */ const std::string fullXPath = "/" + rootStructure + xPath; AnsiString displayName; if ( !subscript ) { displayName = fieldName.c_str(); } else { #if TDBADVGRID_FIXED displayName.sprintf( "[%d]", subscript ); #else displayName.sprintf( "%s[%d]", fieldName.c_str(), subscript ); #endif } /** * Work out whether we have to insert or update, and whether we * have to migrate or not. */ bool insert = false; bool migrate = false; if ( transactions.isContained( fullXPath ) ) { insert = false; migrate = false; } else { if ( transactions.isContained( xPath ) ) { insert = false; migrate = true; } else { insert = true; migrate = false; } } /** * We now assert this value into the database. */ std::stringstream stream; if ( !insert ) { if ( !migrate ) { stream << "UPDATE TXNSPEC_VALUES SET " << "CHILD_COUNT=" << childCount << ',' << "DISPLAY_FIELDNAME=\'" << Utilities::EscapeString( displayName ).c_str() << "\'," << "FIELDNAME=\'" << Utilities::EscapeString( fieldName ) << "\'," << "FIELDTAG=" << atoi( tagValue.c_str() ) << ',' << "ORDINAL=" << ++ordinal << ',' << "SUBSCRIPT=" << subscript << ',' << "TESTSCENARIO_NO=" << testScenario << " WHERE " << "TXNSPEC_NO=\'" << transactionSpecification << "\' AND " << "XPATH=\'" << fullXPath << '\''; transactions.markValue( fullXPath ); } else { stream << "UPDATE TXNSPEC_VALUES SET " << "CHILD_COUNT=" << childCount << ',' << "DISPLAY_FIELDNAME=\'" << Utilities::EscapeString( displayName ).c_str() << "\'," << "FIELDNAME=\'" << Utilities::EscapeString( fieldName ) << "\'," << "FIELDTAG=" << atoi( tagValue.c_str() ) << ',' << "ORDINAL=" << ++ordinal << ',' << "SUBSCRIPT=" << subscript << ',' << "TESTSCENARIO_NO=" << testScenario << ',' << "XPATH=\'" << fullXPath << '\'' << " WHERE " << "TXNSPEC_NO=\'" << transactionSpecification << "\' AND " << "XPATH=\'" << xPath << '\''; transactions.markValue( xPath ); } } else { stream << "INSERT INTO TXNSPEC_VALUES ( " "TXNSPEC_NO," "XPATH," "CHILD_COUNT," "DISPLAY_FIELDNAME," "FIELDNAME," "FIELDTAG," "OBSOLETE," "ORDINAL," "SUBSCRIPT," "TESTSCENARIO_NO," "USER_SUPPLIED," "DISPLAYABLE" " ) VALUES ( " << transactionSpecification << ",\'" << fullXPath << "\'," << childCount << ",\'" << Utilities::EscapeString( displayName ).c_str() << "\',\'" << Utilities::EscapeString( fieldName ).c_str() << "\'," << atoi( tagValue.c_str() ) << ',' << "\'N\'" << ',' << ++ordinal << ',' << subscript << ',' << testScenario << ',' << "\'N\'" << ',' << "\'N\'" << " )"; } query.SQL->Text = stream.str().c_str(); if ( query.ExecSQL() != 1 ) { MTHROW( std::runtime_error, \ "Cannot update field \"" \ << fullXPath \ << "\" of transaction specification " \ << transactionSpecification \ << '.' ); } } else { MTHROW( std::runtime_error, \ "Cannot get name and xpath for schema element \"" \ << fieldHandle \ << "\"." ); } } else { MTHROW( std::runtime_error, \ "Cannot get tag value for schema element \"" \ << fieldHandle \ << "\". The tag is present but has a zero-length value." ); } } //--------------------------------------------------------------------------- void __fastcall TMainForm::buildTransactionSpecificationRepeatValue( TADOQuery & query, const std::string & rootStructure, const std::string & attribute, const int & testScenario, const int & transactionSpecification, const std::string & transactionStructureHandle, int & ordinal, TransactionSpecification & transactions, const int & repeatLimit ) { std::string refcountField; std::string repeatSize; /** * Find the upper bound of the repeat by looking for the "max" property * of the "refcountfield" (possibly an xPath), and then for our * "maxOccurs" property. */ XMLSchema->GetAttributeProperty( attribute, "refcountfield", refcountField ); if ( refcountField.length() ) { XMLSchema->GetAttributeProperty( transactionStructureHandle + "." + refcountField, "max", repeatSize ); } if ( !repeatSize.length() ) { XMLSchema->GetAttributeProperty( attribute, "maxOccurs", repeatSize ); } if ( repeatSize.length() ) { /** * Now instantiate the array so that we may traverse it, but limit it to * repeatLimit elements. */ const int size = std::min< int >( atoi( repeatSize.c_str() ), repeatLimit ); std::string repeatName; if ( ( refcountField.length() == 0 ) || XMLSchema->SetAttributeValue( transactionStructureHandle, refcountField, size ) ) { if ( XMLSchema->GetAttributeProperty( attribute, "name", repeatName ) ) { AnsiString repeatElement; std::string datatype; repeatElement.sprintf( "%s.1.%s", attribute.c_str(), repeatName.c_str() ); if ( XMLSchema->GetAttributeProperty( repeatElement.c_str(), "datatype", datatype ) ) { const bool isStruct = ( datatype == "Struct" ); buildTransactionSpecificationFieldValue( query, rootStructure, attribute, testScenario, transactionSpecification, ordinal, countChildren( attribute, isStruct ), transactions ); if ( size >= 1 ) { std::string repeatHandle; for ( int where = 1; where <= size; ++where ) { repeatElement.sprintf( "%s.%d.%s", attribute.c_str(), where, repeatName.c_str() ); repeatHandle = repeatElement.c_str(); if ( isStruct ) { buildTransactionSpecificationFieldValue( query, rootStructure, repeatHandle, testScenario, transactionSpecification, ordinal, countChildren( repeatHandle, isStruct ), transactions, where ); buildTransactionSpecificationValues( query, rootStructure, testScenario, transactionSpecification, repeatHandle, ordinal, transactions ); } else { buildTransactionSpecificationFieldValue( query, rootStructure, repeatHandle, testScenario, transactionSpecification, ordinal, 0, transactions, where ); } } } } else { MTHROW( std::runtime_error, \ "Cannot get datatype for schema element \"" \ << repeatElement.c_str() \ << "\"." ); } } else { MTHROW( std::runtime_error, \ "Cannot get name for schema element \"" \ << attribute \ << "\"." ); } } else { MTHROW( std::runtime_error, \ "Cannot set size for schema element \"" \ << transactionStructureHandle + "." + refcountField \ << "\"." ); } } else { MTHROW( std::runtime_error, \ "Cannot get repeat size for schema element \"" \ << attribute \ << "\"." ); } } //--------------------------------------------------------------------------- void __fastcall TMainForm::buildTransactionSpecificationValues( TADOQuery & query, const std::string & rootStructure, const int & testScenario, const int & transactionSpecification, const std::string & transactionStructureHandle, int & ordinal, TransactionSpecification & transactions ) { std::vector< std::string > attributes; if ( XMLSchema->GetAttributes( transactionStructureHandle, attributes ) ) { std::string elementType; for ( std::vector< std::string >::iterator where = attributes.begin(); where != attributes.end(); ++where ) { if ( XMLSchema->GetAttributeProperty( *where, "type", elementType ) ) { std::string elementDatatype; if ( elementType == "field" ) { if ( XMLSchema->GetAttributeProperty( *where, "datatype", elementDatatype ) ) { const isStruct = ( elementDatatype == "Struct" ); buildTransactionSpecificationFieldValue( query, rootStructure, *where, testScenario, transactionSpecification, ordinal, ( isStruct ? countChildren( *where, false ) : 0 ), transactions ); if ( isStruct ) { buildTransactionSpecificationValues( query, rootStructure, testScenario, transactionSpecification, *where, ordinal, transactions ); } } else { MTHROW( std::runtime_error, \ "Cannot get datatype for schema element \"" \ << *where \ << "\"." ); } } else if ( elementType == "repeat" ) { buildTransactionSpecificationRepeatValue( query, rootStructure, *where, testScenario, transactionSpecification, transactionStructureHandle, ordinal, transactions ); } } else { MTHROW( std::runtime_error, \ "Cannot get type for schema element \"" \ << *where \ << "\"." ); } } } else { MTHROW( std::runtime_error, \ "Cannot get attributes for schema element \"" \ << transactionStructureHandle \ << "\"." ); } } //--------------------------------------------------------------------------- const unsigned __fastcall TMainForm::countChildren( const std::string & transactionStructureHandle, const bool & isStructureRepeat ) { unsigned childCount = 0; std::vector< std::string > attributes; if ( XMLSchema->GetAttributes( transactionStructureHandle, attributes ) ) { std::string elementType; std::string elementDatatype; for ( std::vector< std::string >::iterator where = attributes.begin(); where != attributes.end(); ++where ) { if ( XMLSchema->GetAttributeProperty( *where, "type", elementType ) ) { // if ( !isStructureRepeat ) // { ++childCount; // } if ( elementType == "field" ) { if ( XMLSchema->GetAttributeProperty( *where, "datatype", elementDatatype ) ) { if ( elementDatatype == "Struct" ) { childCount += countChildren( *where, false ); } } else { MTHROW( std::runtime_error, \ "Cannot get datatype for schema element \"" \ << *where \ << "\"." ); } } else if ( elementType == "repeat" ) { childCount += countChildren( *where, transactionStructureHandle ); } } else { MTHROW( std::runtime_error, \ "Cannot get type for schema element \"" \ << *where \ << "\"." ); } } } else { MTHROW( std::runtime_error, \ "Cannot get attributes for schema element \"" \ << transactionStructureHandle \ << "\"." ); } return ( childCount ); } //--------------------------------------------------------------------------- const unsigned __fastcall TMainForm::countChildren( const std::string & attribute, const std::string & transactionStructureHandle, const int & repeatLimit ) { unsigned childCount = 0; std::string refcountField; std::string repeatSize; /** * Find the upper bound of the repeat by looking for the "max" property * of the "refcountfield" (possibly an xPath), and then for our * "maxOccurs" property. */ XMLSchema->GetAttributeProperty( attribute, "refcountfield", refcountField ); if ( refcountField.length() ) { XMLSchema->GetAttributeProperty( transactionStructureHandle + "." + refcountField, "max", repeatSize ); } if ( !repeatSize.length() ) { XMLSchema->GetAttributeProperty( attribute, "maxOccurs", repeatSize ); } if ( repeatSize.length() ) { /** * Now instantiate the array so that we may traverse it, but limit it to * repeatLimit elements. */ const int size = std::min< int >( atoi( repeatSize.c_str() ), repeatLimit ); std::string repeatName; if ( ( refcountField.length() == 0 ) || XMLSchema->SetAttributeValue( transactionStructureHandle, refcountField, size ) ) { if ( XMLSchema->GetAttributeProperty( attribute, "name", repeatName ) ) { if ( size >= 1 ) { AnsiString repeatElement; std::string datatype; repeatElement.sprintf( "%s.1.%s", attribute.c_str(), repeatName.c_str() ); if ( XMLSchema->GetAttributeProperty( repeatElement.c_str(), "datatype", datatype ) ) { const isStruct = ( datatype == "Struct" ); for ( int where = 1; where <= size; ++where ) { repeatElement.sprintf( "%s.%d.%s", attribute.c_str(), where, repeatName.c_str() ); if ( !isStruct ) { ++childCount; } else { childCount += countChildren( repeatElement.c_str(), false ) + 1; } } } else { MTHROW( std::runtime_error, \ "Cannot get datatype for schema element \"" \ << repeatElement.c_str() \ << "\"." ); } } } else { MTHROW( std::runtime_error, \ "Cannot get name for schema element \"" \ << attribute \ << "\"." ); } } else { MTHROW( std::runtime_error, \ "Cannot set size for schema element \"" \ << transactionStructureHandle + "." + refcountField \ << "\"." ); } } else { MTHROW( std::runtime_error, \ "Cannot get repeat size for schema element \"" \ << attribute \ << "\"." ); } return ( childCount ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::clearTransactionSpecificationValueTree( TDBAdvGrid & grid ) { #if TDBADVGRID_FIXED grid.RemoveAllNodes(); #endif } //--------------------------------------------------------------------------- const int TMainForm::countChildNodes( TDBAdvGrid & grid, TADOQuery & query, const int & row, const int & rows ) { query.RecNo = row; // Move the cursor to the row we're looking at. int count = 0; const AnsiString parentPath = query.FieldByName( "XPATH" )->AsString; for ( int where = row + 1; where <= rows; ++where ) { query.RecNo = where; if ( parentPath == query.FieldByName( "XPATH" ) ->AsString.SubString( 1, parentPath.Length() ) ) { ++count; } else { break; } } return ( count ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::buildTransactionSpecificationValueTree( TDBAdvGrid & grid, TADOQuery & query ) { #if TDBADVGRID_FIXED grid.BeginUpdate(); const int currentRow = query.RecNo; try { int children = 0; const int rows = query.RecordCount; for ( int where = 1; where <= rows; ++where ) { if ( ( children = countChildNodes( grid, query, where, rows ) ) > 0 ) { grid.AddNode( where, 1 + children ); } } } __finally { grid.ContractAll(); query.RecNo = currentRow; grid.EndUpdate(); } #endif } //--------------------------------------------------------------------------- void __fastcall TMainForm::getParentOrdinals( std::vector< int > & parents ) { TADOQuery * query = 0; try { parents.clear(); query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "ORDINAL " "FROM " "TXNSPEC_VALUES " "WHERE " "TESTSCENARIO_NO=%d AND " "TXNSPEC_NO=%d AND " "CHILD_COUNT > 0", m_testscenario_no, m_txnspec_no ); query->SQL->Text = sqlStatement; query->Open(); while ( !query->Eof ) { parents.push_back( query->FieldByName( "ORDINAL" )->AsInteger ); query->Next(); } } __finally { delete query; query = 0; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::populatePayloadStructureTab( const AnsiString & structure ) { AnsiString sqlStatement; PayloadStructureTabSheet->TabVisible = true; PayloadStructureTabSheet->Caption = structure; TxnValuesQuery->Close(); #if TDBADVGRID_FIXED clearTransactionSpecificationValueTree( *NewPayloadStructureGrid ); #endif sqlStatement.sprintf( "SELECT " "* " "FROM " "TXNSPEC_VALUES " "WHERE " "TESTSCENARIO_NO=%d AND " "TXNSPEC_NO=%d AND " "XPATH LIKE \'/%s/%%\' AND " "DISPLAYABLE = \'Y\' AND " "OBSOLETE=\'N\' " #if !INCLUDE_PARENTS "AND CHILD_COUNT=0 " #endif "ORDER BY " "ORDINAL," "FIELDNAME," "SUBSCRIPT", m_testscenario_no, m_txnspec_no, structure.c_str() ); TxnValuesQuery->SQL->Text = sqlStatement; TxnValuesQuery->Open(); #if TDBADVGRID_FIXED buildTransactionSpecificationValueTree( *NewPayloadStructureGrid, *TxnValuesQuery ); #endif #if INCLUDE_PARENTS getParentOrdinals( m_parents ); #endif } //--------------------------------------------------------------------------- void __fastcall TMainForm::populateHeaderStructureTab( const AnsiString & structure ) { AnsiString sqlStatement; HeaderStructureTabSheet->TabVisible = false; HeaderStructureTabSheet->Caption = structure; TxnHeaderValuesQuery->Close(); sqlStatement.sprintf( "SELECT " "* " "FROM " "TXNSPEC_VALUES " "WHERE " "TESTSCENARIO_NO=%d AND " "TXNSPEC_NO=%d AND " "XPATH LIKE \'/%s/%%\' AND " "OBSOLETE=\'N\' " "ORDER BY " "ORDINAL," "FIELDNAME," "SUBSCRIPT", m_testscenario_no, m_txnspec_no, structure.c_str() ); TxnHeaderValuesQuery->SQL->Text = sqlStatement; TxnHeaderValuesQuery->Open(); } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseTreeViewChange(TObject *Sender, TTreeNode *Node) { TestCaseTreeViewEnter(Sender); AnsiString sql_statement; // Only update when TestCase nodes if (Node->Level == 0) { // ----------------- TEST CASE ----------------- TestCasePanel->Caption = Node->Text; MainPageControl->ActivePage = ScenarioStepsTabSheet; m_testscenario_no = (int)(Node->Data); m_txnspec_no = 0; m_structure_name=""; TxnValuesQuery->Close(); TxnHeaderValuesQuery->Close(); //TransactionStructurePageControl->ActivePage = PayloadStructureTabSheet; //PayloadStructureTabSheet->Caption = "Payload Structure"; //HeaderStructureTabSheet->Caption = "Header Structure"; //HeaderStructureTabSheet->TabVisible = false; m_parents.clear(); /* TxnStepsQuery->Close(); sql_statement=""; sql_statement.sprintf("SELECT TESTCASE_SEQNO, NAME, REPEAT_COUNT, DESCRIPTION " "FROM TEST_SCENARIOS " "WHERE TESTCASE_ID = \'%s\' " "ORDER BY TESTCASE_SEQNO", m_currenttestcaseid); TxnStepsQuery->SQL->Text = sql_statement; TxnStepsQuery->Open(); TxnStepsQuery->Edit(); */ // --------------------------------------------- } else if (Node->Level == 1) { // ---------------- TRANSACTION ---------------- TestCasePanel->Caption = Node->Parent->Text; MainPageControl->ActivePage = TestScenariosTabSheet; m_testscenario_no = (int)(Node->Parent->Data); m_txnspec_no = (int)(Node->Data); m_structure_name = Node->Text.c_str(); TransactionStructurePageControl->ActivePage = PayloadStructureTabSheet; if ( !m_transactionCache.isContained( m_txnspec_no ) ) { const TCursor Save_Cursor = Screen->Cursor; try { Screen->Cursor = crHourGlass; AnsiString message; message.sprintf( " Building %s ...", Node->Text.c_str() ); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); buildTransactionSpecificationValues( m_transactionCache, m_testscenario_no, m_txnspec_no, Node->Text.c_str(), g_headerStructure, m_schema_handle, m_currentiteration ); } __finally { Screen->Cursor = Save_Cursor; } } MainStatusBar->Panels->Items[ g_messagePanel ]->Text = ""; populateHeaderStructureTab( g_headerStructure ); populatePayloadStructureTab( Node->Text ); // if (TxnStepsQuery->State == dsEdit) TxnStepsQuery->Post(); // TxnStepsQuery->Close(); /* sql_statement=""; sql_statement.sprintf("SELECT TESTCASE_SEQNO, NAME, REPEAT_COUNT, DESCRIPTION FROM TEST_SCENARIOS " "WHERE TESTCASE_ID = \'%s\' " "ORDER BY TESTCASE_SEQNO", m_currenttestcaseid); TxnStepsQuery->SQL->Text = sql_statement; */ // if(!TxnStepsQuery->Active) // { // TxnStepsQuery->Open(); // TxnStepsQuery->Edit(); // } // --------------------------------------------- } } //--------------------------------------------------------------------------- void __fastcall TMainForm::NewTransactionActionExecute(TObject *Sender) { TTreeNode *current_node = TestCaseTreeView->Selected; if (current_node != NULL) { if (current_node->Level == 0) // Add Txn { AnsiString testcase_text = current_node->Text; int testscenario_no = (int)(current_node->Data); if ( TxnConfig->ShowForm(m_currentproject, m_currentiteration, testcase_text) == true) { TxnSpecQuery->Close(); const TCursor Save_Cursor = Screen->Cursor; TADOQuery * query = new TADOQuery(this); AnsiString sql_statement; query->Connection = Data_Module->IntegrationDBConnection; /* prepare to apply templates to new transaction(s) */ TestScenarioTemplate * all = m_transactionTemplates.findTestScenarioTemplate( 0 ); TADOQuery * txn_query = new TADOQuery(this); txn_query->Connection = Data_Module->IntegrationDBConnection; try { /* could not make atomic as buildtxnspecvalues has a transaction */ //Data_Module->IntegrationDBConnection->BeginTrans(); sql_statement=""; sql_statement.sprintf("SELECT MAX(SEQ_NO) AS MAXSEQ_NO " "FROM TRANSACTION_SPECIFICATION " "WHERE PROJECT_CODE='%s' AND ITERATION=%d AND TESTSCENARIO_NO=%d", m_currentproject.c_str(), m_currentiteration, testscenario_no); query->SQL->Text = sql_statement; query->Open(); int seq_no = query->FieldByName("MAXSEQ_NO")->AsInteger; seq_no++; vector selected_txns = TxnConfig->getSelectedTxns(); vector::iterator selected_txn_itr = selected_txns.begin(); const unsigned count = selected_txns.end() - selected_txns.begin() + 1; m_progressBar->open( count * 2 ); Screen->Cursor = crHourGlass; AnsiString message; message.sprintf(" Building %d new transactions ...", count ); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); while (selected_txn_itr != selected_txns.end()) { unsigned int txnindex = (*selected_txn_itr); unsigned short udtype = txnindex >> 16; unsigned short udsubtype = txnindex & 0xffff; AnsiString txnname = ""; sql_statement=""; sql_statement.sprintf("INSERT INTO TRANSACTION_SPECIFICATION " "(PROJECT_CODE,ITERATION,TESTSCENARIO_NO,UDTYPE,UDSUBTYPE,SEQ_NO) " "VALUES ('%s',%d,%d,%d,%d,%d) ", m_currentproject.c_str(), m_currentiteration, testscenario_no, udtype, udsubtype, seq_no); query->SQL->Text = sql_statement; query->ExecSQL(); // now we have created the new transaction we can get its primary key ansd apply the template sql_statement=""; sql_statement.sprintf("SELECT MASS_TXNS.NAME,TRANSACTION_SPECIFICATION.TXNSPEC_NO " "FROM MASS_TXNS,TRANSACTION_SPECIFICATION " "WHERE TRANSACTION_SPECIFICATION.TESTSCENARIO_NO = %d " "AND TRANSACTION_SPECIFICATION.ITERATION = %d" "AND MASS_TXNS.PROJECTCODE=TRANSACTION_SPECIFICATION.PROJECT_CODE " "AND MASS_TXNS.ITERATION=TRANSACTION_SPECIFICATION.ITERATION " "AND MASS_TXNS.UDTYPE=TRANSACTION_SPECIFICATION.UDTYPE " "AND MASS_TXNS.UDSUBTYPE=TRANSACTION_SPECIFICATION.UDSUBTYPE " "AND TRANSACTION_SPECIFICATION.UDTYPE = %d " "AND TRANSACTION_SPECIFICATION.UDSUBTYPE = %d " "AND TRANSACTION_SPECIFICATION.SEQ_NO = %d ", testscenario_no, m_currentiteration, udtype, udsubtype, seq_no); txn_query->SQL->Text = sql_statement; txn_query->Open(); txnname = txn_query->FieldByName( "NAME" )->AsString; m_txnspec_no = txn_query->FieldByName( "TXNSPEC_NO" )->AsInteger; // create txn spec values buildTransactionSpecificationValues( m_transactionCache, m_testscenario_no, m_txnspec_no, txnname.c_str(), g_headerStructure, m_schema_handle, m_currentiteration ); // now apply template applyTemplatesToNewTransaction( m_txnspec_no, all); txn_query->Close(); m_progressBar->increment(); seq_no++; selected_txn_itr++; } //Data_Module->IntegrationDBConnection->CommitTrans(); //see comment above } catch(...) { //Data_Module->IntegrationDBConnection->RollbackTrans(); //see comment above } MainStatusBar->Panels->Items[ g_messagePanel ]->Text = ""; Screen->Cursor = Save_Cursor; delete query; TxnSpecQuery->Open(); LoadTestCaseNodes(current_node); current_node->Expand(true); } } } } //--------------------------------------------------------------------------- void __fastcall TMainForm::DeleteTransactionActionExecute(TObject *Sender) { bool refresh_testcases = false; for (unsigned selected_item=0; selected_itemSelectionCount; selected_item++) { TTreeNode *current_node = TestCaseTreeView->Selections[selected_item]; if (current_node!= NULL) { if (current_node->Level == 1) // Remove Test Case Transaction { // Confirm deletion AnsiString message; message.sprintf( "Are you sure you want to delete transaction '%s'?", current_node->Text ); if ( MessageDlg( message, mtConfirmation, TMsgDlgButtons() << mbYes << mbNo, 0 ) == mrYes ) { int testscenario_no = (int)(current_node->Parent->Data); int txnspec_no = (int)(current_node->Data); TADOQuery *query = new TADOQuery(this); AnsiString sql_statement; query->Connection = Data_Module->IntegrationDBConnection; try { Data_Module->IntegrationDBConnection->BeginTrans(); sql_statement.sprintf("DELETE FROM TXNSPEC_VALUES " "WHERE TESTSCENARIO_NO=%d AND TXNSPEC_NO=%d", testscenario_no, txnspec_no); query->SQL->Text = sql_statement; query->ExecSQL(); sql_statement=""; sql_statement.sprintf("DELETE FROM TRANSACTION_SPECIFICATION " "WHERE PROJECT_CODE='%s' AND ITERATION=%d " "AND TESTSCENARIO_NO=%d AND TXNSPEC_NO=%d ", m_currentproject.c_str(), m_currentiteration, testscenario_no, txnspec_no); query->SQL->Text = sql_statement; query->ExecSQL(); Data_Module->IntegrationDBConnection->CommitTrans(); refresh_testcases = true; ResequenceTransactions(current_node->Parent); } catch(...) { Data_Module->IntegrationDBConnection->RollbackTrans(); } delete query; } } } } if (refresh_testcases) { bool allow; TestCaseGridRowChanging(Sender, 0, 1, allow = true); } } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseZoomInClick(TObject *Sender) { TestCaseTreeView->FullExpand(); } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseZoomOutClick(TObject *Sender) { TestCaseTreeView->FullCollapse(); } //--------------------------------------------------------------------------- AnsiString & TMainForm::getNameFromNode( AnsiString & name, const AnsiString & string ) { char const *p = string.c_str(); name = string; if ( *p && *p == '(' ) { ++p; while ( *p && isdigit( *p ) ) { ++p; } if ( *p && *p == ')' ) { ++p; while ( *p && isspace( *p ) ) { ++p; } if ( *p ) { name = p; } } } return ( name ); } // delete a step via navigator button void __fastcall TMainForm::ScenarioStepsNavigatorBefore(TObject *Sender, TAdvNavigateBtn Button) { AnsiString BtnName; switch (Button) { case Dbctrls::nbFirst: BtnName = "First Record"; break; case Dbctrls::nbPrior: BtnName = "Prior Record"; break; case Dbctrls::nbNext: BtnName = "Next Record"; break; case Dbctrls::nbLast: BtnName = "Last Record"; break; case Dbctrls::nbInsert: { BtnName = "Insert Record"; AddTestCaseNodeClick(Sender); TTreeNode* dummyNode; ResequenceTestCases(dummyNode); //TxnStepsQuery->Edit(); break; } case Dbctrls::nbDelete: BtnName = "Delete Record"; { //BtnName = "Delete Record"; //AnsiString message; //int myRow = StepsGrid->GetRealRow(); // message.sprintf( //"Are you sure you want to delete all transactions from test step ('%s') %s? ", //StepsGrid->Cells[1][myRow], //StepsGrid->Cells[2][myRow] ); //if ( MessageDlg( message, mtConfirmation, TMsgDlgButtons() << mbYes << mbNo, 0 ) == mrYes ) // { int scenario = TxnStepsQuery->FieldByName( "TESTSCENARIO_NO" )->AsInteger; DeleteScenarioChildren(scenario); // } break; } case Dbctrls::nbEdit: BtnName = "Edit"; break; case Dbctrls::nbCancel: BtnName = "Cancel Edits"; break; case Dbctrls::nbRefresh: BtnName = "Refresh Data"; break; default: BtnName = "Other"; break; } } // add a new step via navigator button void __fastcall TMainForm::ScenarioStepsNavigatorClick(TObject *Sender, TAdvNavigateBtn Button) { AnsiString BtnName; bool refresh_testcases = false; switch (Button) { case Dbctrls::nbFirst: BtnName = "First Record"; break; case Dbctrls::nbPrior: BtnName = "Prior Record"; break; case Dbctrls::nbNext: BtnName = "Next Record"; break; case Dbctrls::nbLast: BtnName = "Last Record"; break; case Dbctrls::nbInsert: { BtnName = "Insert Record"; //refresh_testcases = false; //AddTestCaseNodeClick(Sender); //TTreeNode* dummyNode; //ResequenceTestCases(dummyNode); // TxnStepsQuery->Edit(); break; } case Dbctrls::nbDelete: BtnName = "Delete Record"; { BtnName = "Delete Record"; refresh_testcases = true; break; } case Dbctrls::nbEdit: BtnName = "Edit"; break; case Dbctrls::nbCancel: BtnName = "Cancel Edits"; break; case Dbctrls::nbRefresh: BtnName = "Refresh Data"; break; default: BtnName = "Other"; break; } //for (int J = 0; J < StepsGrid->RowCount; J++) // StepsGrid->Cells[0][J] = IntToStr(J+1); //BtnName = BtnName + " button clicked."; //Application->MessageBox(BtnName.c_str() , "Navigator", MB_OK); if (refresh_testcases) { bool allow; TestCaseGridRowChanging(Sender, 0, 1, allow = true); } } // Add a New Use Case void __fastcall TMainForm::AddTestCaseNodeClick(TObject *Sender) { TADOQuery *query = new TADOQuery(this); AnsiString sql_statement; query->Connection = Data_Module->IntegrationDBConnection; try { Data_Module->IntegrationDBConnection->BeginTrans(); sql_statement=""; sql_statement.sprintf("SELECT MAX(TESTCASE_SEQNO) MAX_SEQNO FROM TEST_SCENARIOS " "WHERE PROJECT_CODE='%s' AND ITERATION=%d " "AND TESTCASE_ID='%s'", m_currentproject.c_str(), m_currentiteration, m_currenttestcaseid.c_str()); query->SQL->Text = sql_statement; query->Open(); int max_testcase_seqno = query->FieldByName("MAX_SEQNO")->AsInteger; sql_statement=""; sql_statement.sprintf("INSERT INTO TEST_SCENARIOS (PROJECT_CODE,ITERATION,USECASE,TESTCASE_ID,TESTCASE_SEQNO,REPEAT_COUNT) " "VALUES ('%s',%d,'%s','%s',%d,%d) ", m_currentproject.c_str(), m_currentiteration, m_currenttestcaseid.c_str(), m_currenttestcaseid.c_str(), max_testcase_seqno+1, 1); query->SQL->Text = sql_statement; query->ExecSQL(); Data_Module->IntegrationDBConnection->CommitTrans(); } catch(...) { Data_Module->IntegrationDBConnection->RollbackTrans(); } delete query; //refresh query and the tree view TxnStepsQuery->Refresh(); bool allow; TestCaseGridRowChanging(Sender, 0, 1, allow = true); } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseTreeViewEndDrag(TObject *Sender, TObject *Target, int X, int Y) { TTreeNode* target_node = TestCaseTreeView->GetNodeAt(X, Y); if ((target_node != NULL) && (target_node != m_startnode)) { TTreeNode *new_node = NULL; TTreeNode *target_case_node = NULL; TTreeNode *start_case_node = NULL; bool isStartTestCase = (m_startnode->Level == 0); bool isTargetTestCase = (target_node->Level == 0); // Move the selected transaction start_case_node = isStartTestCase ? m_startnode : m_startnode->Parent; target_case_node = isTargetTestCase ? target_node : target_node->Parent; TestCaseTreeView->Items->BeginUpdate(); new_node = (isStartTestCase) ? TestCaseTreeView->Items->Insert(target_case_node, m_startnode->Text) : TestCaseTreeView->Items->AddChild(target_case_node, m_startnode->Text); new_node->Data = m_startnode->Data; TestCaseTreeView->Items->Delete(m_startnode); m_startnode = NULL; TestCaseTreeView->Items->EndUpdate(); // Refresh the tree, resequencing affected cases/transactions if (isStartTestCase) { bool allow; ResequenceTestCases(target_case_node); TestCaseGridRowChanging(Sender, 0, 1, allow = true); } else { ResequenceTransactions(target_case_node); LoadTestCaseNodes(target_case_node); if( start_case_node != target_case_node ) { ResequenceTransactions(start_case_node); LoadTestCaseNodes(start_case_node); } } } } //--------------------------------------------------------------------------- void __fastcall TMainForm::ResequenceTestCases(TTreeNode *testcase_node) { // Resequence Subtree nodes TADOQuery *query = new TADOQuery(this); AnsiString sql_statement; query->Connection = Data_Module->IntegrationDBConnection; try { Data_Module->IntegrationDBConnection->BeginTrans(); int testcaseseqno = 1; for (int i=0; iItems->Count; i++) { TTreeNode* childnode = TestCaseTreeView->Items->Item[i]; if (childnode->Level == 0) // Only consider TestCase Nodes { int testscenario_no = (int)(childnode->Data); sql_statement=""; sql_statement.sprintf("UPDATE TEST_SCENARIOS SET TESTCASE_SEQNO=%d " "WHERE TESTSCENARIO_NO=%d", testcaseseqno, testscenario_no); query->SQL->Text = sql_statement; query->ExecSQL(); testcaseseqno++; } } Data_Module->IntegrationDBConnection->CommitTrans(); } catch(...) { Data_Module->IntegrationDBConnection->RollbackTrans(); } delete query; } //--------------------------------------------------------------------------- void __fastcall TMainForm::ResequenceTransactions(TTreeNode *testcase_node) { // Resequence Subtree nodes TADOQuery *query = new TADOQuery(this); AnsiString sql_statement; query->Connection = Data_Module->IntegrationDBConnection; try { Data_Module->IntegrationDBConnection->BeginTrans(); int testscenario_no = (int)(testcase_node->Data); for (int i=0; iCount; i++) { sql_statement=""; sql_statement.sprintf("UPDATE TRANSACTION_SPECIFICATION SET SEQ_NO=%d, TESTSCENARIO_NO=%d" "WHERE PROJECT_CODE='%s' AND ITERATION=%d " "AND TXNSPEC_NO=%d", i+1, testscenario_no, m_currentproject.c_str(), m_currentiteration, testcase_node->Item[i]->Data); query->SQL->Text = sql_statement; query->ExecSQL(); } Data_Module->IntegrationDBConnection->CommitTrans(); } catch(...) { Data_Module->IntegrationDBConnection->RollbackTrans(); } delete query; } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseTreeViewStartDrag(TObject *Sender, TDragObject *&DragObject) { m_startnode = TestCaseTreeView->Selected; } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseTreeViewDragOver(TObject *Sender, TObject *Source, int X, int Y, TDragState State, bool &Accept) { Accept = false; TTreeView * tree_view = dynamic_cast(Source); if ( (tree_view != NULL) && (tree_view == TestCaseTreeView) ) { TTreeNode * source_node = TestCaseTreeView->GetNodeAt(X, Y); if( source_node != NULL ) { // Source and destination cannot be the same if( m_startnode == source_node ) return; // Test scenarios cannot be dropped on test cases if( (m_startnode->Level == 0) && (source_node->Level == 1) ) return; // Otherwise we can drop here Accept = true; } } } //--------------------------------------------------------------------------- void __fastcall TMainForm::ApplyTemplatesClick(TObject *Sender) { const TCursor Save_Cursor = Screen->Cursor; try { Screen->Cursor = crHourGlass; try { TADOQuery * query = 0; try { const unsigned count = countTransactionsInIteration( m_currentproject.c_str(), m_currentiteration ); m_progressBar->open( count * 2 + 1 ); // Rebuild the transaction templates, they may have changed. buildTransactionTemplates( m_transactionTemplates, m_currentproject, m_currentiteration ); m_progressBar->increment(); buildTransactionsForIteration( m_transactionCache, *m_progressBar, m_schema_handle, m_currentproject.c_str(), m_currentiteration ); query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "TESTSCENARIO_NO " "" "FROM " "TEST_SCENARIOS " "WHERE " "PROJECT_CODE=\'%s\' AND " "ITERATION=%d", m_currentproject.c_str(), m_currentiteration ); query->SQL->Text = sqlStatement; query->Open(); try { Data_Module->IntegrationDBConnection->BeginTrans(); while ( !query->Eof ) { applyTemplatesToScenario( *m_progressBar, query->FieldByName( "TESTSCENARIO_NO" )->AsInteger ); query->Next(); } Data_Module->IntegrationDBConnection->CommitTrans(); if ( TxnValuesQuery->State != dsInactive ) { TxnValuesQuery->Refresh(); HeaderStructureGrid->Invalidate(); } if ( TxnHeaderValuesQuery->State != dsInactive ) { TxnHeaderValuesQuery->Refresh(); TransactionValueGrid->Invalidate(); } } catch ( ... ) { Data_Module->IntegrationDBConnection->RollbackTrans(); throw; } } __finally { delete query; query = 0; m_progressBar->close(); } } catch ( const std::exception & exception ) { MessageDlg( exception.what(), mtError, TMsgDlgButtons() << mbOK, 0 ); } catch ( ... ) { MessageDlg( "Unknown exception applying templates to this scenario.", mtError, TMsgDlgButtons() << mbOK, 0 ); } } __finally { Screen->Cursor = Save_Cursor; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::InitialiseMASSTxns() { AnsiString sql_statement; TADOQuery *query = new TADOQuery(this); query->Connection = Data_Module->IntegrationDBConnection; m_mass_txns.clear(); try { sql_statement=""; sql_statement.sprintf("SELECT NAME,UDTYPE,UDSUBTYPE " "FROM MASS_TXNS " "WHERE PROJECTCODE='%s' " "AND ITERATION=%d " "AND ENABLED = 'Y' ", m_currentproject.c_str(), m_currentiteration); query->SQL->Text = sql_statement; query->Open(); while (!query->Eof) { unsigned short udtype = query->FieldByName("UDTYPE")->AsInteger; unsigned short udsubtype = query->FieldByName("UDSUBTYPE")->AsInteger; unsigned int udindex = (udtype << 16) + udsubtype; TXNIndexPair pair(udindex, query->FieldByName("NAME")->AsString); m_mass_txns.insert(pair); query->Next(); } } __finally { delete query; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::InitialiseTxnParams(unsigned int schema_format_version, IterationParams &iteration_params, IterationSequences &iteration_sequences) { AnsiString sql_statement; // Format Version only encodes Major/Minor numbers, and not Patch Level AnsiString formatversion; formatversion.sprintf("0x%08X", schema_format_version); IterationParamsPair pair("#0_@FORMATVERSION", formatversion.c_str()); iteration_params.insert(pair); TADOQuery *query = new TADOQuery(this); query->Connection = Data_Module->IntegrationDBConnection; TADOQuery *seqquery = new TADOQuery(this); seqquery->Connection = Data_Module->IntegrationDBConnection; try { sql_statement=""; sql_statement.sprintf("SELECT * FROM ITERATION_PARAMS " "WHERE PROJECT_CODE='%s' AND ITERATION=%d AND SUPPORTED <> 0 " , m_currentproject.c_str(), m_currentiteration); query->SQL->Text = sql_statement; query->Open(); while (!query->Eof) { int testscenario_no = 0; string fieldvalue = query->FieldByName("FIELDVALUE")->AsString.c_str(); if ( !query->FieldByName("TESTSCENARIO_NO")->IsNull ) { testscenario_no = query->FieldByName("TESTSCENARIO_NO")->AsInteger; } // Format is: @SEQ(,,,) if (fieldvalue.substr(0,4) == "@SEQ") { int lpos = fieldvalue.find("(")+1; int rpos = fieldvalue.rfind(")"); string seqargs = fieldvalue.substr( lpos, rpos ); string seqname; string seqstart; string seqinc; string seqlimit; const char *p = seqargs.c_str(); while ( (*p != '\0') && (*p == ' ') ) p++; // Skip Whitespace while ( (*p != '\0') && (*p != ',') && (*p != ' ') ) { seqname += *p; p++; } if (*p != '\0') p++; while ( (*p != '\0') && (*p == ' ') ) { p++; // Skip Whitespace } while ( (*p != '\0') && (*p != ',') && (*p != ' ') ) { seqstart += *p; p++; } if (*p != '\0') p++; while ( (*p != '\0') && (*p == ' ') ) { p++; // Skip Whitespace } while ( (*p != '\0') && (*p != ',') && (*p != ' ') ) { seqinc += *p; p++; } if (*p != '\0') p++; while ( (*p != '\0') && (*p == ' ') ) { p++; // Skip Whitespace } while (*p != '\0') { seqlimit += *p; p++; } IterationSequence sequence; sequence.name = seqname; if (seqstart.length() > 0) { sequence.initial_value = atoi(seqstart.c_str()); } else { sequence.initial_value = 0; } if (seqname[0] == '#') { string seqgenname = seqname.substr(1,seqname.length()-1); sql_statement=""; sql_statement.sprintf("SELECT SEQVALUE FROM SEQGEN WHERE PROJECT_CODE='%s' AND ITERATION=%d AND SEQNAME='%s'", m_currentproject.c_str(), m_currentiteration, seqgenname.c_str() ); seqquery->SQL->Text = sql_statement; seqquery->Open(); if (seqquery->RecordCount == 0) { sql_statement=""; sql_statement.sprintf("INSERT INTO SEQGEN (PROJECT_CODE,ITERATION,SEQNAME,SEQVALUE) VALUES ('%s',%d,'%s',%d)", m_currentproject.c_str(), m_currentiteration, seqgenname.c_str(), sequence.initial_value ); seqquery->SQL->Text = sql_statement; seqquery->ExecSQL(); } else { sequence.initial_value = seqquery->FieldByName("SEQVALUE")->AsInteger; } } sequence.value = sequence.initial_value; if (seqinc.length() > 0) { sequence.increment = atoi(seqinc.c_str()); } else { sequence.increment = 1; } if (seqlimit.length() > 0) { sequence.reset_at = atoi(seqlimit.c_str()); } else { sequence.reset_at = 0; } sequence.reset_at = 0; IterationSequencesPair seqpair(sequence.name, sequence); iteration_sequences.insert(seqpair); } AnsiString param_name; param_name.sprintf("#%d_%s", testscenario_no, query->FieldByName("NAME")->AsString.c_str()); IterationParamsPair pair2(param_name.c_str(), fieldvalue.c_str()); iteration_params.insert(pair2); query->Next(); } } __finally { delete query; delete seqquery; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::InitialiseTestScenario(unsigned int testscenario_no, TxnSpecValueMap &txnSpecValueMap, FoundTxnSpecValueMap &foundTxnSpecValueMap, IterationSequences &iteration_sequences, IterationParams &iteration_params) { AnsiString sql_statement; TADOQuery *query = new TADOQuery(this); query->Connection = Data_Module->IntegrationDBConnection; TADOQuery *values_query = new TADOQuery(this); values_query->Connection = Data_Module->IntegrationDBConnection; try { sql_statement=""; sql_statement.sprintf("select txnspec_no,udtype,udsubtype " "from transaction_specification " "where testscenario_no=%d order by seq_no", testscenario_no); query->SQL->Text = sql_statement; query->Open(); while (!query->Eof) { // For each transaction unsigned int txnspec_no = query->FieldByName("TXNSPEC_NO")->AsInteger; unsigned short udtype = query->FieldByName("UDTYPE")->AsInteger; unsigned short udsubtype = query->FieldByName("UDSUBTYPE")->AsInteger; unsigned int udindex = (udtype << 16) + udsubtype; TXNIndexMap::iterator txn_itr = m_mass_txns.find(udindex); if (txn_itr != m_mass_txns.end()) { string structure_name; string structure_handle; structure_name = (*txn_itr).second.c_str(); // Create a Transaction Instance if (XMLSchema->Create(m_schema_handle.c_str(), structure_name.c_str(), m_currentiteration, structure_handle, NULL)) { ProcessTxnStructure(structure_handle, udtype, udsubtype, testscenario_no, txnspec_no, values_query, txnSpecValueMap, foundTxnSpecValueMap, iteration_params, iteration_sequences, 0); XMLSchema->Destroy(structure_handle); } else { AnsiString msg; msg.sprintf("Failed to create schema object for Schema: '%s' Structure: '%s'", m_schema_handle.c_str(), structure_name.c_str()); MessageDlg(msg, mtError, TMsgDlgButtons() << mbOK, 0); } } // Found Transaction declaration in MASS TXNS query->Next(); } } __finally { delete query; delete values_query; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::ProcessTxnStructure(string structure_handle, unsigned short udtype, unsigned short udsubtype, int testscenario_no, int txnspec_no, TADOQuery *query, TxnSpecValueMap &txnSpecValueMap, FoundTxnSpecValueMap &foundTxnSpecValueMap, IterationParams &iteration_params, IterationSequences &iteration_sequences, unsigned int nested_subscript) { vector structure_attributes; vector::iterator s_itr; AnsiString sql_statement; XMLSchema->GetAttributes(structure_handle, structure_attributes); s_itr = structure_attributes.begin(); while (s_itr != structure_attributes.end()) { string attribute_handle = (*s_itr); string elementtype; XMLSchema->GetAttributeProperty(attribute_handle, "type", elementtype); if (elementtype == "field") { string datatype; XMLSchema->GetAttributeProperty(attribute_handle, "datatype", datatype); if (datatype == "Struct") { ProcessTxnStructure(attribute_handle, udtype, udsubtype, testscenario_no, txnspec_no, query, txnSpecValueMap, foundTxnSpecValueMap, iteration_params, iteration_sequences, 0); } else { string fieldname; string tagvalue; string xpath; XMLSchema->GetAttributeProperty(attribute_handle, "tag", tagvalue); if (tagvalue.length() > 0) { XMLSchema->GetAttributeProperty(attribute_handle, "name", fieldname); XMLSchema->GetAttributeProperty(attribute_handle, "xpath", xpath); AnsiString lookup_fieldname; AnsiString display_fieldname; if (nested_subscript == 0) { lookup_fieldname.sprintf("$%s", fieldname.c_str()); display_fieldname = fieldname.c_str(); } else { lookup_fieldname.sprintf("$%s#%d", fieldname.c_str(), nested_subscript); display_fieldname.sprintf("%s#%d", fieldname.c_str(), nested_subscript); } AnsiString field_value = LookupParameter(iteration_params, iteration_sequences, query, testscenario_no, lookup_fieldname.c_str(), udtype, udsubtype); AnsiString key; if (nested_subscript == 0) { key.sprintf("%d_%d_%s", testscenario_no, txnspec_no, fieldname.c_str()); } else { key.sprintf("%d_%d_%s#%d", testscenario_no, txnspec_no, fieldname.c_str(), nested_subscript); } FoundTxnSpecValuePair foundpair(key, 0); foundTxnSpecValueMap.insert(foundpair); TxnSpecValueIterator txnspec_value_itr = txnSpecValueMap.find(key); TxnSpecValue &existing_value = (*txnspec_value_itr).second; // Either no existing entry OR the current entry is NOT User supplied // (ie. Ignore field values for existing user supplied items) if ( (txnspec_value_itr == txnSpecValueMap.end()) || (existing_value.user_supplied == 'N') ) { if ( (existing_value.fieldtag != atoi(tagvalue.c_str()) || (existing_value.fieldvalue != field_value) || (existing_value.xpath != AnsiString(xpath.c_str()))) ) { // Remove the existing value if (txnspec_value_itr != txnSpecValueMap.end()) { sql_statement=""; sql_statement.sprintf("DELETE FROM TXNSPEC_VALUES WHERE " "TESTSCENARIO_NO=%d AND TXNSPEC_NO=%d AND FIELDNAME='%s'", testscenario_no, txnspec_no, fieldname.c_str() ); query->SQL->Text = sql_statement; query->ExecSQL(); } // Add the new value sql_statement=""; if (field_value.Length() > 0) { sql_statement.sprintf("INSERT INTO TXNSPEC_VALUES(FIELDTAG, FIELDVALUE, TESTSCENARIO_NO, TXNSPEC_NO, FIELDNAME, DISPLAY_FIELDNAME, XPATH, SUBSCRIPT, USER_SUPPLIED) " "VALUES (%s,'%s',%d,%d,'%s','%s','%s',%d,'N')", tagvalue.c_str(), field_value.c_str(), testscenario_no, txnspec_no, fieldname.c_str(), display_fieldname.c_str(), xpath.c_str(), nested_subscript); } else { sql_statement.sprintf("INSERT INTO TXNSPEC_VALUES(FIELDTAG, TESTSCENARIO_NO, TXNSPEC_NO, FIELDNAME, DISPLAY_FIELDNAME, XPATH, SUBSCRIPT, USER_SUPPLIED) " "VALUES (%s,%d,%d,'%s','%s','%s',%d,'N')", tagvalue.c_str(), testscenario_no, txnspec_no, fieldname.c_str(), display_fieldname.c_str(), xpath.c_str(), nested_subscript); } query->SQL->Text = sql_statement; query->ExecSQL(); } } } } } else if (elementtype == "repeat") { string refcountfield; string maxOccursStr; string refcountAttribute; XMLSchema->GetAttributeProperty(attribute_handle, "refcountfield", refcountfield); if (!refcountfield.empty()) { string refcountAttribute = structure_handle+"."+refcountfield; XMLSchema->GetAttributeProperty(refcountAttribute, "max", maxOccursStr); } if (maxOccursStr.empty()) { XMLSchema->GetAttributeProperty(attribute_handle, "maxOccurs", maxOccursStr); } int maxOccurs = atoi(maxOccursStr.c_str()); // Limit to 100 elements if (maxOccurs > 100) { maxOccurs = 100; } string repeat_name; XMLSchema->GetAttributeProperty(attribute_handle, "name", repeat_name); XMLSchema->SetAttributeValue(structure_handle, refcountfield, maxOccurs); for (int occurrence=1; occurrence<=maxOccurs; occurrence++) { string repeat_attribute_handle; AnsiString temp; temp.sprintf("%s.%d.%s",attribute_handle.c_str(),occurrence,repeat_name.c_str()); repeat_attribute_handle = temp.c_str(); string repeat_attribute_datatype; XMLSchema->GetAttributeProperty(repeat_attribute_handle, "datatype", repeat_attribute_datatype); if (repeat_attribute_datatype != "Struct") { string fieldname; string xpath; string tagvalue; XMLSchema->GetAttributeProperty(repeat_attribute_handle, "tag", tagvalue); if (tagvalue.length() > 0) { XMLSchema->GetAttributeProperty(repeat_attribute_handle, "name", fieldname); XMLSchema->GetAttributeProperty(repeat_attribute_handle, "xpath", xpath); string lookup_fieldname = "$"+fieldname; AnsiString field_value = LookupParameter(iteration_params, iteration_sequences, query, testscenario_no, lookup_fieldname, udtype, udsubtype); AnsiString key; key.sprintf("%d_%d_%s.%d", testscenario_no, txnspec_no, fieldname.c_str(), occurrence); FoundTxnSpecValuePair foundpair(key, 0); foundTxnSpecValueMap.insert(foundpair); TxnSpecValueIterator txnspec_value_itr = txnSpecValueMap.find(key); TxnSpecValue &existing_value = (*txnspec_value_itr).second; // Either no existing entry OR the current entry is NOT User supplied // (ie. Ignore field values for existing user supplied items) if ( (txnspec_value_itr == txnSpecValueMap.end()) || (existing_value.user_supplied == 'N') ) { if ( (existing_value.fieldtag != atoi(tagvalue.c_str()) || (existing_value.fieldvalue != field_value) || (existing_value.xpath != AnsiString(xpath.c_str()))) ) { // Remove the existing value if (txnspec_value_itr != txnSpecValueMap.end()) { sql_statement=""; sql_statement.sprintf("DELETE FROM TXNSPEC_VALUES WHERE " "TESTSCENARIO_NO=%d AND TXNSPEC_NO=%d AND FIELDNAME='%s' AND SUBSCRIPT=%d", testscenario_no, txnspec_no, fieldname.c_str(), occurrence ); query->SQL->Text = sql_statement; query->ExecSQL(); } AnsiString subscripted_fieldname; subscripted_fieldname.sprintf("%s#%d", fieldname.c_str(), occurrence); // Add the new value sql_statement=""; if (field_value.Length() > 0) { sql_statement.sprintf("INSERT INTO TXNSPEC_VALUES(FIELDTAG, FIELDVALUE, TESTSCENARIO_NO, TXNSPEC_NO, FIELDNAME, DISPLAY_FIELDNAME, SUBSCRIPT, XPATH, USER_SUPPLIED) " "VALUES (%s,'%s',%d,%d,'%s','%s',%d,'%s','N')", tagvalue.c_str(), field_value.c_str(), testscenario_no, txnspec_no, fieldname.c_str(), subscripted_fieldname.c_str(), occurrence, xpath.c_str()); } else { sql_statement.sprintf("INSERT INTO TXNSPEC_VALUES(FIELDTAG, TESTSCENARIO_NO, TXNSPEC_NO, FIELDNAME, DISPLAY_FIELDNAME, SUBSCRIPT, XPATH, USER_SUPPLIED) " "VALUES (%s,%d,%d,'%s','%s',%d,'%s','N')", tagvalue.c_str(), testscenario_no, txnspec_no, fieldname.c_str(), subscripted_fieldname.c_str(), occurrence, xpath.c_str()); } query->SQL->Text = sql_statement; query->ExecSQL(); } } } // if (tagvalue.length() > 0) } // if (repeat_attribute_datatype != "Struct") else { ProcessTxnStructure(repeat_attribute_handle, udtype, udsubtype, testscenario_no, txnspec_no, query, txnSpecValueMap, foundTxnSpecValueMap, iteration_params, iteration_sequences, occurrence); } } // for (int i=1; i<=occurrence; i++) } s_itr++; } // while } //--------------------------------------------------------------------------- AnsiString TMainForm::LookupParameter(IterationParams &iteration_params, IterationSequences &iteration_sequences, TADOQuery *query, int testscenario_no, const string ¶m, unsigned short udtype, unsigned short udsubtype) { AnsiString field_value; AnsiString param_lookup; param_lookup.sprintf("#%d_%s", testscenario_no, param.c_str()); IterationParams::iterator param_itr = iteration_params.find(param_lookup.c_str()); if (param_itr == iteration_params.end()) { param_lookup=""; param_lookup.sprintf("#%d_%s", 0, param.c_str()); param_itr = iteration_params.find(param_lookup.c_str()); } if (param_itr != iteration_params.end()) { string param_value = (*param_itr).second; if (param_value == "@FORMATVERSION") { field_value = LookupParameter(iteration_params, iteration_sequences, query, testscenario_no, param_value, udtype, udsubtype); } else if (param_value == "@NOW") { TDateTime current_time = TDateTime::CurrentDateTime(); field_value.sprintf("%s", current_time.FormatString("dd-mm-yyyy hh:nn:ss").c_str()); } else if (param_value == "@UTCNOW") { TDateTime current_time = TDateTime::CurrentDateTime() + ((_timezone/3600.0)/24.0); field_value.sprintf("%s", current_time.FormatString("dd-mm-yyyy hh:nn:ss").c_str()); } else if (param_value == "@TODAY") { TDateTime current_time = TDateTime::CurrentDateTime(); field_value.sprintf("%s", current_time.FormatString("dd-mm-yyyy").c_str()); } else if (param_value == "@YESTERDAY") { TDateTime current_time = TDateTime::CurrentDateTime() - 1; field_value.sprintf("%s", current_time.FormatString("dd-mm-yyyy").c_str()); } else if (param_value.substr(0,5) == "@RAND") { int lpos = param_value.find("(")+1; string rand_args = param_value.substr(lpos, param_value.rfind(")")-1); string lower_bound; string upper_bound; const char *p = rand_args.c_str(); while ( (*p != '\0') && (*p != ',') ) { lower_bound += *p; p++; } if ( *p == ',' ) { p++; } while ( (*p != '\0') && (*p != ')') ) { upper_bound += *p; p++; } int lower_int = atoi(lower_bound.c_str()); int upper_int = atoi(upper_bound.c_str()); double rand_key = (double)rand() / (double)RAND_MAX; int rand_value = (rand_key * (upper_int - lower_int)) + lower_int; field_value.sprintf("%d", rand_value); } else if (param_value == "@UDTYPE") { field_value.sprintf("%d", udtype); } else if (param_value == "@UDSUBTYPE") { field_value.sprintf("%d", udsubtype); } else if (param_value == "@ACCOUNTTYPE") { int account_format = 0; switch(udtype) { case 1: // Card account_format = 2; break; case 2: // Application account_format = 1; break; case 3: // Product account_format = 3; break; case 4: // Other account_format = 4; break; case 5: // Audit account_format = 4; break; case 6: // Event account_format = 4; break; case 7: // Project account_format = 4; break; } // switch field_value.sprintf("%d", account_format); } else if (param_value.substr(0,4) == "@SEQ") { int lpos = param_value.find("(")+1; int comma_pos = param_value.find(","); string seqname = param_value.substr( lpos, comma_pos-lpos ); IterationSequences::iterator s_itr = iteration_sequences.find( seqname ); if (s_itr != iteration_sequences.end()) { IterationSequence &sequence = (*s_itr).second; field_value.sprintf("%d", sequence.value); sequence.value += sequence.increment; if (sequence.reset_at != 0) { if (sequence.value >= sequence.reset_at) { sequence.value = sequence.initial_value; } } if (seqname[0] == '#') { AnsiString sql_statement; string seqgenname = seqname.substr(1,seqname.length()-1); sql_statement.sprintf("UPDATE SEQGEN SET SEQVALUE=%d where PROJECT_CODE='%s' AND ITERATION=%d AND SEQNAME='%s'", sequence.value, m_currentproject.c_str(), m_currentiteration, seqgenname.c_str() ); query->SQL->Text = sql_statement; query->ExecSQL(); } } } else if (param_value[0] == '@') { field_value = LookupParameter(iteration_params, iteration_sequences, query, testscenario_no, param_value, udtype, udsubtype); } else { field_value.sprintf("%s", param_value.c_str()); } } return field_value; } //--------------------------------------------------------------------------- void __fastcall TMainForm::TxnHdrValuesQueryAfterInsert(TDataSet *DataSet) { DataSet->FieldByName("PROJECT_CODE")->AsString = m_currentproject; DataSet->FieldByName("ITERATION")->AsInteger = m_currentiteration; } //--------------------------------------------------------------------------- void __fastcall TMainForm::ScenarioParametersClick(TObject *Sender) { ScenarioParamsForm->ShowForm(m_currentproject, m_currentiteration, m_testscenario_no); } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseTreeViewMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { if (Button == mbRight) { TTreeNode* target_node = TestCaseTreeView->GetNodeAt(X, Y); if (target_node != NULL) { target_node->Selected = true; } } } //--------------------------------------------------------------------------- void __fastcall TMainForm::TxnValuesQueryBeforePost(TDataSet *DataSet) { // DataSet->FieldByName( "USER_SUPPLIED" )->AsString = "Y"; } //--------------------------------------------------------------------------- void __fastcall TMainForm::RemoveUserSuppliedValueClick(TObject *Sender) { if (TxnValuesQuery->FieldByName("USER_SUPPLIED")->AsString == "Y") { Data_Module->IntegrationDBConnection->BeginTrans(); TxnValuesQuery->Delete(); Data_Module->IntegrationDBConnection->CommitTrans(); } } //--------------------------------------------------------------------------- void __fastcall TMainForm::CopyValuesToClipboardBtnClick(TObject *Sender) { AnsiString clipboard_text; Clipboard()->Clear(); AnsiString sql_statement; TADOQuery *query = new TADOQuery(this); query->Connection = Data_Module->IntegrationDBConnection; sql_statement.sprintf("SELECT * FROM TXNSPEC_VALUES " "WHERE TESTSCENARIO_NO=%d AND TXNSPEC_NO=%d " "AND (FIELDVALUE IS NOT NULL OR FIELDVALUE<>'') " "ORDER BY FIELDNAME", m_testscenario_no, m_txnspec_no); query->SQL->Text = sql_statement; query->Open(); while (!query->Eof) { AnsiString clipboard_line; clipboard_line.sprintf("%-30.30s\t%s\r\n", query->FieldByName("FIELDNAME")->AsString.c_str(), query->FieldByName("FIELDVALUE")->AsString.c_str() ); clipboard_text += clipboard_line; query->Next(); } query->Close(); Clipboard()->SetTextBuf( clipboard_text.c_str() ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::loadLegacyVariables( DefinedVariableTable & variables, const AnsiString & project, Iteration & iteration ) { TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "NAME," "FIELDVALUE," "TESTSCENARIO_NO " "FROM " "ITERATION_PARAMS " "WHERE " "PROJECT_CODE=\'%s\' AND " "ITERATION=%d", project.c_str(), iteration.getIterationId() ); query->SQL->Text = sqlStatement; query->Open(); AnsiString fieldName; AnsiString xpath; AnsiString value; bool qualified; DefinedVariable * variable; while ( !query->Eof ) { fieldName = query->FieldByName( "NAME" )->AsString; value = query->FieldByName( "FIELDVALUE" )->AsString; if ( !value.IsEmpty() ) { if ( value[ 1 ] == '=' ) { value.Delete( 1, 1 ); } if ( !value.IsEmpty() ) { switch ( value[ 1 ] ) { case '@': value[ 1 ] = '='; if ( FieldExpression::isFunctor( value.c_str() + 1 ) ) { value += "()"; } break; default: break; } } } if ( !fieldName.IsEmpty() ) { qualified = !query->FieldByName( "TESTSCENARIO_NO" )->IsNull; switch ( fieldName[ 1 ] ) { case '$': // We don't worry about fields here. break; case '@': if ( qualified ) { variable = &variables.defineVariable( fieldName.c_str() + 1, iteration.getTestScenario( query->FieldByName( "TESTSCENARIO_NO" ) ->AsInteger ) ); } else { variable = &variables.defineVariable( fieldName.c_str() + 1 ); } variable->setExpression( value.c_str() ); break; default: break; } } query->Next(); } } __finally { delete query; query = 0; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::readSequences( SequenceCollection & sequences, const std::string & project, const int & iteration ) { TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "SEQNAME," "SEQVALUE " "FROM " "SEQGEN " "WHERE " "PROJECT_CODE=\'%s\' AND " "ITERATION=%d", Utilities::EscapeString( project ).c_str(), iteration ); query->SQL->Text = sqlStatement; query->Open(); std::string sequenceName; int value; Sequence * sequence; while ( !query->Eof ) { sequenceName = query->FieldByName( "SEQNAME" )->AsString.c_str(); value = query->FieldByName( "SEQVALUE" )->AsInteger; sequence = &sequences.getSequence( sequenceName, true, 0 ); sequence->setValue( value ); sequence->setUpdate( true ); sequence->setDirty( false ); query->Next(); } } __finally { delete query; query = 0; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::writeSequences( const SequenceCollection & sequences, const std::string & project, const int & iteration ) { TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; for ( std::map< std::string, Sequence * >::const_iterator sequence = sequences.getCollection().begin(); sequence != sequences.getCollection().end(); ++sequence ) { std::stringstream stream; if ( sequence->second->isPersisted() && sequence->second->isDirty() ) { if ( sequence->second->isUpdate() ) { stream << "UPDATE SEQGEN SET " << "SEQVALUE=" << sequence->second->getValue() << " WHERE " << "PROJECT_CODE=\'" << Utilities::EscapeString( project ) << "\' AND " << "ITERATION=" << iteration << " AND " << "SEQNAME=\'" << Utilities::EscapeString( sequence->second->getName() ) << '\''; } else { stream << "INSERT INTO SEQGEN ( " "PROJECT_CODE," "ITERATION," "SEQNAME," "SEQVALUE " " ) VALUES ( " << '\'' << Utilities::EscapeString( project ) << "\'," << iteration << ",\'" << Utilities::EscapeString( sequence->second->getName() ) << "\'," << sequence->second->getValue() << " )"; } query->SQL->Text = stream.str().c_str(); if ( query->ExecSQL() != 1 ) { MTHROW( std::runtime_error, \ "Cannot " \ << ( sequence->second->isUpdate() ? "update" : "insert" ) \ << " sequence \"" \ << sequence->second->getName() \ << "\"." ); } } } SequenceGeneratorQuery->Refresh(); } __finally { delete query; query = 0; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::GenerateTestTestCaseBtnClick(TObject *Sender) { std::vector< int > scenarios; generateTransaction( scenarios ); } //--------------------------------------------------------------------------- const unsigned __fastcall TMainForm::countTransactionsInIteration( const char * project, const int & iteration ) { unsigned count = 0; TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "COUNT(*) AS COUNT " "FROM " "TRANSACTION_SPECIFICATION " "WHERE " "PROJECT_CODE=\'%s\' AND " "ITERATION=%d", project, iteration ); query->SQL->Text = sqlStatement; query->Open(); count = ( !query->Eof ? query->FieldByName( "COUNT" )->AsInteger : 0 ); } __finally { delete query; query = 0; } return ( count ); } //--------------------------------------------------------------------------- const unsigned __fastcall TMainForm::countTransactionsInScenario( const int & scenario ) { unsigned count = 0; TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "COUNT(*) AS COUNT " "FROM " "TRANSACTION_SPECIFICATION " "WHERE " "TESTSCENARIO_NO=%d", scenario ); query->SQL->Text = sqlStatement; query->Open(); count = ( !query->Eof ? query->FieldByName( "COUNT" )->AsInteger : 0 ); } __finally { delete query; query = 0; } return ( count ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::applyTemplatesToNewTransaction( const int & transaction, const TestScenarioTemplate * all ) { TADOQuery * query = 0; AnsiString sqlStatement; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; sqlStatement.sprintf( "SELECT " "XPATH," "FIELDVALUE, " "DISPLAYABLE " "FROM " "TXNSPEC_VALUES " "WHERE " "TXNSPEC_NO=%d ", transaction ); query->SQL->Text = sqlStatement; query->Open(); std::string xpath; std::string value; unsigned matchCount = 0; AnsiString fieldValue; while ( !query->Eof ) { xpath = query->FieldByName( "XPATH" )->AsString.c_str(); fieldValue = query->FieldByName( "FIELDVALUE" )->AsString; matchCount = ( all ? all->findMatch( value, xpath ) : 0 ); if ( matchCount == 1 ) { query->Edit(); query->FieldByName( "FIELDVALUE" )->AsString = value.c_str(); query->FieldByName( "DISPLAYABLE" )->AsString = "Y"; query->Post(); } else if ( matchCount > 1 ) { MTHROW( std::runtime_error, \ "Ambigious transaction template. " \ << matchCount \ << " matches found for \"" \ << xpath \ << "\"." ); } query->Next(); } } __finally { delete query; query = 0; } try { // hack to remove payment methods and payment values parents as they cause a generation problem. query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; sqlStatement.sprintf( "DELETE FROM " "TXNSPEC_VALUES " "WHERE " "TXNSPEC_NO=%d " "AND " "DISPLAY_FIELDNAME IN (\'paymentMethod\',\'paymentValue\') ", transaction ); query->SQL->Text = sqlStatement; query->ExecSQL(); } __finally { delete query; query = 0; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::applyTemplatesToTransaction( ProgressBar & progressBar, const int & transaction, const TestScenarioTemplate * testScenario, const TestScenarioTemplate * all ) { TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "XPATH," "FIELDVALUE, " "DISPLAYABLE " "FROM " "TXNSPEC_VALUES " "WHERE " "TXNSPEC_NO=%d AND " "USER_SUPPLIED=\'N\' AND " "CHILD_COUNT=0", transaction ); query->SQL->Text = sqlStatement; query->Open(); std::string xpath; std::string value; unsigned matchCount = 0; AnsiString fieldValue; while ( !query->Eof ) { xpath = query->FieldByName( "XPATH" )->AsString.c_str(); fieldValue = query->FieldByName( "FIELDVALUE" )->AsString; matchCount = ( testScenario ? testScenario->findMatch( value, xpath ) : 0 ); if ( matchCount == 1 ) { query->Edit(); query->FieldByName( "FIELDVALUE" )->AsString = value.c_str(); query->FieldByName( "DISPLAYABLE" )->AsString = "Y"; query->Post(); } else if ( matchCount > 1 ) { MTHROW( std::runtime_error, \ "Ambigious scenario transaction template. " \ << matchCount \ << " matches found for \"" \ << xpath \ << "\"." ); } else { matchCount = ( all ? all->findMatch( value, xpath ) : 0 ); if ( matchCount == 1 ) { query->Edit(); query->FieldByName( "FIELDVALUE" )->AsString = value.c_str(); query->FieldByName( "DISPLAYABLE" )->AsString = "Y"; query->Post(); } else if ( matchCount > 1 ) { MTHROW( std::runtime_error, \ "Ambigious transaction template. " \ << matchCount \ << " matches found for \"" \ << xpath \ << "\"." ); } } query->Next(); } } __finally { delete query; query = 0; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::applyTemplatesToScenario( ProgressBar & progressBar, const int & scenario ) { /** * Iterate through the collection of transactions defined for this scenario * and for each field attempt to apply every field template defined. When * multiple fields match, raise an exception and roll any template * applications back. */ TestScenarioTemplate * testScenario = m_transactionTemplates.findTestScenarioTemplate( scenario ); TestScenarioTemplate * all = m_transactionTemplates.findTestScenarioTemplate( 0 ); if ( testScenario || all ) { TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "TXNSPEC_NO," "NAME " "FROM " "TRANSACTION_SPECIFICATION," "MASS_TXNS " "WHERE " "TESTSCENARIO_NO=%d AND " "TRANSACTION_SPECIFICATION.PROJECT_CODE = MASS_TXNS.PROJECTCODE AND " "TRANSACTION_SPECIFICATION.ITERATION = MASS_TXNS.ITERATION AND " "TRANSACTION_SPECIFICATION.UDTYPE = MASS_TXNS.UDTYPE AND " "TRANSACTION_SPECIFICATION.UDSUBTYPE = MASS_TXNS.UDSUBTYPE " "ORDER BY " "TESTSCENARIO_NO," "TXNSPEC_NO", scenario ); query->SQL->Text = sqlStatement; query->Open(); AnsiString message; while ( !query->Eof ) { message.sprintf( " Applying template to %s ...", query->FieldByName( "NAME" )->AsString.c_str() ); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); applyTemplatesToTransaction( progressBar, query->FieldByName( "TXNSPEC_NO" )->AsInteger, testScenario, all ); progressBar.increment(); query->Next(); } } __finally { delete query; query = 0; MainStatusBar->Panels->Items[ g_messagePanel ]->Text = ""; } } } //--------------------------------------------------------------------------- void __fastcall TMainForm::ApplyTemplatesToScenarioClick(TObject *Sender) { // The scenario, our context, is kept in the tag of our parent menu. TPopupMenu * menu = dynamic_cast< TPopupMenu * >( dynamic_cast< TMenuItem * >( Sender )->GetParentMenu() ); if ( menu ) { const int scenario = menu->Tag; try { const TCursor Save_Cursor = Screen->Cursor; try { Screen->Cursor = crHourGlass; const unsigned count = countTransactionsInScenario( scenario ); m_progressBar->open( count * 2 ); buildTransactionsForScenario( m_transactionCache, *m_progressBar, scenario, m_schema_handle, m_currentiteration ); try { Data_Module->IntegrationDBConnection->BeginTrans(); applyTemplatesToScenario( *m_progressBar, scenario ); Data_Module->IntegrationDBConnection->CommitTrans(); } catch ( ... ) { Data_Module->IntegrationDBConnection->RollbackTrans(); throw; } m_progressBar->update( count ); } __finally { m_progressBar->close(); Screen->Cursor = Save_Cursor; } } catch ( const std::exception & exception ) { MessageDlg( exception.what(), mtError, TMsgDlgButtons() << mbOK, 0 ); } catch ( ... ) { MessageDlg( "Unknown exception applying templates to this scenario.", mtError, TMsgDlgButtons() << mbOK, 0 ); } } } string __fastcall TMainForm::FindField(const string &structure_handle, int fieldtag) { string field_path; vector structure_attributes; vector::iterator s_itr; XMLSchema->GetAttributes(structure_handle, structure_attributes); s_itr = structure_attributes.begin(); while (s_itr != structure_attributes.end()) { string elementtype; string datatype; XMLSchema->GetAttributeProperty((*s_itr), "type", elementtype); if (elementtype == "field") { XMLSchema->GetAttributeProperty((*s_itr), "datatype", datatype); if (datatype == "Struct") { field_path = FindField((*s_itr), fieldtag); if (!field_path.empty()) { break; } } else { string xml_fieldtag; XMLSchema->GetAttributeProperty((*s_itr), "tag", xml_fieldtag); if ( fieldtag == atoi(xml_fieldtag.c_str()) ) { field_path = (*s_itr); break; } } } else if (elementtype == "repeat") { string repeatname; XMLSchema->GetAttributeProperty((*s_itr), "name", repeatname); string repeatAttribute = (*s_itr)+".1"; field_path = FindField(repeatAttribute, fieldtag); if (!field_path.empty()) { break; } } s_itr++; } return field_path; } //--------------------------------------------------------------------------- void __fastcall TMainForm::FieldEnumValuesDblClick(TObject *Sender) { TADOQuery * query = 0; if ( TransactionStructurePageControl->ActivePage == PayloadStructureTabSheet ) { query = TxnValuesQuery; } else if ( TransactionStructurePageControl->ActivePage == HeaderStructureTabSheet ) { query = TxnHeaderValuesQuery; } if ( query ) { if ( query->State != dsEdit ) { query->Edit(); } query->FieldByName( "FIELDVALUE" )->AsString = FieldEnumValues->Items->Strings[ FieldEnumValues->ItemIndex ]; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action) { XMLSchema->Active = false; if( m_Registry != 0 ) m_Registry->CloseKey(); } //--------------------------------------------------------------------------- void __fastcall TMainForm::SetGenerationDirectoryClick(TObject *Sender) { AnsiString directory; if ( SelectDirectory("Select Generation Directory", "c:\\", directory) ) { if (m_Registry != NULL) { m_Registry->WriteString("MRUGenerationDir", directory); } } } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseGridRowChanging(TObject *Sender, int OldRow, int NewRow, bool &Allow) { TCursor Save_Cursor = Screen->Cursor; Screen->Cursor = crHourGlass; // Show hourglass cursor try { TxnStepsQuery->Close(); if ( (m_currentproject.Length() > 0) && (m_currentiteration != 0) ) { TestCaseTreeView->Items->BeginUpdate(); TestCaseTreeView->Items->Clear(); TADOQuery *query = new TADOQuery(this); query->Connection = Data_Module->IntegrationDBConnection; m_currenttestcaseid = TestCaseQuery->FieldByName("TESTCASE_ID")->AsString; m_currentcaserepeat = TestCaseQuery->FieldByName("CASE_REPEAT")->AsInteger; m_currentcasedelay = TestCaseQuery->FieldByName("REPEAT_DELAY")->AsInteger; AnsiString sql_statement; sql_statement.sprintf("SELECT * FROM TEST_SCENARIOS " "WHERE PROJECT_CODE='%s' AND ITERATION=%d " "AND TESTCASE_ID='%s' " "ORDER BY TESTCASE_SEQNO", m_currentproject.c_str(), m_currentiteration, m_currenttestcaseid.c_str()); query->SQL->Text = sql_statement; query->Open(); int count = 0; while (!query->Eof) { AnsiString testcase_desc; testcase_desc.sprintf("(%d) %s", query->FieldByName("TESTCASE_SEQNO")->AsInteger, query->FieldByName("NAME")->AsString.c_str() ); int testscenario_no = query->FieldByName("TESTSCENARIO_NO")->AsInteger; TTreeNode *testcase_node = TestCaseTreeView->Items->AddObject(NULL, testcase_desc, (void *)testscenario_no); LoadTestCaseNodes(testcase_node); ++count; query->Next(); } GenerateTestTestCaseBtn->Caption = "Generate Test Case: " + m_currenttestcaseid; GenerateTestTestCaseBtn->Enabled = ( count > 0 ); delete query; TestCaseTreeView->Items->EndUpdate(); TestCaseTreeView->FullExpand(); /* also refresh the Test Steps tab */ TxnStepsQuery->SQL->Text = sql_statement; TxnStepsQuery->Open(); } } __finally { Screen->Cursor = Save_Cursor; } Allow = true; } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseQueryAfterClose(TDataSet *DataSet) { TestScenarioToolBar->Enabled = false; AddTestCaseNode->Enabled = false; // InitTxnBtn->Enabled = false; // GenerateAllTxnsBtn->Enabled = false; } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseQueryAfterOpen(TDataSet *DataSet) { TestScenarioToolBar->Enabled = true; AddTestCaseNode->Enabled = true; // InitTxnBtn->Enabled = true; // GenerateAllTxnsBtn->Enabled = true; } //--------------------------------------------------------------------------- void __fastcall TMainForm::SequenceGeneratorQueryAfterInsert( TDataSet *DataSet) { DataSet->FieldByName("PROJECT_CODE")->AsString = m_currentproject; DataSet->FieldByName("ITERATION")->AsInteger = m_currentiteration; } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseQueryBeforePost(TDataSet *DataSet) { DataSet->FieldByName("USECASE_ID")->AsString = DataSet->FieldByName("TESTCASE_ID")->AsString; if( DataSet->FieldByName("CASE_REPEAT")->AsInteger < 1) DataSet->FieldByName("CASE_REPEAT")->AsInteger = 1; if( DataSet->FieldByName("REPEAT_DELAY")->AsInteger > 3600) DataSet->FieldByName("REPEAT_DELAY")->AsInteger = 3600; if( DataSet->FieldByName("BATCH_SIZE")->AsInteger < 1) DataSet->FieldByName("BATCH_SIZE")->AsInteger = 99; } //--------------------------------------------------------------------------- void __fastcall TMainForm::TxnStepsQueryBeforeClose(TDataSet *DataSet) { if (DataSet->State == dsEdit ) { DataSet->FieldByName("TESTCASE_ID")->AsString = m_currenttestcaseid; //DataSet->FieldByName("USECASE")->AsString = m_currenttestcaseid; //DataSet->FieldByName("PROJECT_CODE")->AsString = m_currentproject; //DataSet->FieldByName("ITERATION")->AsInteger = m_currentiteration; if( DataSet->FieldByName("REPEAT_COUNT")->AsInteger < 1) DataSet->FieldByName("REPEAT_COUNT")->AsInteger = 1; DataSet->Post(); } } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseTreeViewEditing(TObject *Sender, TTreeNode *Node, bool &AllowEdit) { if (Node->Level == 0) { AllowEdit = true; } else { AllowEdit = false; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseTreeViewEdited(TObject *Sender, TTreeNode *Node, AnsiString &S) { // We've enable editing of the root level only, but we'll check anyway. if (Node->Level == 0) { const int testscenario_no = (int)(Node->Data); TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sql_statement; AnsiString name; sql_statement.sprintf( "UPDATE TEST_SCENARIOS SET NAME='%s' WHERE TESTSCENARIO_NO=%d", Utilities::EscapeString( getNameFromNode( name, S ) ).c_str(), testscenario_no ); query->SQL->Text = sql_statement; Data_Module->IntegrationDBConnection->BeginTrans(); try { query->ExecSQL(); Data_Module->IntegrationDBConnection->CommitTrans(); } catch ( ... ) { Data_Module->IntegrationDBConnection->RollbackTrans(); } } __finally { delete query; } } } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestScenarioPropertiesClick(TObject *Sender) { TestScenarioPropertiesForm->ShowForm( m_testscenario_no ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseTreeViewContextPopup(TObject *Sender, TPoint &MousePos, bool &Handled) { TTreeView * view = dynamic_cast< TTreeView * >( Sender ); if ( view ) { TTreeNode * Node = view->GetNodeAt( MousePos.x, MousePos.y ); const TPoint screen = TestCaseTreeView->ClientToScreen( MousePos ); if ( Node ) { switch ( Node->Level ) { case 0: // Rebuild the transaction templates, they may have changed. buildTransactionTemplates( m_transactionTemplates, m_currentproject, m_currentiteration ); ApplyTemplatesToScenario->Enabled = ( m_transactionTemplates.haveTemplatesForScenario( reinterpret_cast< int >( Node->Data ) ) ); ScenarioPopupMenu->Tag = reinterpret_cast< int >( Node->Data ); ScenarioPopupMenu->Popup( screen.x, screen.y ); break; case 1: TransactionPopupMenu->Popup( screen.x, screen.y ); break; } } } } //--------------------------------------------------------------------------- void __fastcall TMainForm::DeleteScenarioChildren(int testscenario_no) { bool refresh_testcases = false; TADOQuery *query = new TADOQuery(this); AnsiString sql_statement; query->Connection = Data_Module->IntegrationDBConnection; try { Data_Module->IntegrationDBConnection->BeginTrans(); sql_statement.sprintf( "DELETE FROM TXNSPEC_VALUES WHERE TESTSCENARIO_NO=%d", testscenario_no ); query->SQL->Text = sql_statement; query->ExecSQL(); sql_statement=""; sql_statement.sprintf( "DELETE FROM TRANSACTION_SPECIFICATION WHERE TESTSCENARIO_NO=%d", testscenario_no ); query->SQL->Text = sql_statement; query->ExecSQL(); sql_statement=""; sql_statement.sprintf( "DELETE FROM ITERATION_PARAMS WHERE TESTSCENARIO_NO=%d", testscenario_no ); query->SQL->Text = sql_statement; query->ExecSQL(); //sql_statement=""; //sql_statement.sprintf( // "DELETE FROM TEST_SCENARIOS WHERE TESTSCENARIO_NO=%d", // testscenario_no ); //query->SQL->Text = sql_statement; //query->ExecSQL(); Data_Module->IntegrationDBConnection->CommitTrans(); //refresh_testcases = true; //ResequenceTestCases(current_node); } catch(...) { Data_Module->IntegrationDBConnection->RollbackTrans(); } delete query; /* if (refresh_testcases) { bool allow; TestCaseGridRowChanging(Sender, 0, 1, allow = true); } */ } //--------------------------------------------------------------------------- void __fastcall TMainForm::DeleteScenarioClick(TObject *Sender) { bool refresh_testcases = false; for ( unsigned selected_item=0; selected_itemSelectionCount; selected_item++ ) { TTreeNode * current_node = TestCaseTreeView->Selections[ selected_item ]; if ( current_node != NULL ) { if (current_node->Level == 0) // Remove Test Scenario { // Confirm deletion AnsiString message; message.sprintf( "Are you sure you want to delete test scenario '%s'?", current_node->Text ); if ( MessageDlg( message, mtConfirmation, TMsgDlgButtons() << mbYes << mbNo, 0 ) == mrYes ) { int testscenario_no = (int)(current_node->Data); TADOQuery *query = new TADOQuery(this); AnsiString sql_statement; query->Connection = Data_Module->IntegrationDBConnection; try { Data_Module->IntegrationDBConnection->BeginTrans(); sql_statement.sprintf( "DELETE FROM TXNSPEC_VALUES WHERE TESTSCENARIO_NO=%d", testscenario_no ); query->SQL->Text = sql_statement; query->ExecSQL(); sql_statement=""; sql_statement.sprintf( "DELETE FROM TRANSACTION_SPECIFICATION WHERE TESTSCENARIO_NO=%d", testscenario_no ); query->SQL->Text = sql_statement; query->ExecSQL(); sql_statement=""; sql_statement.sprintf( "DELETE FROM ITERATION_PARAMS WHERE TESTSCENARIO_NO=%d", testscenario_no ); query->SQL->Text = sql_statement; query->ExecSQL(); sql_statement=""; sql_statement.sprintf( "DELETE FROM TEST_SCENARIOS WHERE TESTSCENARIO_NO=%d", testscenario_no ); query->SQL->Text = sql_statement; query->ExecSQL(); Data_Module->IntegrationDBConnection->CommitTrans(); refresh_testcases = true; ResequenceTestCases(current_node); } catch(...) { Data_Module->IntegrationDBConnection->RollbackTrans(); } delete query; } } } } if (refresh_testcases) { bool allow; TestCaseGridRowChanging(Sender, 0, 1, allow = true); } } //--------------------------------------------------------------------------- void __fastcall TMainForm::TransactionValueGrid1BeforeContractNode( TObject *Sender, int ARow, int ARowReal, bool &Allow) { Allow = ( TransactionValueGrid->RealRow <= ARowReal ); } //--------------------------------------------------------------------------- const bool __fastcall TMainForm::isParent( const int & ordinal ) { return ( std::find( m_parents.begin(), m_parents.end(), ordinal ) != m_parents.end() ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::TransactionValueGridCanEditCell(TObject *Sender, int ARow, int ACol, bool &CanEdit) { #if INCLUDE_PARENTS /** * Use the real row as the ordinal number into the dataset. When the row * has children, it cannot be edited, otherwise it can. */ CanEdit = !isParent( TransactionValueGrid->RealRowIndex( ARow ) ); #endif } //--------------------------------------------------------------------------- void __fastcall TMainForm::TransactionValueGridGetDisplText( TObject *Sender, int ACol, int ARow, AnsiString &Value) { #if INCLUDE_PARENTS const int row = TransactionValueGrid->RealRowIndex( ARow ); if ( row > 0 ) { switch ( TransactionValueGrid->RealColIndex( ACol ) ) { case 2: // The value column. /** * Use the real row as the ordinal number into the dataset. When * the row has children, it cannot be edited, otherwise it can. */ if ( isParent( row ) ) { Value = "{...}"; } break; case 3: // The checkbox column. if ( isParent( row ) ) { Value = ""; } break; } } #endif } //--------------------------------------------------------------------------- void __fastcall TMainForm::TransactionGridRowChanging( TADOQuery & query, const char * structureName ) { TxnFieldComments->Lines->Clear(); FieldEnumValues->Clear(); FieldDatatype->Clear(); DocDataType->Clear(); IncludedInMac->Checked = false; if ( query.State != dsInactive && query.RecordCount ) { if (!m_schema_handle.empty()) { const int fieldtag = query.FieldByName("FIELDTAG")->AsInteger; string structure_handle; try { XMLSchema->Create(m_schema_handle.c_str(), structureName, m_currentiteration, structure_handle, NULL); string field_path = FindField(structure_handle, fieldtag); if (!field_path.empty()) { std::string fieldcomments; std::string datatype; std::string docdatatype; std::string includedInMac; XMLSchema->GetAttributeProperty(field_path, "comments", fieldcomments); TxnFieldComments->Lines->Add(fieldcomments.c_str()); XMLSchema->GetAttributeProperty(field_path, "datatype", datatype); FieldDatatype->Text = datatype.c_str(); XMLSchema->GetAttributeProperty(field_path, "docdatatype", docdatatype ); DocDataType->Text = docdatatype.c_str(); XMLSchema->GetAttributeProperty(field_path, "inMac", includedInMac ); IncludedInMac->Checked = ( includedInMac == "true" ); string valuemap; XMLSchema->GetAttributeProperty(field_path, "valuemap", valuemap); if (!valuemap.empty()) { vector enum_values; if (XMLSchema->GetEnumerationValues(m_schema_handle, valuemap.c_str(), enum_values)) { vector::iterator eitr = enum_values.begin(); while (eitr != enum_values.end()) { FieldEnumValues->AddItem( (*eitr).c_str(), NULL); ++eitr; } } } } } __finally { XMLSchema->Destroy( structure_handle ); } } } } //--------------------------------------------------------------------------- void __fastcall TMainForm::TransactionValueGridRowChanging(TObject *Sender, int OldRow, int NewRow, bool &Allow) { TransactionGridRowChanging( *TxnValuesQuery, m_structure_name.c_str() ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::HeaderStructureGridRowChanging(TObject *Sender, int OldRow, int NewRow, bool &Allow) { TransactionGridRowChanging( *TxnHeaderValuesQuery, g_headerStructure ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::HeaderStructureTabSheetShow(TObject *Sender) { TransactionGridRowChanging( *TxnHeaderValuesQuery, g_headerStructure ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::PayloadStructureTabSheetShow(TObject *Sender) { TransactionGridRowChanging( *TxnValuesQuery, m_structure_name.c_str() ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::MainStatusBarResize(TObject *Sender) { if ( m_progressBar ) { RECT Rect; MainStatusBar->Perform( SB_GETRECT, 0, (LPARAM)&Rect ); const int progressPanel = 1; int offset = 0; for ( int i = 0; i < progressPanel; i++ ) { offset += MainStatusBar->Panels->Items[ i ]->Width; } m_progressBar->resize( Rect.top, Rect.left + offset, MainStatusBar->Panels->Items[ progressPanel ]->Width, Rect.bottom - Rect.top ); } } //--------------------------------------------------------------------------- void __fastcall TMainForm::TransactionValueGridKeyDown(TObject *Sender, WORD &Key, TShiftState Shift) { if ( Key == 'F' ) { TShiftState mask; mask << ssCtrl; if ( Shift * mask == mask ) { TransactionValueGridFindDialog->Execute(); } } } //--------------------------------------------------------------------------- void __fastcall TMainForm::HeaderStructureGridKeyDown(TObject *Sender, WORD &Key, TShiftState Shift) { if ( Key == 'F' ) { TShiftState mask; mask << ssCtrl; if ( Shift * mask == mask ) { HeaderStructureGridFindDialog->Execute(); } } } //--------------------------------------------------------------------------- void __fastcall TMainForm::ImportTransactionActionExecute(TObject *Sender) { TTreeNode * currentNode = TestCaseTreeView->Selected; if ( currentNode ) { // Are we importing a scenario, or a single transaction? if ( currentNode->Level == 0 ) { const int testScenarioNumber = reinterpret_cast< int >( currentNode->Data ); } } } //--------------------------------------------------------------------------- void __fastcall TMainForm::buildExecutionSchedule( TransactionSpecification & transactionSpecification ) { TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "XPATH," "FIELDVALUE " "FROM " "TXNSPEC_VALUES " "WHERE " "TXNSPEC_NO=%d AND " "FIELDVALUE IS NOT NULL AND " "OBSOLETE=\'N\' " "ORDER BY " "ORDINAL", transactionSpecification.getTransactionSpecificationNumber() ); query->SQL->Text = sqlStatement; query->Open(); TransactionSpecificationValue * value = 0; while ( !query->Eof ) { value = &transactionSpecification.getTransactionField( query->FieldByName( "XPATH" )->AsString.c_str() ); value->setExpression( query->FieldByName( "FIELDVALUE" )->AsString.c_str() ); query->Next(); } } __finally { delete query; query = 0; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::buildExecutionSchedule( TestScenario & testScenario ) { TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "TRANSACTION_SPECIFICATION.TXNSPEC_NO AS TXNSPEC_NO," "TRANSACTION_SPECIFICATION.UDTYPE AS UDTYPE," "TRANSACTION_SPECIFICATION.UDSUBTYPE AS UDSUBTYPE," "MASS_TXNS.NAME AS NAME " "FROM " "TRANSACTION_SPECIFICATION," "MASS_TXNS " "WHERE " "TESTSCENARIO_NO=%d AND " "TRANSACTION_SPECIFICATION.PROJECT_CODE = MASS_TXNS.PROJECTCODE AND " "TRANSACTION_SPECIFICATION.ITERATION = MASS_TXNS.ITERATION AND " "TRANSACTION_SPECIFICATION.UDTYPE = MASS_TXNS.UDTYPE AND " "TRANSACTION_SPECIFICATION.UDSUBTYPE = MASS_TXNS.UDSUBTYPE " "ORDER BY " "SEQ_NO", testScenario.getScenarioNumber() ); query->SQL->Text = sqlStatement; query->Open(); TransactionSpecification * transaction = 0; while ( !query->Eof ) { transaction = &testScenario.getTransactionSpecification( query->FieldByName( "TXNSPEC_NO" )->AsInteger, query->FieldByName( "NAME" )->AsString.c_str() ); transaction->setUdType( query->FieldByName( "UDTYPE" )->AsInteger ); transaction->setUdSubtype( query->FieldByName( "UDSUBTYPE" )->AsInteger ); buildExecutionSchedule( *transaction ); query->Next(); } } __finally { delete query; query = 0; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::buildExecutionSchedule( Iteration & iteration, const std::string & testcaseId ) { TADOQuery * query = 0; try { query = new TADOQuery( this ); query->Connection = Data_Module->IntegrationDBConnection; AnsiString sqlStatement; sqlStatement.sprintf( "SELECT " "TESTSCENARIO_NO," "REPEAT_COUNT," "BATCH_SIZE," "NAME " "FROM " "TEST_SCENARIOS " "WHERE " "TESTCASE_ID=\'%s\' AND " "PROJECT_CODE=\'%s\' AND " "ITERATION=%d " "ORDER BY " "TESTCASE_SEQNO", Utilities::EscapeString( testcaseId ).c_str(), Utilities::EscapeString( iteration.getProjectCode() ).c_str(), iteration.getIterationId() ); query->SQL->Text = sqlStatement; query->Open(); TestScenario * scenario = 0; while ( !query->Eof ) { scenario = &iteration.getTestScenario( query->FieldByName( "TESTSCENARIO_NO" )->AsInteger ); /* scenario->setBatchSize( !query->FieldByName( "BATCH_SIZE" )->IsNull ? query->FieldByName( "BATCH_SIZE" )->AsInteger : 0 ); */ scenario->setBatchSize( 99 ); scenario->setRepeatCount( !query->FieldByName( "REPEAT_COUNT" )->IsNull ? query->FieldByName( "REPEAT_COUNT" )->AsInteger : 1 ); scenario->setScenarioName( query->FieldByName( "NAME" )->AsString.c_str() ); buildExecutionSchedule( *scenario ); query->Next(); } } __finally { delete query; query = 0; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::generateTransaction( std::vector< int > & scenarios ) { // GenerationPropertiesForm->Visible = true; // GenerationPropertiesForm->SendToBack(); if ( GenerationPropertiesForm->ShowModal() == mrOk ) { const bool generateHeaders = GenerationPropertiesForm->GenerateHeadersCheckBox->Checked; const std::string folder = GenerationPropertiesForm->GenerationFolderDirectoryEdit->Text.c_str(); const std::string batchPrefix = GenerationPropertiesForm->DrainFilePrefixEdit->Text.c_str(); const std::string batchSuffix = GenerationPropertiesForm->DrainFileSuffixEdit->Text.c_str(); //const bool buildManifest = GenerationPropertiesForm->BuildManifestCheckBox->Checked; //const std::string manifestPrefix = GenerationPropertiesForm->ManifestPrefixEdit->Text.c_str(); //const std::string manifestSuffix = GenerationPropertiesForm->ManifestSuffixEdit->Text.c_str(); const std::string securityServer = GenerationPropertiesForm->SecurityServerPipeEdit->Text.c_str(); const unsigned short keyNumber = GenerationPropertiesForm->KeyNumberEdit->Text.ToInt(); const unsigned short keyVersion = GenerationPropertiesForm->KeyVersionEdit->Text.ToInt(); const std::string pathmapTarget = GenerationPropertiesForm->PathmapTargetEdit->Text.c_str(); const int macAlgorithm = GenerationPropertiesForm->MacAlgorithmComboBox->ItemIndex; GenerationPropertiesForm->Visible = false; AnsiString testCase = TestCaseQuery->FieldByName( "TESTCASE_ID" )->AsString; const std::string manifestPrefix = testCase.c_str(); const std::string manifestSuffix = ".txt"; const bool buildManifest = true; /** Create a transaction stream into our generation folder, and generate the transactions into it. We need to know whether we have to prepend header (i.e., whether it is a .xdr which has a header, or a .devud which doesn't). */ const TCursor Save_Cursor = Screen->Cursor; bool transactionOpen = false; ICryptographicServerProxy * cryptographicServerProxy = 0; IMessageDigest * messageDigest = 0; IHash * hash = 0; AnsiString message; try { // firstly prepare for crypto MAC if ( m_securityWrapperFactory ) { cryptographicServerProxy = m_securityWrapperFactory ->createCryptographicServerProxy( securityServer.c_str() ); if ( cryptographicServerProxy ) { if ( cryptographicServerProxy->getModuleCount() ) { /** * We don't know which module will be used to compute the * MAC (security doesn't tell us), so until they do we * assume its the first module. */ const unsigned int serialNumber = cryptographicServerProxy->getSerialNumber( 0 ); /** We now need to turn the 4-byte serial number into an 8-byte diversifier. Apparently, we must do this by writing the serial number into the lower 4-bytes in big endian. An API is being added to crypto to do this: until it is there we need to do it ourselves. */ unsigned char buffer[ 8 ]; buffer[ 0 ] = 0; buffer[ 1 ] = 0; buffer[ 2 ] = 0; buffer[ 3 ] = 0; buffer[ 4 ] = ( serialNumber >> 24 ) & 0xFF; buffer[ 5 ] = ( serialNumber >> 16 ) & 0xFF; buffer[ 6 ] = ( serialNumber >> 8 ) & 0xFF; buffer[ 7 ] = ( serialNumber ) & 0xFF; messageDigest = m_securityWrapperFactory ->createMessageDigest( *cryptographicServerProxy, keyNumber, keyVersion, buffer, sizeof( buffer ) ); /** * If we need to compute the MAC by computing the MAC * of the SHA-1 hash, then we create the hash object * here. */ if ( macAlgorithm == 1 ) { hash = m_securityWrapperFactory->createHash(); } } else { MWARNING( "Cryptographic server has no modules." ); } } } Screen->Cursor = crHourGlass; Data_Module->IntegrationDBConnection->BeginTrans(); transactionOpen = true; TransactionStream stream(folder, batchPrefix, batchSuffix, buildManifest, manifestPrefix, manifestSuffix, pathmapTarget ); Iteration iteration( m_currentproject.c_str(), m_currentiteration, *XMLSchema->GetSchemaWrapperFactory(), *XMLSchema->GetSchema(), m_schema_handle ); DefinedVariableTable definedVariableTable; SequenceCollection sequences; TimeEstimate timeEstimate( *MainStatusBar->Panels->Items[ 0 ] ); EvaluationContext context(definedVariableTable, sequences, *m_progressBar, messageDigest, hash, cryptographicServerProxy, timeEstimate ); buildExecutionSchedule( iteration, testCase.c_str() ); loadLegacyVariables( definedVariableTable, m_currentproject.c_str(), iteration ); readSequences( sequences, m_currentproject.c_str(), m_currentiteration ); iteration.setBatchSize (TestCaseQuery->FieldByName( "BATCH_SIZE" )->Text.ToInt()); try { int count = 0; bool generated = false; time_t startTime; if ( scenarios.empty() ) { // generate for an entire test case // first setup the environment count = iteration.getTransactionCount(); iteration.setTestCaseName (m_currenttestcaseid.c_str()); iteration.setCaseRepeat (m_currentcaserepeat); iteration.setRepeatDelay (m_currentcasedelay); if (count > 0) { // now preapre the log file and progress bars message = DateToStr(Date()); stream.logToManifest (message.c_str(), false); message = "Generating for Test Case " + testCase + ". " + TestCaseQuery->FieldByName( "NAME" )->AsString ; stream.logToManifest (message.c_str(), false); message.sprintf("Each run will create %d transactions with batch size of %d",count,iteration.getBatchSize()); stream.logToManifest (message.c_str(), false); m_progressBar->open( count ); timeEstimate.start( count ); // now run the testcase multiple times generated = true; for ( int repeat = 1; repeat <= m_currentcaserepeat && generated; ++repeat ) { // first more logging and status bar info stream.logToManifest (" ", false); message.sprintf("run %d of %d started.",repeat,m_currentcaserepeat); stream.logToManifest (message.c_str(), true); message.sprintf("%s: run %d of %d in progress. %d transactions with batch size of %d", m_currenttestcaseid.c_str(),repeat,m_currentcaserepeat,count, iteration.getBatchSize()); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); // now the real thing: generate the test case startTime = time(NULL); if (!iteration.generate( stream, generateHeaders, context ) ) { generated = false; break; } timeEstimate.stop(); m_progressBar->close(); if (!generated) { // problems with the generation .. best we can do for now is report it in status bar and log message.sprintf("run %d encountered a problem." ,repeat); stream.logToManifest (message.c_str(), true); message.sprintf("%s: run %d of %d encountered a problem." , m_currenttestcaseid.c_str(),repeat, m_currentcaserepeat); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); } else { // last run was good so check if we have to do it again // but first update log message.sprintf("run %d completed. Elapsed time for run was %d seconds" , repeat, time(NULL) - startTime); stream.logToManifest (message.c_str(), true); if ( repeat < m_currentcaserepeat ) { // do it again but possibly wait here before starting next session for (int delayRepeat = m_currentcasedelay - (time(NULL) - startTime); delayRepeat > 0 ; --delayRepeat) { message.sprintf("%s: run %d of %d completed. Pausing generation for %d seconds" , m_currenttestcaseid.c_str(),repeat, m_currentcaserepeat, delayRepeat); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); Sleep (1000); } } else { // all done message.sprintf("%s: run %d of %d completed. " , m_currenttestcaseid.c_str(),repeat, m_currentcaserepeat); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); } } } } else { MessageDlg( "No transactions to generate", mtWarning, TMsgDlgButtons() << mbOK, 0 ); } } // end of test case generation else { // single test step generation // note code caters for a list of scenarios but the GUI should only deliver a list of 1 std::string batchName; TestScenario * scenario = 0; std::vector< int >::const_iterator where = scenarios.begin(); for ( where = scenarios.begin(); where != scenarios.end(); ++where ) { scenario = &iteration.findTestScenario( *where ); count += scenario->getTransactionCount(); } if (count > 0) { // now preapre the log file and progress bars message = DateToStr(Date()); stream.logToManifest (message.c_str(), false); message = "Generating for a single Test Step " ; stream.logToManifest (message.c_str(), false); message.sprintf("The step will create %d transactions with batch size of %d",count,iteration.getBatchSize()); stream.logToManifest (message.c_str(), false); m_progressBar->open( count ); timeEstimate.start( count ); generated = true; for ( where = scenarios.begin(); where != scenarios.end(); ++where ) { // first more logging and status bar info stream.logToManifest (" ", false); message.sprintf("test step started."); stream.logToManifest (message.c_str(), true); message.sprintf("test step generation in progress. %d transactions with batch size of %d", count, iteration.getBatchSize()); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); // for test step we setup the filename here not in the iteration class which caters for test cases scenario = &iteration.findTestScenario( *where ); batchName = scenario->buildBatchName (batchName, scenario->getScenarioName() ); stream.newBatch(iteration.getBatchSize(),batchName); // now the real thing: generate the test step startTime = time(NULL); if ( !scenario->generate( stream, generateHeaders, context ) ) { generated = false; // problems with the generation .. best we can do for now is report it in status bar and log message.sprintf("test step encountered a problem."); stream.logToManifest (message.c_str(), true); message.sprintf("generation for test step encountered a problem." ); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); break; } else { // all done message.sprintf("test step completed. Elapsed time for run was %d seconds",time(NULL) - startTime); stream.logToManifest (message.c_str(), true); message.sprintf("generation for test step completed." ); MainStatusBar->Panels->Items[ g_messagePanel ]->Text = message; Application->ProcessMessages(); } } } else { MessageDlg( "No transactions to generate", mtWarning, TMsgDlgButtons() << mbOK, 0 ); } } // generation complete so just finish off and tidy up if ( generated ) { writeSequences( sequences, m_currentproject.c_str(), m_currentiteration ); Data_Module->IntegrationDBConnection->CommitTrans(); transactionOpen = false; } } __finally { timeEstimate.stop(); m_progressBar->close(); } } __finally { if ( hash ) { m_securityWrapperFactory->destroyHash( *hash ); hash = 0; } if ( messageDigest ) { m_securityWrapperFactory ->destroyMessageDigest( *messageDigest ); messageDigest = 0; } if ( cryptographicServerProxy ) { m_securityWrapperFactory ->destroyCryptographicServerProxy( *cryptographicServerProxy ); cryptographicServerProxy = 0; } if ( transactionOpen ) { Data_Module->IntegrationDBConnection->RollbackTrans(); } Screen->Cursor = Save_Cursor; } } } //--------------------------------------------------------------------------- void __fastcall TMainForm::GenerateActionExecute(TObject *Sender) { TTreeNode * currentNode = 0; std::vector< int > scenarios; for ( unsigned selection=0; selectionSelectionCount; selection++ ) { currentNode = TestCaseTreeView->Selections[ selection ]; if ( currentNode ) { scenarios.push_back( reinterpret_cast< int >( currentNode->Data ) ); } } generateTransaction( scenarios ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::UdTransferBtnClick(TObject *Sender) { //UdTransferHistoryForm->Show(); } //--------------------------------------------------------------------------- void __fastcall TMainForm::FormCloseQuery(TObject *Sender, bool &CanClose) { CanClose = true; // Warn if there are transfer tasks currently running /*if( (m_transferManager != NULL) && (m_transferManager->IsTaskRunning()) ) { AnsiString msg = "There are UD transfers currently in progress. Quitting now will abort these tasks."; msg += "\nAre you sure you want to continue?"; if( MessageDlg( msg, mtWarning, TMsgDlgButtons() << mbYes << mbNo, 0 ) == mrNo ) { CanClose = false; } } */ } //--------------------------------------------------------------------------- void __fastcall TMainForm::TestCaseTreeViewKeyUp(TObject *Sender, WORD &Key, TShiftState Shift) { if( Key == VK_DELETE ) { bool deleteScenario = false; bool deleteTransaction = false; for( unsigned selected_item=0; selected_itemSelectionCount; selected_item++) { TTreeNode * current_node = TestCaseTreeView->Selections[selected_item]; if( current_node != NULL ) { if( current_node->Level == 0 ) { deleteScenario = true; } else if( current_node->Level == 1 ) { deleteTransaction = true; } } } if( deleteScenario ) { DeleteScenarioClick( Sender ); } if( deleteTransaction ) { DeleteTransactionActionExecute( Sender ); } } } //--------------------------------------------------------------------------- void __fastcall TMainForm::ValidateOldTestCaseCell(TObject *Sender, int OldRow, int OldCol, int NewRow, int NewCol, bool &Allow) { switch (OldCol) { case 3: // Repeats MainStatusBar->Panels->Items[ g_messagePanel ]->Text = "repeats finished"; Application->ProcessMessages(); break; case 4: // period MainStatusBar->Panels->Items[ g_messagePanel ]->Text = "period finished" + DBAdvStringGrid2->Cells[OldCol][OldRow]; Application->ProcessMessages(); if (StrToInt(DBAdvStringGrid2->Cells[OldCol][OldRow]) > 360) DBAdvStringGrid2->Cells[OldCol][OldRow] = "360"; DBAdvStringGrid2->Cells[OldCol][OldRow] = "33" ; // TestCaseQuery->Post(); break; case 5: // batch MainStatusBar->Panels->Items[ g_messagePanel ]->Text = "batch finished"; Application->ProcessMessages(); break; } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- void __fastcall TMainForm::ExitClick(TObject *Sender) { Close(); } void __fastcall TMainForm::AboutClick(TObject *Sender) { AboutForm->Show(); } //---------------------------------------------------------------------------