|
| 1 | +\chapter{A \textit{Gekko} szoftver komponens} |
| 2 | + |
| 3 | +Bár a~\ref{sec:ch2-summary} fejezetben azt ígértem, hogy az adatiránynak megfelelő sorrendben mutatom be szoftver |
| 4 | +komponenseket, a \textit{Gekko} komponenes pedig egy opcionális nulladik lépés, ennek ellenére az utolsó komponens |
| 5 | +fejezetben ismertetem. |
| 6 | + |
| 7 | +Ennek legfőbb okai, hogy a \textit{Gekko} komponenes használata opcionális, és a~\ref{chp:reporter} fejezetben |
| 8 | +megismert szoftverkomponenshez hasonlóan egy külön parancsosori futtatható. |
| 9 | + |
| 10 | +A \textit{Gekko} komponenes célja, hogy egy megfelelő teszt generátor alkalmazást felhasználva, létrehozni egy olyan |
| 11 | +testcsomagot amely kompatibilis a teszt keretrendszerrel. Gyakorlatilag egy \textit{frontendet} biztosít különböző |
| 12 | +teszt generátorokhoz, melyek közül tartalmaz egy implementációt a \textit{Csmith}~\cite{csmith} teszt generátorhoz. |
| 13 | + |
| 14 | +Az eredeti ötlet egy egyszerű szkript megvalósítása volt, amely generál valamennyi tesztesetet |
| 15 | +\textit{Csmith-el}~\cite{csmith}, majd kimenetüket átkonvertálja a teszt keretrendszer által ismertre. Ennél azonban |
| 16 | +generikusabb és robosztusabb megoldást választottam. |
| 17 | + |
| 18 | +A generátor alkalmazás által létrehozott teszteseteket megvizsgálja egy vagy több ismert stabil fordítóprogrammal, hogy |
| 19 | +keletkezzen egy viszonyítási alap. Erre azért van szükség mert előfordulhat, hogy egy generált teszteset bizonyos |
| 20 | +fordítóprogramon lefordul másikon pedig nem. Az ilyen tesztek nem várt bukásokat eredményezhetnek a tesztelés alatt |
| 21 | +álló fordítóprogramot használva. Az ilyen típusú hibákat nehéz megtalálni így jobb elkerülni. |
| 22 | + |
| 23 | +A \textit{Gekko} komponens szoftver architektúrális szempontból fel van készítve arra, hogy egyéb teszt generátorokat |
| 24 | +is meg tudjon hajtani, a jelen implementáción túl. Ezt többek között a \textit{Python} által nyújtott \textit{Protocol} |
| 25 | +osztályokkal valósítottam meg, amik lehetővé teszik a \textit{Struktúrált típusosság} alkalmazását a \textit{Pythonban} |
| 26 | +megszokott \textit{Duck típusosság} helyett. Ennek használatával inheritencia nélkül, implicit módon lehet |
| 27 | +implementálni interfészeket, a típus korrektség megőrzése mellett. |
| 28 | + |
| 29 | +\newpage |
| 30 | + |
| 31 | +\section{A komponenes konfigurácjója} |
| 32 | + |
| 33 | + A \textit{Gekko} szoftver komponenes újrahasználja a~\ref{chp:config-manager} fejeyetben megismert |
| 34 | + \textit{ConfigManager} komponenst, és definiálja a saját konfigurációs fájl formátumát. |
| 35 | + |
| 36 | + A konfigurációs fájl az alábbi szekciókat támogatja: |
| 37 | + |
| 38 | + \begin{itemize} |
| 39 | + \item \textit{DEFAULT}: itt adahatóak meg \textit{Gekko} konfigurációi. A \verb|COMPILE_TIMEOUT| és a |
| 40 | + \verb|RUN_TIMEOUT| amik a verifikáló fordítóprogramok futás idejét, illetve a generált tesztek |
| 41 | + futásidejét korlátozzák. A \verb|PREFIX| kapcsolóval a generált tesztesetek nevének előtagja |
| 42 | + változtatható. A \verb|HOST_COMPILERS| pedig egy lista azokból a fordítóprogramokból amik a viszonyítási |
| 43 | + alapot fogják adni. |
| 44 | + \item \textit{CSMITH}: A jelenleg támogatott generátor kapcsolói. Itt adható meg az \verb|OPTIONS| kapcsolóval |
| 45 | + a program parancssori argumentumai. A \verb|TIMEOUT| kapcsolóval megszorítható a generátor futásideje egy |
| 46 | + időkeretbe. |
| 47 | + \item A további szekciókban a verfikáló fordítóprogramokat lehet felsorolni a \textit{DEFAULT} szekció |
| 48 | + \verb|HOST_COMPILERS| kapcsolója számára. Ezen szekciók kapcsolói, a \verb|COMPILER| ami a program |
| 49 | + elérési útvonala, a \verb|COMPILE_FLAGS| ami a fordítási kapcsolók megadására szolgál, és a |
| 50 | + \verb|LINK_FLAGS| ahol a szerkesztő program számára lehet kapcsolókat átadni. |
| 51 | + \end{itemize} |
| 52 | + |
| 53 | + A \textbf{\ref{fig:gekko-config}. ábrán} látható egy példa a konfigurációs fájlra. |
| 54 | + |
| 55 | +\section{A komponens felépítése} |
| 56 | + |
| 57 | + A \textit{workers} parancssori argumentummal finomhangolható, az egyidejűleg generált tesztesetek száma. Ez a |
| 58 | + kapcsoló szemantikailag nem összekeverndő, az összesen generálni kívánt tesztesetek számát szabályzó |
| 59 | + \textit{num-tests} kapcsolóval. |
| 60 | + |
| 61 | + A komponens a teszt keretrendszerhez hasonlóan egy aszinkron esemény hurokban fut. Az esemény hurkon egyszerre |
| 62 | + maximum a \textit{workers} kapcsoló által megadott mennyiségű egyidejű feladat fut. Ezt egy \textit{Szemafor} |
| 63 | + szabályozza amely csak a \textit{workers} parancssori argumentumnak megfelelő feladatot enged egyidejűleg futtatni. |
| 64 | + A \textit{Gekko} komponenes viszont egyszerre dupla annyi feladatot tesz fel az esemény hurokra mint amennyi |
| 65 | + egyidejűleg futhat. |
| 66 | + |
| 67 | + Erre azért van szükség, mert annyi teszteset generálásért felelős feladat jön létre, \\ amennyi a |
| 68 | + \textit{num-tests} értéke. Tehát a feladatok száma lineárisan nő, a generálandó tesztesetek számával. A korlátozás |
| 69 | + azért van, hogy a feladatok számából következő lineárisan növekvő tráigény, felülről korlátos legyen. Továbbá, ha |
| 70 | + gyorsabban regisztrálódnak feladatok az esemény hurkon mint ahogyan elfogynak, akkor a \textit{Szemaforért} is |
| 71 | + zárolási verseny alakulna ki, ezt az esetet is kizárja a felsőkorlát beiktatása. |
| 72 | + |
| 73 | + A \textit{Gekko} által futtatott aszinkron feladatok három alkomponensből állnak össze. Ezen komponensek |
| 74 | + \textit{UML Komponens diagramját} ábrázolja a \textbf{\ref{fig:gekko-uml}. ábra}. |
| 75 | + |
| 76 | + \begin{figure}[ht] |
| 77 | + \centering |
| 78 | + \hrule |
| 79 | + \begin{tikzpicture} |
| 80 | + \begin{umlcomponent}{Gekko} |
| 81 | + \umlbasiccomponent[y=3.3]{Transformer} |
| 82 | + \umlbasiccomponent[x=2]{EvaluationEngine} |
| 83 | + \umlbasiccomponent[x=4,y=3.3]{TestGenerator} |
| 84 | + |
| 85 | + \umlport{TestGenerator}{0} |
| 86 | + \umlrequiredinterface[interface=Config, with port]{TestGenerator} |
| 87 | + \umlprovidedinterface[interface=SSCTest, with port]{Transformer} |
| 88 | + |
| 89 | + \umlHVassemblyconnector[interface=TestCase, with port, anchor1=0, anchor2=-60, second arm]{EvaluationEngine}{TestGenerator} |
| 90 | + \umlVHassemblyconnector[interface=GoodTest, with port, anchor1=-120, anchor2=180, first arm]{Transformer}{EvaluationEngine} |
| 91 | + \end{umlcomponent} |
| 92 | + |
| 93 | + \umlHVHrelation{Gekko-east-port}{TestGenerator-east-interface} |
| 94 | + \umlHVHrelation{Transformer-west-interface}{Gekko-west-port} |
| 95 | + |
| 96 | + \umlport{Gekko}{0} |
| 97 | + \umlport{Gekko}{180} |
| 98 | + \end{tikzpicture} |
| 99 | + \hrule |
| 100 | + \caption{\label{fig:gekko-uml} \textit{Gekko UML Komponens} diagram} |
| 101 | + \end{figure} |
| 102 | + |
| 103 | + \newpage |
| 104 | + |
| 105 | + Az architektúra gyakorlatilag egy csővezeték felépítést követ. Fontos kiemelni, hogy ha a csővezetékben bárhol hiba |
| 106 | + keletkezik akkor a rendszer megpróbálja a folyamatot a csővezeték elejéről. Ezt maximum hatszor teszi meg, ha ennyi |
| 107 | + alkalommal nem sikerül tesztet generálni, akkor feltételezhetjük hogy egyéb, az alkalmazás működésén kívül eső |
| 108 | + probléma áll fent. Az újrapróbálkozás felső korlátja azt is jelenti, hogy a kért teszteseteknél előfordulhat, hogy |
| 109 | + kevesebbet generál az alkalmazás. A bementi konfiguráció alapján a \textit{Gekko} a következő lépés sorozatot |
| 110 | + hajtja végre, alkomponensek szerint: |
| 111 | + |
| 112 | + \begin{enumerate} |
| 113 | + \item Teszteset generálás. |
| 114 | + \item Teszteset verfikáció, a konfigurációban definiált fordítóprogramokkal. |
| 115 | + \item Verfikált teszteset transzformáció, a \textit{SuperSet} teszt keretrendszer formátumára. |
| 116 | + \end{enumerate} |
| 117 | + |
| 118 | + A komponensek számára a konfigurációt elérhetővé kell tenni egy globális helyen, ezt a feladatot |
| 119 | + \textbf{\ref{fig:gekko-uml}. ábrán} nem szereplő, \textit{Collector} komponens látja el. |
| 120 | + |
| 121 | + A \textit{Collector} komponens az alábbi fontos konfigurációkat teszi elérhetővé a konfigurációs fájlból |
| 122 | + beolvasottakon túl: |
| 123 | + |
| 124 | + \begin{itemize} |
| 125 | + \item A teszteset generáló objektumot, amelyen keresztül egy közös interfészen keresztül hívhatóak különböző |
| 126 | + teszteset generátorok. |
| 127 | + \item A verifikáló fordítóprogram objektumokat. |
| 128 | + \end{itemize} |
| 129 | + |
| 130 | + A komponens megvizsgálja a verifikáló fordítóprogramokat pár egyszerű invokációval, így megbizonyosdik róla hogy a |
| 131 | + parancssori argumentum interfészük a \textit{Gekko} által ismert. A komponens ezen felül több a futás során |
| 132 | + szükséges elérési útvonal létrehozásáról is gondoskodik, például a kimeneti mappájéról, és a \textit{log} fájlok |
| 133 | + mappájéról. |
| 134 | + |
| 135 | +\section{A \textit{Gekko} alkomponensei} |
| 136 | + |
| 137 | + Ahogyan azt a \textbf{\ref{fig:gekko-uml}. ábrán} láthattuk az első komponens a \textit{TestGenerator}. |
| 138 | + |
| 139 | + A \textit{TestGenerator} alkomponens az egyetlen publikus tagfüggvényén, a \textit{generate} függvényen keresztül |
| 140 | + generál egy tesztesetet. Ezt a konfigurációban megadott, teszteset generátor alkamazás alprocesszusban történő |
| 141 | + meghívásával teszi. |
| 142 | + |
| 143 | + A második komponenes az \textit{EvaluationEngine}, vagyis a kiértékelő komponens. Ez a komponens végzi a |
| 144 | + \textit{TestGenerator} által generált tesztesetek verfikációját. A konfigurációban megadott fordítóprogramokkal |
| 145 | + lefordítja a tesztesetet. |
| 146 | + |
| 147 | + Azonban itt nem fejezi be a munkát. A tény, hogy minden alkalmazott fordítoprogram tudott futtatható állományt |
| 148 | + generálni, még nem elég ahhoz, hogy meggyőzödjünk a teszteset helyességéről. |
| 149 | + |
| 150 | + A \textit{Csmith}~\cite{csmith} teszteset generáló program kimeneti forrásfájlai futásidejű tesztesetek. |
| 151 | + Kimenetükben egy ellenőrzőössszeget adnak vissza. Ennek az összegnek a helyességét kell verifikálni. Ennek |
| 152 | + tudatában, az \textit{EvaluationEngine} implementációja az összes tesztet le is futtatja, és az eredményüket |
| 153 | + ellenőrzi, hogy az elvárt ellenőrzőösszeget produkálják. |
| 154 | + |
| 155 | + Eltérés esetén a teszteset nem kerül felhasználásra és a csővezeték hibával megáll. Itt a fentebb említett módon |
| 156 | + történhet új tesztesettel újra próbálkozás. |
| 157 | + |
| 158 | + A harmadik alkomponens a \textit{Transformer}. Ahogyan azt az \textit{EvaluationEngine} kapcsán említettem a |
| 159 | + \textit{Csmith}~\cite{csmith} kimenete egy specifikus formátumban van. |
| 160 | + |
| 161 | + A formátum tartalmaz metainformációkat a generált tesztesetről, és a generáló programról. Ezek nagyon hasznos |
| 162 | + információk, mert nem kell a tesztesetet lefordított futtható állományát elmenteni, ha reprodukálni szeretnénk a |
| 163 | + bukást. Egyszerűen a metainformációból újra előállítható a teszteset. A \textit{Transformer} a következő |
| 164 | + metainformációkat tárolja el: |
| 165 | + |
| 166 | + \begin{itemize} |
| 167 | + \item A generáló alkalmazást, verziójával együtt. |
| 168 | + \item A generáló alkalmazás parancssori argumentumait. |
| 169 | + \item A \textit{Gekko} saját egyedi azonosítóját \textit{(hash)}. |
| 170 | + \item A tesztgeneráló által alkalmazott \textit{seed} érték, amely a véletlen generálást reprodukálhatóvá |
| 171 | + teszi. |
| 172 | + \end{itemize} |
| 173 | + |
| 174 | + A metainformációkat egy \textit{JSON}~\cite{json} fájlban tárolja a komponens. Az alábbi |
| 175 | + \textbf{\ref{fig:metadata-json}. ábrán} látható módon. |
| 176 | + |
| 177 | + \newpage |
| 178 | + |
| 179 | + \begin{figure}[ht] |
| 180 | + \centering |
| 181 | + \begin{minted}{json} |
| 182 | +{ |
| 183 | + "test_1.c": { |
| 184 | + "generator": "csmith 2.4.0", |
| 185 | + "options": "--no-argc --max-array-dim 5 --no-longlong --no-packed-struct -o test_1.c", |
| 186 | + "revision": "0ec6f1b", |
| 187 | + "seed": "15774984650604141557" |
| 188 | + } |
| 189 | +} |
| 190 | + \end{minted} |
| 191 | + \caption{\label{fig:metadata-json} Egy teszteset metainformációja \textit{JSON} formátumban} |
| 192 | + \end{figure} |
| 193 | + |
| 194 | + \subsection{Az alkomponens interfészek} |
| 195 | + |
| 196 | + A különböző alkomponensek egy-egy interfész rétegen keresztül kommunikálnak egymással. Ez az interfész réteg a |
| 197 | + \textit{Python} protokollokra építkezik. |
| 198 | + |
| 199 | + Ahogyan azt a fejezet elején is említettem a protokollokkal elérhető a \textit{struktúrált típusosság} |
| 200 | + öröklődés beveztése nélkül. Ez nagyban leegyszerűsíti a kódot, ugyanis elhagyhatók a \textit{Pythonban} |
| 201 | + megszokott \verb|@abstractmethod| függvény annotációk. |
| 202 | + |
| 203 | + Ezek elkerülése nem csak a kódolvashatóságon javít, hanem a futás időn is. Ez a javaulás elenyésző ugyan de |
| 204 | + attól még említésre méltó. A javulás annak köszönhető, hogy az \textit{abstract} annotációkat a |
| 205 | + \textit{Python}, mint ahogyan minden más konstrukciót is, futás időben értékeli ki. |
| 206 | + |
| 207 | + Ezzel szemben, a protokollokat a \textit{Python interpreter} futásidőben nem ellenőrzi. Az ellenőrzésükhöz |
| 208 | + szükség van egy harmadik féltől származó típus ellenőrző alkalmazásra. Például, \textit{mypy}~\cite{mypy}, |
| 209 | + \textit{pyright}~\cite{pyright}, \textit{ty}~\cite{ty}. |
| 210 | + |
| 211 | + A protokollok egy szoftverarchitektúrális szempontból, is előnyesek, mert egy tisztább megoldást kínálnak mint |
| 212 | + az egyébként \textit{Pythonban} elérhető \textit{abstract} osztályok. Mivel nem osztályok és nincs szükség |
| 213 | + öröklődésre, így adattagokat sosem kapnak az implementációk a protokolloktól. |
| 214 | + |
| 215 | + A protokollok hátránya egyedül a lefelé kasztolásnál jön elő, mert csak a \\ \verb|@runtime_checkable| |
| 216 | + annotációval ellátott protokollok tesztelhetők futásidőben. Erre a felhasználásra ideálisabb \textit{abstract} |
| 217 | + osztályokat alkalmazni. |
0 commit comments