tex: use listings w/ Fira Code for code+mono
This commit is contained in:
parent
9a28821207
commit
a94edf9310
60
tex/UTB.tex
60
tex/UTB.tex
@ -48,6 +48,38 @@
|
||||
\usepackage{colorprofiles}
|
||||
% \usepackage[a-2b,mathxmp]{pdfx}[2018/12/22]
|
||||
|
||||
\usepackage{fontspec}
|
||||
\setmonofont{Fira Code}[
|
||||
Scale=MatchLowercase,
|
||||
Contextuals=Alternate % Activate the calt feature
|
||||
]
|
||||
\usepackage{lstfiracode} % https://ctan.org/pkg/lstfiracode
|
||||
% listings settings.
|
||||
\lstset{
|
||||
style=FiraCodeStyle, % Use predefined FiraCodeStyle
|
||||
basicstyle=\linespread{0.8}\small\ttfamily, % Use \ttfamily for source code listings
|
||||
captionpos=b,
|
||||
keepspaces=true,
|
||||
inputencoding=utf8,
|
||||
upquote=true,
|
||||
showlines=true,
|
||||
emptylines=true,
|
||||
columns=fullflexible,
|
||||
showstringspaces=false
|
||||
}
|
||||
|
||||
% listings
|
||||
\AtBeginDocument{%
|
||||
\counterwithin{lstlisting}{section}
|
||||
\renewcommand{\thelstlisting}{%
|
||||
\ifnum\value{subsection}=0
|
||||
\thesection.\arabic{lstlisting}%
|
||||
\else
|
||||
\thesubsection.\arabic{lstlisting}%
|
||||
\fi
|
||||
}
|
||||
}
|
||||
|
||||
% for pdflatex only
|
||||
%\pdfminorversion=4
|
||||
%\pdfobjcompresslevel=0
|
||||
@ -91,6 +123,8 @@
|
||||
\captionsetup[figure]{belowskip=0pt}
|
||||
\captionsetup[table]{aboveskip=0pt}
|
||||
\captionsetup[table]{belowskip=5pt}
|
||||
\captionsetup[listing]{aboveskip=5pt}
|
||||
\captionsetup[listing]{belowskip=0pt}
|
||||
|
||||
|
||||
% =========================================================================== %
|
||||
@ -328,6 +362,18 @@
|
||||
\clearpage
|
||||
}
|
||||
|
||||
\def\seznamkodu{
|
||||
\clearpage
|
||||
\phantomsection
|
||||
\ifczech
|
||||
\addcontentsline{toc}{section}{Seznam kódů}
|
||||
\else \ifenglish
|
||||
\addcontentsline{toc}{section}{List of Listings}
|
||||
\fi
|
||||
\lstlistoflistings
|
||||
\clearpage
|
||||
}
|
||||
|
||||
% Příkaz pro vysázení seznamu tabulek
|
||||
\def\seznamtab{
|
||||
\clearpage
|
||||
@ -628,6 +674,7 @@
|
||||
|
||||
\def\thefigure{\arabic{figure}} % číslování obrázků typu (y)
|
||||
\def\thetable{\arabic{table}} % číslování tabulek typu (y)
|
||||
\def\thelstlisting{\arabic{listing}}
|
||||
\captiondelim{. } % změníme dvoutečku za Obr/Tab za tečku
|
||||
|
||||
% Nastavení číslování obrázků, tabulek i rovnic do formátu <číslo kapitoly>.<pořadové číslo>
|
||||
@ -640,11 +687,13 @@
|
||||
%{\renewcommand*\numberline[1]{Fig. \,#1\space}}
|
||||
%\renewcommand*\l@figure{\@dottedtocline{1}{0em}{5.0em}}
|
||||
%\renewcommand*\l@table{\@dottedtocline{1}{0em}{5.0em}}
|
||||
\def\l@lstlisting#1#2{\@dottedtocline{1}{0em}{5.0em}{\lstlistingname\space#1}{#2}}
|
||||
|
||||
% Vynulování čítačů
|
||||
\@addtoreset{table}{section}
|
||||
\@addtoreset{figure}{section}
|
||||
\@addtoreset{footnote}{section}
|
||||
\@addtoreset{lstlisting}{section}
|
||||
|
||||
\makeatother % a to je ukončení \makeatletter
|
||||
|
||||
@ -677,6 +726,8 @@
|
||||
\cftsetindents{subsubsec}{1cm}{1.5cm}
|
||||
\cftsetindents{fig}{0cm}{1.5cm}
|
||||
\cftsetindents{tab}{0cm}{1.5cm}
|
||||
\cftsetindents{lstlisting}{0cm}{1.5cm}
|
||||
\cftsetindents{listing}{0cm}{1.5cm}
|
||||
|
||||
% nastavení vodící čáry pro styl část, nadpis 1--3, obrázky a tabulky
|
||||
\renewcommand{\cftdot}{\ensuremath{.}} % tímto příkazem lze změnit vodící tečky v obsahu na jiný znak
|
||||
@ -686,11 +737,14 @@
|
||||
\renewcommand{\cftsubsubsecleader}{\cftdotfill{0.3}}
|
||||
\renewcommand{\cftfigleader}{\cftdotfill{0.3}}
|
||||
\renewcommand{\cfttableader}{\cftdotfill{0.3}}
|
||||
\renewcommand{\cftlstlistingleader}{\cftdotfill{0.3}}
|
||||
\renewcommand{\cftlistingleader}{\cftdotfill{0.3}}
|
||||
|
||||
% změna fontu pro text "Obsah", "Seznam obrázků" a "Seznam tabulek"
|
||||
\renewcommand{\cfttoctitlefont}{\normalsize\bfseries\thispagestyle{empty}}
|
||||
\renewcommand{\cftloftitlefont}{\normalsize\bfseries\thispagestyle{fancy}}
|
||||
\renewcommand{\cftlottitlefont}{\normalsize\bfseries\thispagestyle{fancy}}
|
||||
\renewcommand{\cftloltitlefont}{\normalsize\bfseries\thispagestyle{fancy}}
|
||||
|
||||
\renewcommand{\cfttabpresnum}{Tab. }
|
||||
\renewcommand{\cftfigaftersnum}{.}
|
||||
@ -810,13 +864,16 @@
|
||||
\addto\captionsczech{\renewcommand{\refname}{\MakeTextUppercase{Seznam použité literatury}}}
|
||||
\addto\captionsczech{\renewcommand{\listfigurename}{\MakeTextUppercase{Seznam obrázků}}}
|
||||
\addto\captionsczech{\renewcommand{\listtablename}{\MakeTextUppercase{Seznam tabulek}}}
|
||||
\renewcommand{\lstlistlistingname}{\MakeTextUppercase{Seznam kódů}}
|
||||
%\addto\captionsczech{\renewcommand{\figurename}{Obr.}}
|
||||
%\addto\captionsczech{\renewcommand{\tablename}{Tab.}}
|
||||
\renewcommand{\cftfigpresnum}{Obr. }
|
||||
\else \ifenglish
|
||||
\usepackage[UKenglish]{babel}
|
||||
\selectlanguage{english}
|
||||
\hyphenpenalty 5000
|
||||
% \hyphenpenalty 7000
|
||||
\hyphenpenalty 7000
|
||||
%\hyphenpenalty 9000
|
||||
% \hyphenpenalty 10000
|
||||
% \exhyphenpenalty 10000
|
||||
% Vlastni definice nazvu
|
||||
@ -824,6 +881,7 @@
|
||||
\addto\captionsenglish{\renewcommand{\refname}{\MakeTextUppercase{References}}}
|
||||
\addto\captionsenglish{\renewcommand{\listfigurename}{\MakeTextUppercase{List of Figures}}}
|
||||
\addto\captionsenglish{\renewcommand{\listtablename}{\MakeTextUppercase{List of Tables}}}
|
||||
\renewcommand{\lstlistlistingname}{List of Listings}
|
||||
%\addto\captionsenglish{\renewcommand{\figurename}{Fig.}}
|
||||
%\addto\captionsenglish{\renewcommand{\tablename}{Tab.}}
|
||||
\renewcommand{\cftfigpresnum}{Fig. }
|
||||
|
520
tex/text.tex
520
tex/text.tex
@ -2,14 +2,6 @@
|
||||
% Encoding: UTF-8 (žluťoučký kůň úpěl ďábelšké ódy)
|
||||
% =========================================================================== %
|
||||
|
||||
\vspace*{\fill}
|
||||
\begin{center}
|
||||
\Large
|
||||
\textit{This is a document draft.}
|
||||
\end{center}
|
||||
\vspace*{\fill}
|
||||
\newpage
|
||||
|
||||
% =========================================================================== %
|
||||
\nn{Introduction}
|
||||
Introduce the goals and the methods attempted to achieve the goals.
|
||||
@ -246,7 +238,7 @@ represents that a password is:
|
||||
\end{itemize}
|
||||
|
||||
\obr{Short arbitrary password length
|
||||
limit~\cite{larsklint}}{fig:forbiddencharacters}{.8}{graphics/arbitrarypasswdlengthlimit.jpg}
|
||||
limit~\cite{larsklint}}{fig:arbitrarypasswdlengthlimit}{.8}{graphics/arbitrarypasswdlengthlimit.jpg}
|
||||
|
||||
This is wrong for multiple reasons, and it is a classic example of short
|
||||
arbitrary length requirement. It essentially prevents users from using
|
||||
@ -616,22 +608,17 @@ reference.
|
||||
The validity of a signature on a particular commit can be viewed with git using
|
||||
the following commands (the \% sign denotes the shell prompt):
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{varwidth}{\linewidth}
|
||||
\begin{verbatim}
|
||||
\vspace{\parskip}
|
||||
\begin{lstlisting}[language=bash, caption={Verifying signature of a git commit},
|
||||
label=gitverif, basicstyle=\linespread{0.9}\footnotesize\ttfamily]
|
||||
% cd <cloned project dir>
|
||||
% git show --show-signature <commit>
|
||||
% # alternatively:
|
||||
% git verify-commit <commit>
|
||||
\end{verbatim}
|
||||
\end{varwidth}
|
||||
\caption{Verifying signature of a git commit}
|
||||
\label{fig:gitverif}
|
||||
\end{figure}
|
||||
\end{lstlisting}
|
||||
|
||||
There is one caveat to this though, git first needs some additional
|
||||
configuration for the code in Figure~\ref{fig:gitverif} to work as one would
|
||||
configuration for the code in Listing~\ref{gitverif} to work as one would
|
||||
expect. Namely that the public key used to verify the signature needs to be
|
||||
stored in git's ``allowed signers file'', then git needs to be told where that
|
||||
file is using the configuration value \texttt{gpg.ssh.allowedsignersfile} and
|
||||
@ -642,26 +629,20 @@ Because git allows the configuration values to be local to each repository,
|
||||
both of the mentioned issues can be solved by running the following commands
|
||||
from inside of the cloned repository:
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{varwidth}{\linewidth}
|
||||
\scriptsize
|
||||
\begin{verbatim}
|
||||
% # set the signature format for the local repository.
|
||||
% git config --local gpg.format ssh
|
||||
% # save the public key.
|
||||
% cat >./tmp/.allowed_signers \
|
||||
<<<'leo ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKwshTdBgLzwY4d8N7VainZCngH88OwvPGhZ6bm87rBO'
|
||||
% # set the allowed signers file path for the local repository.
|
||||
% git config --local gpg.ssh.allowedsignersfile=./tmp/.allowed_signers
|
||||
\end{verbatim}
|
||||
\end{varwidth}
|
||||
\caption{Prepare allowed signers file and signature format for git}
|
||||
\label{fig:gitsshprep}
|
||||
\end{figure}
|
||||
\vspace{\parskip}
|
||||
\begin{lstlisting}[language=bash, caption={Prepare allowed signers file and signature format for git},
|
||||
label=gitsshprep, basicstyle=\linespread{0.9}\footnotesize\ttfamily]
|
||||
% # set the signature format for the local repository.
|
||||
% git config --local gpg.format ssh
|
||||
% # save the public key.
|
||||
% cat >./tmp/.allowed_signers \
|
||||
<<<'leo ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKwshTdBgLzwY4d8N7VainZCngH88OwvPGhZ6bm87rBO'
|
||||
% # set the allowed signers file path for the local repository.
|
||||
% git config --local gpg.ssh.allowedsignersfile=./tmp/.allowed_signers
|
||||
\end{lstlisting}
|
||||
|
||||
After the code in Figure~\ref{fig:gitsshprep} is run, everything from the
|
||||
Figure~\ref{fig:gitverif} should remain applicable for the lifetime of the
|
||||
After the code in Listing~\ref{gitsshprep} is run, everything from the
|
||||
Listing~\ref{gitverif} should remain applicable for the lifetime of the
|
||||
repository or until git changes implementation of signature verification. The
|
||||
git \texttt{user.name} that can be seen on the commits in the \textbf{Author}
|
||||
field is named after the machine that was used to develop the program, since
|
||||
@ -725,7 +706,7 @@ and a 400Mbps downlink, software-wise running Arch with an author-flavoured
|
||||
Xanmod kernel version 6.3.x.
|
||||
|
||||
\obr{Drone CI median build
|
||||
time}{fig:drone-median-build}{.77}{graphics/drone-median-build}
|
||||
time}{fig:drone-median-build}{.84}{graphics/drone-median-build}
|
||||
|
||||
|
||||
\n{2}{Source code repositories}\label{sec:repos}
|
||||
@ -946,67 +927,62 @@ Section~\ref{sec:repos} for details). This enabled it to be independently
|
||||
developed and versioned, and only pulled into the main application whenever it
|
||||
is determined the application is ready for it.
|
||||
|
||||
The full schema with type annotations can be seen in
|
||||
Figure~\ref{fig:dhallschema}. The \texttt{let} statement declares a variable
|
||||
called \texttt{Schema} and assigns it the result of the expression on the right
|
||||
side of the equals sign, which has for practical reasons been trimmed and is
|
||||
displayed without the \emph{default} block, which is instead shown in its own
|
||||
Figure~\ref{fig:dhallschemadefaults}.
|
||||
The full schema with type annotations can be seen in Listing~\ref{dhallschema}.
|
||||
The \texttt{let} statement declares a variable called \texttt{Schema} and
|
||||
assigns it the result of the expression on the right side of the equals sign,
|
||||
which has for practical reasons been trimmed and is displayed without the
|
||||
\emph{default} block, which is instead shown in its own
|
||||
Listing~\ref{dhallschemadefaults}.
|
||||
|
||||
\begin{figure}[!h]
|
||||
\begin{varwidth}
|
||||
\scriptsize
|
||||
\begin{verbatim}
|
||||
let Schema =
|
||||
{ Type =
|
||||
{ Host : Text
|
||||
, Port : Natural
|
||||
, HTTP :
|
||||
{ Domain : Text
|
||||
, Secure : Bool
|
||||
, AutoTLS : Bool
|
||||
, TLSKeyPath : Text
|
||||
, TLSCertKeyPath : Text
|
||||
, HSTSMaxAge : Natural
|
||||
, ContentSecurityPolicy : Text
|
||||
, RateLimit : Natural
|
||||
, Gzip : Natural
|
||||
, Timeout : Natural
|
||||
}
|
||||
, Mailer :
|
||||
{ Enabled : Bool
|
||||
, Protocol : Text
|
||||
, SMTPAddr : Text
|
||||
, SMTPPort : Natural
|
||||
, ForceTrustServerCert : Bool
|
||||
, EnableHELO : Bool
|
||||
, HELOHostname : Text
|
||||
, Auth : Text
|
||||
, From : Text
|
||||
, User : Text
|
||||
, Password : Text
|
||||
, SubjectPrefix : Text
|
||||
, SendPlainText : Bool
|
||||
}
|
||||
, LiveMode : Bool
|
||||
, DevelMode : Bool
|
||||
, AppPath : Text
|
||||
, Session :
|
||||
{ CookieName : Text
|
||||
, CookieAuthSecret : Text
|
||||
, CookieEncrSecret : Text
|
||||
, MaxAge : Natural
|
||||
}
|
||||
, Logger : { JSON : Bool, Fmt : Optional Text }
|
||||
, Init : { CreateAdmin : Bool, AdminPassword : Text }
|
||||
, Registration : { Allowed : Bool }
|
||||
\vspace{\parskip}
|
||||
\begin{lstlisting}[language=Haskell, caption={Dhall configuration schema version 0.0.1-rc.2},
|
||||
label=dhallschema, basicstyle=\linespread{0.9}\footnotesize\ttfamily]
|
||||
let Schema =
|
||||
{ Type =
|
||||
{ Host : Text
|
||||
, Port : Natural
|
||||
, HTTP :
|
||||
{ Domain : Text
|
||||
, Secure : Bool
|
||||
, AutoTLS : Bool
|
||||
, TLSKeyPath : Text
|
||||
, TLSCertKeyPath : Text
|
||||
, HSTSMaxAge : Natural
|
||||
, ContentSecurityPolicy : Text
|
||||
, RateLimit : Natural
|
||||
, Gzip : Natural
|
||||
, Timeout : Natural
|
||||
}
|
||||
, Mailer :
|
||||
{ Enabled : Bool
|
||||
, Protocol : Text
|
||||
, SMTPAddr : Text
|
||||
, SMTPPort : Natural
|
||||
, ForceTrustServerCert : Bool
|
||||
, EnableHELO : Bool
|
||||
, HELOHostname : Text
|
||||
, Auth : Text
|
||||
, From : Text
|
||||
, User : Text
|
||||
, Password : Text
|
||||
, SubjectPrefix : Text
|
||||
, SendPlainText : Bool
|
||||
}
|
||||
, LiveMode : Bool
|
||||
, DevelMode : Bool
|
||||
, AppPath : Text
|
||||
, Session :
|
||||
{ CookieName : Text
|
||||
, CookieAuthSecret : Text
|
||||
, CookieEncrSecret : Text
|
||||
, MaxAge : Natural
|
||||
}
|
||||
, Logger : { JSON : Bool, Fmt : Optional Text }
|
||||
, Init : { CreateAdmin : Bool, AdminPassword : Text }
|
||||
, Registration : { Allowed : Bool }
|
||||
}
|
||||
\end{verbatim}
|
||||
\end{varwidth}
|
||||
\caption{Dhall configuration schema version 0.0.1-rc.2}
|
||||
\label{fig:dhallschema}
|
||||
\end{figure}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
The main configuration is comprised of both raw attributes and child records,
|
||||
which allow for grouping of related functionality. For instance, configuration
|
||||
@ -1020,6 +996,75 @@ while \textbf{true} is evaluated as an \emph{unbound} variable, that is, a
|
||||
variable \emph{not} defined in the current \emph{scope} and thus not
|
||||
\emph{present} in the current scope.
|
||||
|
||||
\vspace{\parskip}
|
||||
\begin{lstlisting}[language=Haskell, caption={Dhall configuration defaults for
|
||||
schema version 0.0.1-rc.2},
|
||||
label=dhallschemadefaults, basicstyle=\linespread{0.9}\scriptsize\ttfamily]
|
||||
, default =
|
||||
-- | have sane defaults.
|
||||
{ Host = ""
|
||||
, Port = 3000
|
||||
, HTTP =
|
||||
{ Domain = ""
|
||||
, Secure = False
|
||||
, AutoTLS = False
|
||||
, TLSKeyPath = ""
|
||||
, TLSCertKeyPath = ""
|
||||
, HSTSMaxAge = 0
|
||||
, ContentSecurityPolicy = ""
|
||||
, RateLimit = 0
|
||||
, Gzip = 0
|
||||
, Timeout = 0
|
||||
}
|
||||
, Mailer =
|
||||
{ Enabled = False
|
||||
, Protocol = "smtps"
|
||||
, SMTPAddr = ""
|
||||
, SMTPPort = 465
|
||||
, ForceTrustServerCert = False
|
||||
, EnableHELO = False
|
||||
, HELOHostname = ""
|
||||
, Auth = ""
|
||||
, From = ""
|
||||
, User = ""
|
||||
, Password = ""
|
||||
, SubjectPrefix = "pcmt - "
|
||||
, SendPlainText = True
|
||||
}
|
||||
, LiveMode =
|
||||
-- | LiveMode controls whether the application looks for
|
||||
-- | directories "assets" and "templates" on the filesystem or
|
||||
-- | in its bundled Embed.FS.
|
||||
False
|
||||
, DevelMode = False
|
||||
, AppPath =
|
||||
-- | AppPath specifies where the program looks for "assets" and
|
||||
-- | "templates" in case LiveMode is True.
|
||||
"."
|
||||
, Session =
|
||||
{ CookieName = "pcmt_session"
|
||||
, CookieAuthSecret = ""
|
||||
, CookieEncrSecret = ""
|
||||
, MaxAge = 3600
|
||||
}
|
||||
, Logger = { JSON = True, Fmt = None Text }
|
||||
, Init =
|
||||
{ CreateAdmin =
|
||||
-- | if this is True, attempt to create a user with admin
|
||||
-- | privileges with the password specified below (or better -
|
||||
-- | overriden); it fails if users already exist in the DB.
|
||||
False
|
||||
, AdminPassword =
|
||||
-- | used for the first admin, forced change on first login.
|
||||
"50ce50fd0e4f5894d74c4caecb450b00c594681d9397de98ffc0c76af5cff5953eb795f7"
|
||||
}
|
||||
, Registration.Allowed = True
|
||||
}
|
||||
}
|
||||
|
||||
in Schema
|
||||
\end{lstlisting}
|
||||
|
||||
Another one of specialties of Dhall is that $==$ and $!=$ equality operators
|
||||
only work on values of type \texttt{Bool}, which for example means that
|
||||
variables of type \texttt{Natural} (\texttt{uint}) or \texttt{Text}
|
||||
@ -1040,80 +1085,6 @@ same-origin policy and (optionally) pinning a cryptographic hash of the value
|
||||
of the expression being imported.
|
||||
|
||||
|
||||
\begin{figure}[!h]
|
||||
\begin{varwidth}
|
||||
\scriptsize
|
||||
\begin{verbatim}
|
||||
, default =
|
||||
-- | have sane defaults.
|
||||
{ Host = ""
|
||||
, Port = 3000
|
||||
, HTTP =
|
||||
{ Domain = ""
|
||||
, Secure = False
|
||||
, AutoTLS = False
|
||||
, TLSKeyPath = ""
|
||||
, TLSCertKeyPath = ""
|
||||
, HSTSMaxAge = 0
|
||||
, ContentSecurityPolicy = ""
|
||||
, RateLimit = 0
|
||||
, Gzip = 0
|
||||
, Timeout = 0
|
||||
}
|
||||
, Mailer =
|
||||
{ Enabled = False
|
||||
, Protocol = "smtps"
|
||||
, SMTPAddr = ""
|
||||
, SMTPPort = 465
|
||||
, ForceTrustServerCert = False
|
||||
, EnableHELO = False
|
||||
, HELOHostname = ""
|
||||
, Auth = ""
|
||||
, From = ""
|
||||
, User = ""
|
||||
, Password = ""
|
||||
, SubjectPrefix = "pcmt - "
|
||||
, SendPlainText = True
|
||||
}
|
||||
, LiveMode =
|
||||
-- | LiveMode controls whether the application looks for
|
||||
-- | directories "assets" and "templates" on the filesystem or
|
||||
-- | in its bundled Embed.FS.
|
||||
False
|
||||
, DevelMode = False
|
||||
, AppPath =
|
||||
-- | AppPath specifies where the program looks for "assets" and
|
||||
-- | "templates" in case LiveMode is True.
|
||||
"."
|
||||
, Session =
|
||||
{ CookieName = "pcmt_session"
|
||||
, CookieAuthSecret = ""
|
||||
, CookieEncrSecret = ""
|
||||
, MaxAge = 3600
|
||||
}
|
||||
, Logger = { JSON = True, Fmt = None Text }
|
||||
, Init =
|
||||
{ CreateAdmin =
|
||||
-- | if this is True, attempt to create a user with admin
|
||||
-- | privileges with the password specified below (or better -
|
||||
-- | overriden); it fails if users already exist in the DB.
|
||||
False
|
||||
, AdminPassword =
|
||||
-- | used for the first admin, forced change on first login.
|
||||
"50ce50fd0e4f5894d74c4caecb450b00c594681d9397de98ffc0c76af5cff5953eb795f7"
|
||||
}
|
||||
, Registration.Allowed = True
|
||||
}
|
||||
}
|
||||
|
||||
in Schema
|
||||
\end{verbatim}
|
||||
\end{varwidth}
|
||||
\caption{Dhall configuration defaults for schema version 0.0.1-rc.2}
|
||||
\label{fig:dhallschemadefaults}
|
||||
\end{figure}
|
||||
|
||||
|
||||
\n{3}{Possible alternatives}
|
||||
|
||||
While developing the program, the author has also
|
||||
@ -1304,7 +1275,7 @@ user for browsing.
|
||||
\n{3}{Local Dataset Plugin} Breach data from locally available datasets can be
|
||||
imported into the application by first making sure it adheres to the specified
|
||||
schema (have a look at the \emph{breach data schema} in
|
||||
Figure~\ref{fig:breachDataGoSchema}). If it doesn't (which is very likely with
|
||||
Listing~\ref{breachDataGoSchema}). If it doesn't (which is very likely with
|
||||
random breach data), it needs to be converted to a form that does before
|
||||
importing it to the application, e.g.\ using a Python script or similar.
|
||||
Attempting to import data that does not follow the outlined schema would result
|
||||
@ -1313,10 +1284,9 @@ would by default be rejected by the program as a precaution, since marshaling
|
||||
e.g.\ a 1 TiB document would likely result in an OOM situation on the host,
|
||||
assuming regular consumer hardware conditions, not HPC.
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{varwidth}{\linewidth}
|
||||
\begin{verbatim}
|
||||
\vspace{\parskip}
|
||||
\begin{lstlisting}[language=Go, caption={Breach Data Schema represented as a Go struct with imports from the standard library are assumed},
|
||||
label=breachDataGoSchema]
|
||||
type breachDataSchema struct {
|
||||
Name string
|
||||
Time time.Time
|
||||
@ -1330,28 +1300,22 @@ assuming regular consumer hardware conditions, not HPC.
|
||||
ContainsEmails bool
|
||||
Data any
|
||||
}
|
||||
\end{verbatim}
|
||||
\end{varwidth}
|
||||
\end{lstlisting}
|
||||
|
||||
\caption{Breach Data Schema represented as a Go struct with imports from the
|
||||
standard library are assumed}
|
||||
\label{fig:breachDataGoSchema}
|
||||
\end{figure}
|
||||
|
||||
The Go representation shown in Figure~\ref{fig:breachDataGoSchema} will in
|
||||
The Go representation shown in Listing~\ref{breachDataGoSchema} will in
|
||||
actuality be written and supplied by the user of the program as a YAML
|
||||
document. YAML was chosen for multiple reasons: relative ease of use (plain
|
||||
text, readable, support for inclusion of comments, its capability to store
|
||||
multiple \emph{documents} inside of a single file with most of the inputs
|
||||
implicitly typed as strings while thanks to being a superset of JSON it sports
|
||||
machine readability. That should allow for documents similar to what can be
|
||||
seen in Figure~\ref{fig:breachDataYAMLSchema} to be ingested by the program,
|
||||
seen in Listing~\ref{breachDataYAMLSchema} to be ingested by the program,
|
||||
read and written by humans and programs alike.
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{varwidth}{\linewidth}
|
||||
\begin{verbatim}
|
||||
\vspace{\parskip}
|
||||
\begin{lstlisting}[language=YAML, caption={Example Breach Data Schema supplied
|
||||
to the program as a YAML file, optionally containing multiple documents},
|
||||
label=breachDataYAMLSchema]
|
||||
---
|
||||
name: Horrible breach
|
||||
time: 2022-04-23T00:00:00Z+02:00
|
||||
@ -1375,17 +1339,10 @@ read and written by humans and programs alike.
|
||||
# document #2, describing another breach.
|
||||
name: Horrible breach 2
|
||||
...
|
||||
}
|
||||
\end{verbatim}
|
||||
\end{varwidth}
|
||||
\end{lstlisting}
|
||||
|
||||
\caption{Example Breach Data Schema supplied to the program as a YAML file, optionally
|
||||
containing multiple documents}
|
||||
\label{fig:breachDataYAMLSchema}
|
||||
\end{figure}
|
||||
|
||||
Notice how the emails list in Figure~\ref{fig:breachDataYAMLSchema} misses one
|
||||
record, perhaps because it was not supplied or mistakenly ommitted. This is a
|
||||
Notice how the emails list in Listing~\ref{breachDataYAMLSchema} misses one
|
||||
record, perhaps because it was not supplied or mistakenly omitted. This is a
|
||||
valid scenario (mistakes happen) and the application needs to be able to handle
|
||||
it. The alternative would be to require the user to prepare the data in such a
|
||||
way that the empty/partial records would be dropped entirely.
|
||||
@ -1559,9 +1516,9 @@ then after pushing to remote in the CI.
|
||||
|
||||
\n{3}{func TestUserExists(t *testing.T)}
|
||||
|
||||
An example integration test shown in Figure~\ref{fig:integrationtest} can be
|
||||
An example integration test shown in Listing~\ref{integrationtest} can be
|
||||
seen to declare a helper function \texttt{getCtx() context.Context}, which
|
||||
takes no arguments and returns a new \texttt{context.Context} initialised with
|
||||
takes no arguments and returns a new\\ \texttt{context.Context} initialised with
|
||||
a value of the global logger, which is how the logger gets injected into the
|
||||
user module functions. The function \texttt{TestUserExists(t *testing.T)} first
|
||||
declares a database connection string and attempting to open a connection to
|
||||
@ -1596,10 +1553,84 @@ first argument, with the database pointer and username being passed next, while
|
||||
the \texttt{email} variable is only used at a later stage, but was declared
|
||||
here to give a sense of grouping. The error value returned from this function
|
||||
is again checked and if everything goes well, the value of the
|
||||
\texttt{usernameFound} boolean is checked next. Since the database has just
|
||||
been created, there should be no users, which is checked in the next
|
||||
\texttt{if} statement. The same check is then performed for the
|
||||
earlier-declared user email that is also expected to fail.
|
||||
\texttt{usernameFound} boolean is checked next.
|
||||
|
||||
\smallskip
|
||||
\begin{lstlisting}[language=Go, caption={Example integration test.},
|
||||
label=integrationtest,basicstyle=\linespread{0.8}\footnotesize\ttfamily]
|
||||
// modules/user/user_test.go
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"git.dotya.ml/mirre-mt/pcmt/ent/enttest"
|
||||
"git.dotya.ml/mirre-mt/pcmt/slogging"
|
||||
_ "github.com/xiaoqidun/entps"
|
||||
)
|
||||
|
||||
func getCtx() context.Context {
|
||||
l := slogging.Init(false)
|
||||
ctx := context.WithValue(context.Background(), CtxKey{}, l)
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
||||
func TestUserExists(t *testing.T) {
|
||||
connstr := "file:ent_tests?mode=memory&_fk=1"
|
||||
db := enttest.Open(t, "sqlite3", connstr)
|
||||
defer db.Close()
|
||||
|
||||
if err := db.Schema.Create(context.Background()); err != nil {
|
||||
t.Errorf("failed to create schema resources: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
username := "dude"
|
||||
email := "dude@b.cc"
|
||||
ctx := getCtx()
|
||||
|
||||
usernameFound, err := UsernameExists(ctx, db, username)
|
||||
if err != nil {
|
||||
t.Errorf("error checking for username {%s} existence: %q",
|
||||
username,
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
if usernameFound {
|
||||
t.Errorf("unexpected: user{%s} should not have been found",
|
||||
username,
|
||||
)
|
||||
}
|
||||
|
||||
if _, err := EmailExists(ctx, db, email); err != nil {
|
||||
t.Errorf("unexpected: user email '%s' should not have been found",
|
||||
email,
|
||||
)
|
||||
}
|
||||
|
||||
usr, err := CreateUser(ctx, db, email, username, "so strong")
|
||||
if err != nil {
|
||||
t.Errorf("failed to create user, error: %q", err)
|
||||
t.FailNow()
|
||||
} else if usr == nil {
|
||||
t.Error("got nil usr back")
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if usr.Username != username {
|
||||
t.Errorf("got back wrong username, want: %s, got: %s",
|
||||
username, usr.Username,
|
||||
)
|
||||
} // ...more checks...
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
Since the database has just been created, there should be no users, which is
|
||||
checked in the next \texttt{if} statement. The same check is then performed for
|
||||
the earlier-declared user email that is also expected to fail.
|
||||
|
||||
The final statements of the described test attempts a user creation call, which
|
||||
is again checked for both error and \emph{nilability}. The test continues with
|
||||
@ -1609,85 +1640,6 @@ A neat thing about error handling in Go is that it allows for very easy
|
||||
checking of all paths, not just the \emph{happy path} where there are no
|
||||
issues.
|
||||
|
||||
\begin{figure}[!h]
|
||||
\centering
|
||||
\scriptsize
|
||||
\begin{varwidth}{\linewidth}
|
||||
\begin{verbatim}
|
||||
// modules/user/user_test.go
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"git.dotya.ml/mirre-mt/pcmt/ent/enttest"
|
||||
"git.dotya.ml/mirre-mt/pcmt/slogging"
|
||||
_ "github.com/xiaoqidun/entps"
|
||||
)
|
||||
|
||||
func getCtx() context.Context {
|
||||
l := slogging.Init(false)
|
||||
ctx := context.WithValue(context.Background(), CtxKey{}, l)
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
||||
func TestUserExists(t *testing.T) {
|
||||
connstr := "file:ent_tests?mode=memory&_fk=1"
|
||||
db := enttest.Open(t, "sqlite3", connstr)
|
||||
defer db.Close()
|
||||
|
||||
if err := db.Schema.Create(context.Background()); err != nil {
|
||||
t.Errorf("failed to create schema resources: %v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
username := "dude"
|
||||
email := "dude@b.cc"
|
||||
ctx := getCtx()
|
||||
|
||||
usernameFound, err := UsernameExists(ctx, db, username)
|
||||
if err != nil {
|
||||
t.Errorf("error checking for username {%s} existence: %q",
|
||||
username,
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
if usernameFound {
|
||||
t.Errorf("unexpected: user{%s} should not have been found",
|
||||
username,
|
||||
)
|
||||
}
|
||||
|
||||
if _, err := EmailExists(ctx, db, email); err != nil {
|
||||
t.Errorf("unexpected: user email '%s' should not have been found",
|
||||
email,
|
||||
)
|
||||
}
|
||||
|
||||
usr, err := CreateUser(ctx, db, email, username, "so strong")
|
||||
if err != nil {
|
||||
t.Errorf("failed to create user, error: %q", err)
|
||||
t.FailNow()
|
||||
} else if usr == nil {
|
||||
t.Error("got nil usr back")
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
if usr.Username != username {
|
||||
t.Errorf("got back wrong username, want: %s, got: %s",
|
||||
username, usr.Username,
|
||||
)
|
||||
}
|
||||
// ...more checks...
|
||||
}
|
||||
\end{verbatim}
|
||||
\end{varwidth}
|
||||
\caption{Example integration test}
|
||||
\label{fig:integrationtest}
|
||||
\end{figure}
|
||||
|
||||
\n{2}{Testing environment}
|
||||
|
||||
|
@ -118,6 +118,7 @@
|
||||
% list of tables
|
||||
\seznamtab
|
||||
|
||||
\seznamkodu
|
||||
|
||||
% =========================================================================== %
|
||||
% list of appendices
|
||||
|
Reference in New Issue
Block a user