* test_s11_reparatie_1472.prg * Proba reparatiei S11 (docs\raport_s11_reparatie_1472.md): confirma ca garda Nvl(...,[NULL]) * aplicata pe poArt.id_articol (ofacturare.vc2:19979) si poArt.id_jtva_coloana (ofacturare.vc2:19994, * in frm_facturare_articole2.do_scrie_articole) repara EROAREA 1472 pe documentul 630, fara sa * schimbe lcSql-ul pe randuri fara NULL pe aceste doua campuri (neregresie). * * Tipar identic cu test_s11_izolare_camp_1472.prg: mock pe goExecutor, NIMIC scris in Oracle, * document 630 incarcat REAL (IncarcaAntetFacturaEditare + IncarcaLiniiFacturaEditare), goExecutor * inlocuit cu mock DOAR dupa incarcare, inaintea do_scrie_articole(). * * PAS1 (regresia care conta): doc 630 BRUT (id_articol ramane NULL, ca in Oracle) - inainte de * reparatie VARTYPE(lcSql)='X' (control negativ, citat din * docs\raport_s11_cauza_1472_camp.md §4 PAS2-brut, nu s-a rerulat). Asteptam acum VARTYPE='C'. * PAS2 (neregresie, comparatie caracter-cu-caracter): acelasi scenariu ca PAS3 din * test_s11_izolare_camp_1472.prg (id_articol/id_jtva_coloana normalizate cu NVL(...,0), ca sa * nu mai fie NULL) - garda noua e un no-op pe valori ne-NULL, deci lcSql trebuie sa fie * IDENTIC, caracter cu caracter, cu sirul deja capturat inainte de reparatie * (docs\raport_s11_cauza_1472_camp.md §4 PAS3, citat mai jos ca literal). LPARAMETERS tnCaz SET SAFETY OFF SET TALK OFF PUBLIC gcErrLog, gnPass, gnFail PUBLIC poDate gcErrLog = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_s11_reparatie_1472_log_' + ; STRTRAN(STRTRAN(STRTRAN(TTOC(DATETIME()), '/', ''), ':', ''), ' ', '_') + '.txt' STRTOFILE('start ' + TRANSFORM(DATETIME()) + CHR(13) + CHR(10), gcErrLog) ON ERROR DO test_error_handler WITH ERROR(), MESSAGE(), PROGRAM(), LINENO() ON SHUTDOWN QUIT DO ('D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_init_env_auto_roafacturare.prg') WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT' IF gnHandle <= 0 STRTOFILE('EROARE: conectare esuata' + CHR(13) + CHR(10), gcErrLog, 1) QUIT ENDIF gnIdUtil = 8 SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\ofacturare_editare.prg ADDITIVE SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\ofacturare_rutare_scriere.prg ADDITIVE *!* la nume duplicat de procedura castiga PRIMUL fisier din lista SET PROCEDURE, nu ultimul LOCAL lcProcExistent lcProcExistent = SET("PROCEDURE") SET PROCEDURE TO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\mock_amessagebox.prg", &lcProcExistent LOCAL lcPathVechi, lcPathNou lcPathVechi = SET("PATH") lcPathNou = 'D:\ROA\ROAFACTURARE\COMUN\Utile\Teste\achizitie_import\stub_verificare;' + lcPathVechi SET PATH TO &lcPathNou PUBLIC gnMockRaspuns, gcMockUltimMesaj, gnMockUltimTip gnMockRaspuns = 7 gcMockUltimMesaj = '' gnMockUltimTip = 0 gnPass = 0 gnFail = 0 PUBLIC gcSqlUltim, gcVartypeUltim gcSqlUltim = '' gcVartypeUltim = '' DO ProbaReparatie STRTOFILE('REZULTAT: ' + TRANSFORM(gnPass) + ' PASS / ' + TRANSFORM(gnFail) + ' FAIL' + CHR(13) + CHR(10), gcErrLog, 1) STRTOFILE('end ' + TRANSFORM(DATETIME()) + CHR(13) + CHR(10), gcErrLog, 1) QUIT *============================================================================================== PROCEDURE ProbaReparatie LOCAL lnIdV lnIdV = 630 LOCAL lnDiscRon, lnDiscVal lnDiscRon = 0 lnDiscVal = 0 poDate = IncarcaAntetFacturaEditare(lnIdV, @lnDiscRon, @lnDiscVal) DO asserteaza WITH '0a antetul documentului ' + TRANSFORM(lnIdV) + ' s-a incarcat', VARTYPE(poDate) = 'O', VARTYPE(poDate) IF VARTYPE(poDate) <> 'O' RETURN ENDIF IncarcaLiniiFacturaEditare(poDate, lnIdV) DO asserteaza WITH '0b liniile documentului ' + TRANSFORM(lnIdV) + ' s-au incarcat', ; USED('crsfactura') AND RECCOUNT('crsfactura') > 0, TRANSFORM(IIF(USED('crsfactura'), RECCOUNT('crsfactura'), -1)) IF !USED('crsfactura') OR RECCOUNT('crsfactura') = 0 RETURN ENDIF *!* curatare LOCALA (doar in RAM), identica cu test_s11_izolare_camp_1472.prg SELECT crsfactura REPLACE ALL explicatie WITH 'test-s11-izolare', serie WITH '', lot WITH '', opt_facturare WITH 0 IN crsfactura GO TOP IN crsfactura *!* PAS1: doc 630 BRUT (id_articol ramane NULL) - proba REGRESIEI CARE CONTA DO RuleazaCuMock WITH 'PAS1-brut-postfix' DO asserteaza WITH 'PAS1 lcSql BRUT (id_articol NULL, ca in Oracle) e text valid dupa reparatie (VARTYPE C)', gcVartypeUltim = 'C', gcVartypeUltim IF gcVartypeUltim = 'C' DO asserteaza WITH 'PAS1 lcSql contine apelul adauga_articol_factura', 'pack_facturare.adauga_articol_factura(' $ gcSqlUltim, gcSqlUltim ENDIF *!* PAS2: neregresie - acelasi scenariu ca PAS3 din test_s11_izolare_camp_1472.prg (id_articol, *!* id_jtva_coloana normalizate cu NVL(...,0)); garda e no-op pe valori ne-NULL, deci lcSql *!* trebuie sa fie IDENTIC caracter-cu-caracter cu sirul capturat INAINTE de reparatie *!* (docs\raport_s11_cauza_1472_camp.md §4 PAS3, citat literal, nu recalculat). SELECT crsfactura GO TOP IN crsfactura REPLACE ALL id_articol WITH NVL(id_articol,0), id_jtva_coloana WITH NVL(id_jtva_coloana,0) IN crsfactura GO TOP IN crsfactura DO RuleazaCuMock WITH 'PAS2-neregresie-normalizat' LOCAL lcAsteptatDinRaportInainteDeReparatie lcAsteptatDinRaportInainteDeReparatie = "begin pack_facturare.adauga_articol_factura(905,0,'','test-s11-izolare',NULL,0,0.0000,NULL,NULL,100.00,0,0,0,1.000,0.00,'',0.000000,1,0,0,0,0.0000,0,134,8,NULL,'',1.1900); end;" DO asserteaza WITH 'PAS2 lcSql (dupa reparatie, valori ne-NULL) e IDENTIC caracter-cu-caracter cu sirul din raportul dinainte de reparatie', ; ALLTRIM(gcSqlUltim) == ALLTRIM(lcAsteptatDinRaportInainteDeReparatie), 'CAPTURAT: ' + TRANSFORM(gcSqlUltim) STRTOFILE('PAS2 --- sirul asteptat (din raport, dinainte de reparatie) ---' + CHR(13) + CHR(10) + lcAsteptatDinRaportInainteDeReparatie + CHR(13) + CHR(10), gcErrLog, 1) STRTOFILE('PAS2 --- sirul capturat (dupa reparatie) ---' + CHR(13) + CHR(10) + TRANSFORM(gcSqlUltim) + CHR(13) + CHR(10), gcErrLog, 1) ENDPROC *============================================================================================== * RuleazaCuMock: apeleaza do_scrie_articole() cu goExecutor mockat, intoarce lcSql-ul (sau * diagnosticul VARTYPE) al APELULUI cu PCOUNT()=1 (adauga_articol_factura din Scan), plus * rollback pe conexiunea REALA dupa fiecare rulare (tranzactia ramane deschisa pe succes). *============================================================================================== PROCEDURE RuleazaCuMock LPARAMETERS tcPrefix LOCAL loForm, loMock, loExecutorReal, llReturn loForm = CREATEOBJECT('frm_facturare_articole2') IF TYPE('plRegenerareEditare') <> 'U' RELEASE plRegenerareEditare ENDIF loExecutorReal = goExecutor loMock = CREATEOBJECT('MockGoExecutorS11Reparatie') goExecutor = loMock llReturn = loForm.do_scrie_articole() goExecutor = loExecutorReal SQLROLLBACK(gnHandle) SQLSetProp(gnHandle, 'Transactions', 1) gcSqlUltim = loMock.cSqlArticolCapturat gcVartypeUltim = loMock.cVartypeArticol STRTOFILE(tcPrefix + ' do_scrie_articole()=' + TRANSFORM(llReturn) + ' VARTYPE(tcSql pe apelul articol)=' + gcVartypeUltim + CHR(13) + CHR(10), gcErrLog, 1) STRTOFILE(tcPrefix + ' --- lcSql capturat (apelul articol) ---' + CHR(13) + CHR(10) + TRANSFORM(gcSqlUltim) + CHR(13) + CHR(10), gcErrLog, 1) RELEASE loForm ENDPROC PROCEDURE asserteaza LPARAMETERS tcNume, tlConditie, tcValoare IF m.tlConditie gnPass = gnPass + 1 STRTOFILE('PASS ' + m.tcNume + CHR(13) + CHR(10), gcErrLog, 1) ELSE gnFail = gnFail + 1 STRTOFILE('FAIL ' + m.tcNume + ' (valoare: ' + TRANSFORM(m.tcValoare) + ')' + CHR(13) + CHR(10), gcErrLog, 1) ENDIF ENDPROC PROCEDURE test_error_handler LPARAMETERS tnError, tcMessage, tcProgram, tnLineNo STRTOFILE('EROARE ' + TRANSFORM(tnError) + ' [' + tcProgram + ':' + TRANSFORM(tnLineNo) + '] ' + tcMessage + CHR(13) + CHR(10), gcErrLog, 1) IF TYPE('gnHandle') = 'N' AND gnHandle > 0 SQLROLLBACK(gnHandle) SQLSetProp(gnHandle, 'Transactions', 1) ENDIF gnFail = gnFail + 1 STRTOFILE('REZULTAT: ' + TRANSFORM(gnPass) + ' PASS / ' + TRANSFORM(gnFail) + ' FAIL' + CHR(13) + CHR(10), gcErrLog, 1) STRTOFILE('end (eroare) ' + TRANSFORM(DATETIME()) + CHR(13) + CHR(10), gcErrLog, 1) QUIT ENDPROC *============================================================================================== * MockGoExecutorS11Reparatie: identic cu MockGoExecutorS11Izolare (test_s11_izolare_camp_1472.prg), * clasa distincta doar ca sa nu se coliziona cu cea din fisierul de izolare pe acelasi SET PROCEDURE. *============================================================================================== DEFINE CLASS MockGoExecutorS11Reparatie AS Custom cSqlArticolCapturat = '' cVartypeArticol = '' nApeluri = 0 cEroare = '' FUNCTION oExecute(tcSql) THIS.nApeluri = THIS.nApeluri + 1 LOCAL lcVartype lcVartype = VARTYPE(m.tcSql) IF THIS.nApeluri >= 3 THIS.cSqlArticolCapturat = TRANSFORM(m.tcSql) THIS.cVartypeArticol = m.lcVartype ENDIF RETURN 1 ENDFUNC FUNCTION oExecuta(tcSql, tcCursor) THIS.nApeluri = THIS.nApeluri + 1 IF VARTYPE(m.tcCursor) = 'C' AND !EMPTY(m.tcCursor) IF USED(m.tcCursor) USE IN (m.tcCursor) ENDIF CREATE CURSOR (m.tcCursor) (xdummy I) ENDIF RETURN .T. ENDFUNC FUNCTION oPrelucrareEroare() RETURN 'MockGoExecutorS11Reparatie: ' + THIS.cEroare ENDFUNC ENDDEFINE