Files
comun/utile/Teste/facturare_unificat/test_s3_do_cauta.prg
Marius Mutu 8e022d332e #13: formular de facturare unificat - etapa curenta
Squash al branch-ului de lucru plan13-s2.

Clase: ofacturare (nucleul formularului unificat), ofacturare_comun,
ferestre_cere_date, ocomenzi, caut_ora (lista de preturi in combo-urile de
cautare), omodificari.

Programe: ofacturare impartit - ofacturare_antet, ofacturare_rutare_scriere si
ogrid_latimi sunt fisiere noi; oproceduri_facturare primeste discountul pe linie
si cota standard de TVA cand articolul nu are cota pe politica.

Documentatie: capcana SQLExec no_data_found, conventia de encoding, depanarea
testelor VFP si regulile de lucru - conflictele cu modificarile venite din alte
proiecte sunt rezolvate pastrand ambele parti.

Loguri de rulare a testelor scoase din versionare; testele raman.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PkyjGyrV2S7932om4kfSiK
2026-09-09 21:38:25 +03:00

402 lines
18 KiB
Plaintext

* test_s3_do_cauta.prg
* Headless: paritatea cautarilor de antet (do_cauta_* + do_verifica) intre calea veche (frm_date_factura /
* frm_date_aviz, metode in .vcx) si formularul unificat (frm_facturare_articole2 -> oAntetFacturare din
* ofacturare_antet.prg), cu dialogurile modale inlocuite de mock_caut_antet.prg si amessagebox de
* mock_amessagebox.prg.
*
* REZULTAT ASTEPTAT (declarat inainte de rulare):
* A. Pentru fiecare caz (metoda, tip, varianta) se construieste ACELASI poDate de doua ori (oDateFactura +
* aceleasi valori de intrare), se creeaza formularul vechi pe primul si unificatul pe al doilea, se
* apeleaza metoda pe fiecare si se compara amprenta: toate proprietatile poDate (AMEMBERS, camp cu camp,
* TRANSFORM), proprietatile de formular scrise de metode (nSoldLei, nSoldValuta, cgestiune_init, tooltip
* client), lista apelurilor catre dialoguri (nume + argumente - dovedeste ramura aleasa si parametrii:
* ex. caut_contract_facturare(id) pe factura vs (id,[3,4]) pe aviz; cCont 4111 / 357 / 461 la client),
* mesajele amessagebox (text + tip) si erorile VFP (numar + mesaj). Asteptat: IDENTIC pe toate cazurile, cu
* exceptia lui poDate.nract cand la Init calea veche a ars deja un numar (cascada de LostFocus) si unificatul
* nu - acolo se verifica tiparul (vechi>0, nou=0, neschimbat de metoda) si se normalizeaza doar acea cheie.
* B. Cazuri (tip -> metode), variante: NORMAL (id_client real), IDCLIENT0 (id_client = 0 -> mesaj "Nu ati
* ales clientul!" / "gestiunea"), SAMECLIENT (dialogul intoarce acelasi id_client -> listaid/descriere NU
* se golesc pe factura), BUTON0 (dialogul seteaza gnButon = 0 -> lucrare/sectie/venchelt pe factura
* pun Null, pe aviz (lucrare/sectie) pastreaza valoarea intoarsa), VALUTA0 (tip 9 fara valuta -> mesaj):
* - factura: 1: client(NORMAL,SAMECLIENT), fdoc, lucrare(NORMAL,BUTON0), sectie(NORMAL,BUTON0),
* venchelt(NORMAL,BUTON0), responsabil, verifica, altele(=nimic); 2: altele(->contract), contract(IDCLIENT0),
* gestiune_init; 3: client, altele(->comanda), comanda(IDCLIENT0); 4: altele(->avize), avize(IDCLIENT0);
* 5: valuta; 7: altele(->factura), factura(IDCLIENT0); 8: altele(->facturi); 9: facturi(VALUTA0,NORMAL);
* 45: altele(->locatii), locatii.
* - aviz: 21: client, altele(->comanda), comanda, lucrare(NORMAL,BUTON0), sectie(BUTON0), venchelt(BUTON0),
* responsabil, gestiune_init, fdoc; 22: client; 23: client, altele(->gestiune_dest), gestiune_dest(IDCLIENT0),
* politica; 24: altele(->avize); 25: client, comanda; 26: altele(->contract), contract; 28: client;
* 41: client, gestiune_dest; 42: client.
* C. Netestabil headless: focusul de dupa cautare (SetFocus fara Show - daca ridica eroare, eroarea e parte
* din amprenta si trebuie sa fie identica pe ambele cai); selectia reala din dialog (mock cu valoare fixa);
* raspunsul Oracle la pack_facturare.cauta_date_comanda (real, acelasi pe ambele cai).
* D. Neregresie calea veche: test_s3_neregresie_vechi.prg CURENT vs BACKUP (amprenta Init) - separat.
*
* Rulare: vfp9.exe -A -T "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_unificat\test_s3_do_cauta.prg"
* Log: D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_unificat\out\test_s3_do_cauta.log
* Mediu: ROA_CENTRAL / MARIUSM_AUTO; gnIdUtil = 8 (seriile pe utilizator); gnScadereStoc = 1; rezultat_serii
* real (creeaza_cursor_serii, numarul se dezaloca dupa fiecare caz) ca sa existe clb_serie_act pe ambele.
SET SAFETY OFF
SET TALK OFF
SET NOTIFY OFF
PUBLIC gcLog, gnFail, gnPass, gcCaz, gcErr, gcMockApeluri, gnMockIdPart, gnMockButon, gcBaza, gnDivergenteQ8
gcLog = "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_unificat\out\test_s3_do_cauta.log"
IF !DIRECTORY("D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_unificat\out")
MD "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_unificat\out"
ENDIF
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13) + CHR(10), gcLog)
gnFail = 0
gnPass = 0
gcCaz = ""
gcErr = ""
gcMockApeluri = ""
gnMockIdPart = 0
gnMockButon = 1
gnDivergenteQ8 = 0
ON ERROR DO AfErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
DO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_init_env_auto_roafacturare.prg" WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF TYPE('gnHandle') <> 'N' OR gnHandle <= 0
DO AfLog WITH "FAIL: conexiune Oracle esuata"
DO Final
ENDIF
* la nume duplicat castiga PRIMUL fisier din lista SET PROCEDURE, nu ultimul: mock-urile se pun in fata
LOCAL lcProc
lcProc = SET("PROCEDURE")
SET PROCEDURE TO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\mock_amessagebox.prg", "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_unificat\mock_caut_antet.prg", &lcProc
PUBLIC gcMockUltimMesaj, gnMockUltimTip
gcMockUltimMesaj = ""
gnMockUltimTip = 0
IF !actualizeaza_optiuni_program()
DO AfLog WITH "FAIL: actualizeaza_optiuni_program()"
DO Final
ENDIF
gnIdUtil = 8
goExecutor.oExecuta([begin pack_sesiune.set_Id_Util(?gnIdUtil); end;])
gnScadereStoc = 1
DO AfLog WITH "ENV OK, gnAn=" + TRANSFORM(gnAn) + " gnLuna=" + TRANSFORM(gnLuna) + " gnScadereStoc=" + TRANSFORM(gnScadereStoc)
SET PATH TO "D:\ROA\ROAFACTURARE\COMUN\utile\gridextras" ADDITIVE
* dovada ca ofacturare_antet.prg e incarcat de harness si ca mock-urile castiga rezolutia
DO Assert WITH TYPE('CREATEOBJECT("oAntetFacturare")') = 'O', "oAntetFacturare instantiabil (ofacturare_antet.prg in SET PROCEDURE)"
LOCAL loMock
loMock = caut_fdoc()
DO Assert WITH VARTYPE(loMock) = 'O' AND loMock.fel_document == "FEL MOCK", "mock caut_fdoc activ"
DO AfLog WITH "asertiuni initiale: pass=" + TRANSFORM(gnPass) + " fail=" + TRANSFORM(gnFail) + " erori=[" + gcErr + "]"
gcErr = ""
PRIVATE poDate, poGeneratorNumere, plVizibil, poDateGestiuneDest
plVizibil = .F.
poGeneratorNumere = CREATEOBJECT("oGeneratorNumere")
poDateGestiuneDest = CREATEOBJECT("oDateGestiune")
IF USED('crscursuri')
USE IN crscursuri
ENDIF
CREATE CURSOR crscursuri (curs N(12,4), nume_val C(10), multiplicator N(6))
DO creeaza_facturacrs WITH 'crsfactura'
SELECT *, CAST(NULL AS C(100)) AS gestiune FROM crsfactura INTO CURSOR crsfact_tmp READWRITE
USE IN crsfactura
SELECT * FROM crsfact_tmp INTO CURSOR crsfactura READWRITE
USE IN crsfact_tmp
* doi clienti reali (GetSoldClient si cauta_date_comanda cer id-uri existente)
PUBLIC gnIdClient1, gnIdClient2
gnIdClient1 = 0
gnIdClient2 = 0
IF SQLEXEC(gnHandle, "select min(id_part) as id1, max(id_part) as id2 from nom_parteneri", "crsclient") > 0
gnIdClient1 = NVL(crsclient.id1, 0)
gnIdClient2 = NVL(crsclient.id2, 0)
USE IN crsclient
ENDIF
DO AfLog WITH "clienti de test: " + TRANSFORM(gnIdClient1) + " / " + TRANSFORM(gnIdClient2)
* ---- factura ----
DO Caz WITH 1, "do_cauta_client", "NORMAL"
DO Caz WITH 1, "do_cauta_client", "SAMECLIENT"
DO Caz WITH 1, "do_cauta_fdoc", "NORMAL"
DO Caz WITH 1, "do_cauta_lucrare", "NORMAL"
DO Caz WITH 1, "do_cauta_lucrare", "BUTON0"
DO Caz WITH 1, "do_cauta_sectie", "NORMAL"
DO Caz WITH 1, "do_cauta_sectie", "BUTON0"
DO Caz WITH 1, "do_cauta_venchelt", "NORMAL"
DO Caz WITH 1, "do_cauta_venchelt", "BUTON0"
DO Caz WITH 1, "do_cauta_responsabil", "NORMAL"
DO Caz WITH 1, "do_verifica", "NORMAL"
DO Caz WITH 1, "do_cauta_altele", "NORMAL"
DO Caz WITH 2, "do_cauta_altele", "NORMAL"
DO Caz WITH 2, "do_cauta_contract", "IDCLIENT0"
DO Caz WITH 2, "do_cauta_gestiune_init", "NORMAL"
DO Caz WITH 3, "do_cauta_client", "NORMAL"
DO Caz WITH 3, "do_cauta_altele", "NORMAL"
DO Caz WITH 3, "do_cauta_comanda", "IDCLIENT0"
DO Caz WITH 4, "do_cauta_altele", "NORMAL"
DO Caz WITH 4, "do_cauta_avize", "IDCLIENT0"
DO Caz WITH 5, "do_cauta_valuta", "NORMAL"
DO Caz WITH 7, "do_cauta_altele", "NORMAL"
DO Caz WITH 7, "do_cauta_factura", "IDCLIENT0"
DO Caz WITH 8, "do_cauta_altele", "NORMAL"
DO Caz WITH 9, "do_cauta_facturi", "VALUTA0"
DO Caz WITH 9, "do_cauta_facturi", "NORMAL"
DO Caz WITH 45, "do_cauta_altele", "NORMAL"
DO Caz WITH 45, "do_cauta_locatii", "NORMAL"
* ---- aviz ----
DO Caz WITH 21, "do_cauta_client", "NORMAL"
DO Caz WITH 21, "do_cauta_altele", "NORMAL"
DO Caz WITH 21, "do_cauta_comanda", "NORMAL"
DO Caz WITH 21, "do_cauta_lucrare", "NORMAL"
DO Caz WITH 21, "do_cauta_lucrare", "BUTON0"
DO Caz WITH 21, "do_cauta_sectie", "BUTON0"
DO Caz WITH 21, "do_cauta_venchelt", "BUTON0"
DO Caz WITH 21, "do_cauta_responsabil", "NORMAL"
DO Caz WITH 21, "do_cauta_gestiune_init", "NORMAL"
DO Caz WITH 21, "do_cauta_fdoc", "NORMAL"
DO Caz WITH 22, "do_cauta_client", "NORMAL"
DO Caz WITH 23, "do_cauta_client", "NORMAL"
DO Caz WITH 23, "do_cauta_altele", "NORMAL"
DO Caz WITH 23, "do_cauta_gestiune_dest", "IDCLIENT0"
DO Caz WITH 23, "do_cauta_politica", "NORMAL"
DO Caz WITH 24, "do_cauta_altele", "NORMAL"
DO Caz WITH 25, "do_cauta_client", "NORMAL"
DO Caz WITH 25, "do_cauta_comanda", "NORMAL"
DO Caz WITH 26, "do_cauta_altele", "NORMAL"
DO Caz WITH 26, "do_cauta_contract", "NORMAL"
DO Caz WITH 28, "do_cauta_client", "NORMAL"
DO Caz WITH 41, "do_cauta_client", "NORMAL"
DO Caz WITH 41, "do_cauta_gestiune_dest", "NORMAL"
DO Caz WITH 42, "do_cauta_client", "NORMAL"
DO Final
*----------------------------------------------------------------------------------------
PROCEDURE Caz
LPARAMETERS tnTip, tcMetoda, tcVar
LOCAL llAviz, lcVechi, lcNou, lcBazaVechi, lcBazaNou, lcExclus
llAviz = INLIST(tnTip, 21, 22, 23, 24, 25, 26, 28, 29, 41, 42, 47)
gcCaz = "[tip=" + TRANSFORM(tnTip) + " " + tcMetoda + " " + tcVar + "] "
lcVechi = Amprenta(tnTip, llAviz, IIF(llAviz, 'frm_date_aviz', 'frm_date_factura'), tcMetoda, tcVar)
lcBazaVechi = gcBaza
lcNou = Amprenta(tnTip, llAviz, 'frm_facturare_articole2', tcMetoda, tcVar)
lcBazaNou = gcBaza
* proprietatile poDate care difera deja dupa Init (inainte de apel) tin de Init (focus headless), nu de
* metoda testata: cand e exact divergenta Q8 (nract ars la Init pe calea veche) se verifica tiparul si se
* normalizeaza in loc sa se excluda, ca sa ramana comparat tot restul amprentei, inclusiv nract dupa apel
lcExclus = CheiDiferite(lcBazaVechi, lcBazaNou)
IF !EMPTY(lcExclus)
DO AfLog WITH " > " + gcCaz + "INIT-DIF (Q8, normalizat, nu exclus): " + lcExclus
lcVechi = NormalizeazaInitDifQ8(lcVechi, lcNou, lcBazaVechi, lcBazaNou, lcExclus)
ENDIF
IF lcVechi == lcNou
gnPass = gnPass + 1
DO AfLog WITH "OK " + gcCaz + TRANSFORM(OCCURS(CHR(10), lcVechi)) + " linii amprenta"
ELSE
gnFail = gnFail + 1
DO AfLog WITH "FAIL " + gcCaz + "amprente diferite:"
DO DifLinii WITH lcVechi, lcNou
ENDIF
ENDPROC
FUNCTION NormalizeazaInitDifQ8
* Q8: pe calea veche, cascada de LostFocus de la Init arde un numar inainte ca metoda testata sa ruleze;
* pe calea unificata nu se aloca nimic. Se verifica tiparul (nu doar cheia nract, ci si valorile) si ca
* metoda testata nu mai atinge nract pe nicio cale, apoi se normalizeaza doar nract, restul ramane comparat.
LPARAMETERS tcVechi, tcNou, tcBazaVechi, tcBazaNou, tcExclus
LOCAL lnBazaVechi, lnBazaNou, lnFinalVechi, lnFinalNou, lcVechiNorm
DO Assert WITH tcExclus == "poDate.nract=(vechi " + ValoareCheieDC(tcBazaVechi, "poDate.nract") + " / nou " + ValoareCheieDC(tcBazaNou, "poDate.nract") + "), ", "Q8: singura cheie care difera la Init e poDate.nract, nu altceva"
lnBazaVechi = VAL(ValoareCheieDC(tcBazaVechi, "poDate.nract"))
lnBazaNou = VAL(ValoareCheieDC(tcBazaNou, "poDate.nract"))
DO Assert WITH lnBazaVechi > 0, "Q8: la Init, pe calea veche nract e deja ars (cascada de LostFocus)"
DO Assert WITH lnBazaNou = 0, "Q8: la Init, pe calea unificata nract ramane 0"
lnFinalVechi = VAL(ValoareCheieDC(tcVechi, "poDate.nract"))
lnFinalNou = VAL(ValoareCheieDC(tcNou, "poDate.nract"))
DO Assert WITH lnFinalVechi = lnBazaVechi, "Q8: metoda testata nu mai modifica nract pe calea veche fata de Init"
DO Assert WITH lnFinalNou = lnBazaNou, "Q8: metoda testata nu mai modifica nract pe calea unificata fata de Init"
gnDivergenteQ8 = gnDivergenteQ8 + 1
DO AfLog WITH "DIVERGENTA-ASTEPTATA (Q8): " + gcCaz + "la Init, calea veche a ars deja un numar (nract=" + TRANSFORM(lnBazaVechi) + "), unificatul nu a alocat nimic (nract=0); neschimbat de metoda testata"
lcVechiNorm = STRTRAN(tcVechi, "poDate.nract=" + TRANSFORM(lnFinalVechi) + CHR(13) + CHR(10), "poDate.nract=" + TRANSFORM(lnFinalNou) + CHR(13) + CHR(10), 1, 1)
RETURN lcVechiNorm
ENDFUNC
FUNCTION ValoareCheieDC
* valoarea unei chei "cheie=valoare" dintr-o amprenta poDate, cautata linie cu linie
LPARAMETERS tcAmprenta, tcCheie
LOCAL laL[1], lnL, i
lnL = ALINES(laL, tcAmprenta)
FOR i = 1 TO lnL
IF LEFT(laL[i], LEN(tcCheie) + 1) == tcCheie + "="
RETURN SUBSTR(laL[i], LEN(tcCheie) + 2)
ENDIF
ENDFOR
RETURN "<lipsa>"
ENDFUNC
FUNCTION Amprenta
LPARAMETERS tnTip, tlAviz, tcClasa, tcMetoda, tcVar
LOCAL loF, lcA, lcCmd
poDate = NULL
poDate = CREATEOBJECT("oDateFactura", 25000 + tnTip, tnTip)
poDate.nIdTipDoc = IIF(tlAviz, poDate.nIdTipDocAvizExpeditie, poDate.nIdTipDocFactura)
poGeneratorNumere.ResetNumere()
poDate.rezultat_serii = poGeneratorNumere.creeaza_cursor_serii(poDate.nIdTipDoc)
poDate.dataact = DATE(gnAn, gnLuna, 1)
poDate.dataireg = poDate.dataact
poDate.id_client = IIF(tcVar == "IDCLIENT0", 0, gnIdClient1)
poDate.nume_client = IIF(tcVar == "IDCLIENT0", "", "CLIENT INITIAL")
poDate.listaid = "999"
poDate.descriere = "DESCRIERE INITIALA"
poDate.text_aditional = "TEXT INITIAL"
IF tnTip = 9
poDate.id_valuta = IIF(tcVar == "VALUTA0", 0, 2)
ENDIF
gnMockIdPart = IIF(tcVar == "SAMECLIENT", gnIdClient1, gnIdClient2)
gnMockButon = IIF(tcVar == "BUTON0", 0, 1)
gnButon = 1
poDateGestiuneDest.Reset()
gcErr = ""
gcMockApeluri = ""
gcMockUltimMesaj = ""
gnMockUltimTip = 0
DO AfLog WITH " > " + gcCaz + "creez " + tcClasa
loF = CREATEOBJECT(tcClasa)
IF VARTYPE(loF) <> 'O'
RETURN "CREATEOBJECT " + tcClasa + " ESUAT" + CHR(13) + CHR(10) + gcErr
ENDIF
gcErr = ""
* focusul pleaca de pe controlul lasat de Init inainte de apel: pe frm_date_factura Init lasa focusul pe
* combo-ul fdoc, al carui LostFocus (do_schimba_tipdoc -> clb_serie_act.genereazaNumar) ar scrie poDate.nract
* la primul SetFocus din metoda testata; efectul tine de evenimentele formularului, nu de metoda.
* Doar pe factura: pe aviz vechiul nu are combo, iar pe unificat Clb_dataact.LostFocus ar scrie datascad (S3-3)
IF !tlAviz
loF.clb_dataact.SetFocus()
ENDIF
gcBaza = AmprentaPoDate()
gcMockApeluri = ""
gcErr = ""
lcCmd = "loF." + tcMetoda + "()"
DO AfLog WITH " > " + gcCaz + "apelez " + lcCmd
&lcCmd
DO AfLog WITH " > " + gcCaz + "apel incheiat"
lcA = "metoda=" + tcMetoda + CHR(13) + CHR(10)
lcA = lcA + AmprentaPoDate()
* soldul exista doar pe frm_date_factura si pe unificat; pe aviz unificatul nu trebuie sa-l scrie
IF PEMSTATUS(loF, "nSoldLei", 5)
IF tlAviz
DO Assert WITH loF.nSoldLei = 0 AND loF.nSoldValuta = 0, "pe aviz nSoldLei/nSoldValuta raman 0 (" + tcClasa + ")"
DO AfLog WITH " > " + gcCaz + "sold pe " + tcClasa + ": " + TRANSFORM(loF.nSoldLei) + "/" + TRANSFORM(loF.nSoldValuta)
ELSE
lcA = lcA + "form.nSoldLei=" + TRANSFORM(loF.nSoldLei) + CHR(13) + CHR(10)
lcA = lcA + "form.nSoldValuta=" + TRANSFORM(loF.nSoldValuta) + CHR(13) + CHR(10)
ENDIF
ENDIF
lcA = lcA + "form.cgestiune_init=" + TRANSFORM(loF.cgestiune_init) + CHR(13) + CHR(10)
lcA = lcA + "form.tooltip_client=" + TRANSFORM(loF.Ct_clb_nume_client.clb_TX_CAUTARE.text_SIMPLU1.ToolTipText) + CHR(13) + CHR(10)
lcA = lcA + "gest_dest=" + TRANSFORM(poDateGestiuneDest.id_gestiune) + "|" + TRANSFORM(poDateGestiuneDest.id_tipgest) + "|" + TRANSFORM(poDateGestiuneDest.Cont) + "|" + TRANSFORM(poDateGestiuneDest.acont) + CHR(13) + CHR(10)
lcA = lcA + "gnButon=" + TRANSFORM(gnButon) + CHR(13) + CHR(10)
lcA = lcA + "APELURI:" + CHR(13) + CHR(10) + gcMockApeluri
lcA = lcA + "MESAJ=" + gcMockUltimMesaj + "|" + TRANSFORM(gnMockUltimTip) + CHR(13) + CHR(10)
lcA = lcA + "ERORI:" + CHR(13) + CHR(10) + gcErr
loF.Release()
RELEASE loF
IF poDate.rezultat_serii <> 0
poGeneratorNumere.dezaloca_numar(poDate.nIdTipDoc)
ENDIF
RETURN lcA
ENDFUNC
FUNCTION AmprentaPoDate
LOCAL laM[1], lnN, i, lcA, lcV
lcA = ""
lnN = AMEMBERS(laM, poDate, 0)
ASORT(laM)
FOR i = 1 TO lnN
IF TYPE("poDate." + laM[i]) $ "CNDTLY"
lcV = TRANSFORM(EVALUATE("poDate." + laM[i]))
ELSE
lcV = "<" + TYPE("poDate." + laM[i]) + ">"
ENDIF
lcA = lcA + "poDate." + LOWER(laM[i]) + "=" + lcV + CHR(13) + CHR(10)
ENDFOR
RETURN lcA
ENDFUNC
FUNCTION CheiDiferite
* cheile (poDate.x=) ale liniilor care difera intre doua amprente poDate, cu valorile, separate prin virgula
LPARAMETERS tcV, tcN
LOCAL laV[1], laN[1], lnV, lnN, i, lcChei, lcCheie, lcLinie
lnV = ALINES(laV, tcV)
lnN = ALINES(laN, tcN)
lcChei = ""
FOR i = 1 TO MAX(lnV, lnN)
IF i > lnV OR i > lnN OR !(laV[i] == laN[i])
lcLinie = IIF(i <= lnV, laV[i], laN[i])
lcCheie = LEFT(lcLinie, AT("=", lcLinie))
IF !(lcCheie + "(" $ lcChei)
lcChei = lcChei + lcCheie + "(vechi " + IIF(i <= lnV, SUBSTR(laV[i], LEN(lcCheie) + 1), "<lipsa>") ;
+ " / nou " + IIF(i <= lnN, SUBSTR(laN[i], LEN(lcCheie) + 1), "<lipsa>") + "), "
ENDIF
ENDIF
ENDFOR
RETURN lcChei
ENDFUNC
FUNCTION FaraChei
* scoate dintr-o amprenta liniile a caror cheie (pana la =) apare in lista de chei
LPARAMETERS tcA, tcChei
LOCAL laL[1], lnL, i, lcR, lnEq
lnL = ALINES(laL, tcA)
lcR = ""
FOR i = 1 TO lnL
lnEq = AT("=", laL[i])
IF lnEq = 0 OR !(LEFT(laL[i], lnEq) + "(" $ tcChei)
lcR = lcR + laL[i] + CHR(13) + CHR(10)
ENDIF
ENDFOR
RETURN lcR
ENDFUNC
PROCEDURE DifLinii
LPARAMETERS tcV, tcN
LOCAL laV[1], laN[1], lnV, lnN, i, lnMax
lnV = ALINES(laV, tcV)
lnN = ALINES(laN, tcN)
lnMax = MAX(lnV, lnN)
FOR i = 1 TO lnMax
IF i > lnV OR i > lnN OR !(laV[i] == laN[i])
DO AfLog WITH " vechi: " + IIF(i <= lnV, laV[i], "<lipsa>")
DO AfLog WITH " nou : " + IIF(i <= lnN, laN[i], "<lipsa>")
ENDIF
ENDFOR
ENDPROC
PROCEDURE Assert
LPARAMETERS tlCond, tcMsg
IF tlCond
gnPass = gnPass + 1
ELSE
gnFail = gnFail + 1
DO AfLog WITH "FAIL: " + gcCaz + tcMsg
ENDIF
ENDPROC
PROCEDURE AfLog
LPARAMETERS tcMsg
STRTOFILE(tcMsg + CHR(13) + CHR(10), gcLog, 1)
ENDPROC
PROCEDURE AfErr
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
gcErr = gcErr + TRANSFORM(tnErr) + " " + tcMsg + CHR(13) + CHR(10)
ENDPROC
PROCEDURE Final
DO AfLog WITH "TOTAL pass=" + TRANSFORM(gnPass) + " fail=" + TRANSFORM(gnFail) + " divergente-asteptate(Q8)=" + TRANSFORM(gnDivergenteQ8)
DO AfLog WITH "END " + TTOC(DATETIME())
QUIT
ENDPROC