1
0

tex: use listings w/ Fira Code for code+mono

This commit is contained in:
leo 2023-05-25 20:35:21 +02:00
parent 9a28821207
commit a94edf9310
Signed by: wanderer
SSH Key Fingerprint: SHA256:Dp8+iwKHSlrMEHzE3bJnPng70I7LEsa3IJXRH/U+idQ
3 changed files with 296 additions and 285 deletions

@ -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. }

@ -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