Chcę móc zacząć wprowadzać własne modyfikacje kodu źródłowego guix.

Koniecznym elementem procesu modyfikacji guix jest testowanie zmian przez całkowitą rekonfigurację systemu na podstawie wprowadzonej zmiany. Nie jest możliwa rekonfiguracja za pomocą trywialnego dodania lokalnego repozytorium guix do ścieżki ładowania Guile.

Dokumentacja Guix nie ułatwia zadania. Opisuje przede wszystkim proces instalacji programu guix ze źródeł, a moim celem jest modyfikacja kolekcji paczek i narzędzi dostępnych w tym samym repozytorium.


Pozostaje mi eksperymentalne dotarcie do celu.

Dzisiaj myślę o dodaniu do mojej kopii repozytorium guix gałęzi dedykowanych dla moich zmian.

Wiem, że nie będę w stanie samodzielnie uwierzytelniać tych zmian, ale zakładam, że wystarczy mi dodanie wyłączenie autoryzacji w aliasie test-system. W najgorszym wypadku, gdyby te zmiany uniemożliwały normalną aktualizację z gałęzi master, pozostaje opcja instalacji kolejnej kopii repozytorium guix dla celu jej programowania.

Dodanie gałęzi

ŹRÓDŁO Krokiem przygotowawczym jest modyfikacja aliasu test-system.

Repozytorium guix jest wyjątkowe w kontekście systemu Guix — posiada dedykowane opcje w programie guix i nie jest możliwe wykorzystanie go bezpośrednio w ścieżce ładowania Guile. Nieznajomość technicznej przyczyny takiego stanu rzeczy nie jest istotna w tym eksperymencie.

Do realizacji tego przygotowania nie wystarczy dodać opcji --branch=test do aliasu test-system, ponieważ guix system nie posiada takiej opcji. Pozostaje wydanie dodatkowego polecenia pull-guix --branch=test przed testowaną rekonfiguracją.


Po kilku próbach udało mi się dodać guix pull --fallback --branch=test ; do aliasu test-system.

$ alias
alias collect-garbage='guix home delete-generations 7d; sudo guix system delete-generations 7d; sudo guix gc -d 7d '
alias downgrade-system='guix pull --fallback --allow-downgrades ; sudo guix system reconfigure -e "(@ (deployment systems rakan) operating-system*)" --fallback --allow-downgrades ; guix home delete-generations 7d; sudo guix system delete-generations 7d; sudo guix gc -d 7d '
alias edit='kate -s sesja -b'
alias grep='grep --color=auto'
alias ip='ip -color=auto'
alias ll='ls -l'
alias ls='ls -p --color=auto'
alias pull-guix='guix pull --fallback '
alias reconfigure-system='sudo guix system reconfigure -e "(@ (deployment systems rakan) operating-system*)" --fallback '
alias test-system='guix pull --fallback --allow-downgrades --branch=test ; sudo guix system reconfigure -e "(@ (deployment systems rakan) operating-system*)" --fallback  -L ~/Szablony/sovereign -L ~/Szablony/deployment -v 3 '
alias update-system='guix pull --fallback ; sudo guix system reconfigure -e "(@ (deployment systems rakan) operating-system*)" --fallback ; guix home delete-generations 7d; sudo guix system delete-generations 7d; sudo guix gc -d 7d '

Oczywiście, to nie wystarczy, ponieważ testowa gałąź nie istnieje jeszcze na mojej kopii repozytorium guix.

$ test-system
Updating channel 'guix' from Git repository at 'https://git.marekpasnikowski.pl/git/guix.git'...
guix pull: błąd: Błąd Git: cannot locate remote-tracking branch 'origin/test'
Hasło:

Tworzę tę gałąź i wypycham ją do repozytorium źródłowego.

$ git branch test

$ git push origin test
Enter passphrase for key '/home/marek/.ssh/id_rsa':
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To ssh://marekpasnikowski.pl:23/guix.git
 * [new branch]            test -> test

Tym razem proces rekonfiguracji dochodzi do skutku.

Test niezależności

Zanim zacznę polegać na tym nowym mechanizmie, potrzebuję sprawdzić czy zlecenie zwykłej aktualizacji wykorzystuje gałąź master z repozytorium guix. Obawiam się scenariusza, że usługa guix zapamiętuje (choć nie powinna) ostatnio używaną wartość opcji --branch.

Ten eksperyment polega na tym, że po wydaniu polecenia test-system następne polecenie update-system powinno nie powieść się ze względu na cofnięcie wersji kanału, przed którym update-system zabezpiecza. Aby doprowadzić do tego scenariusza testowego, gałąź test kanału guix powinna odnosić się do późniejszej wersji.

Tak się składa, że obecnie gałąź master mojej kopii kanału guix od wielu dni odnosi się do tej samej zmiany, ponieważ późniejsze zmiany są szkodliwe dla mojej konfiguracji. Umożliwia to symulację procesu aktualizacji guix na gałęzi test, co w istocie jest jednym z celów dzisiejszej pracy. Dla celu tego testu wystarczy, że do skutku dojdzie pierwsza część polecenia test-systemguix pull. Po załadowaniu testowej wersji repozytorium skuteczny będzie test cofnięcia wersji.

Nie ma znaczenia, że moja konfiguracja nie daje się zbudować z obecnej wersji guix, ponieważ rekonfiguracja nie jest celem tego eksperymentu.


Eksperyment składa się z trzech czynności.

  1. Aktualizacja na gałęzi test.
  2. Aktywacja gałęzi test.
  3. Sprawdzenie aktywacji gałęzi master.

Aktualizacja na gałęzi test jest wykonaniem codziennej rutyny dotychczas wykonywanej na gałęzi master. Aktywacja gałęzi test polega na wykonaniu nowego polecenia test-system. Ostatni krok jest wykonaniem polecenia update-system.

Sama aktualizacja repozytorium nie sprawia najmniejszych problemów. Muszę tylko uważać, żeby pracować na gałęzi test.

$ cd guix

$ git fetch upstream
remote: Enumerating objects: 3141, done.
remote: Counting objects: 100% (2153/2153), done.
remote: Compressing objects: 100% (195/195), done.
remote: Total 3141 (delta 2059), reused 2021 (delta 1958), pack-reused 988 (from 1)
Pobieranie obiektów: 100% (3141/3141), 2.19 MiB | 5.10 MiB/s, gotowe.
Rozwiązywanie delt: 100% (2481/2481), wykonano z 373 lokalnymi obiektami.
Z https://codeberg.org/guix/guix
 + 28b28b1789...af779e8126 astro-updates -> upstream/astro-updates  (wymuszona aktualizacja)
   95dd640b7e..f62206ecd8  master        -> upstream/master
 + 2b01b504e3...9a0f0bcaee mesa-updates  -> upstream/mesa-updates  (wymuszona aktualizacja)
 + 848519ed83...36ecf6b0f2 python-team   -> upstream/python-team  (wymuszona aktualizacja)

$ git checkout test
Przełączono na gałąź „test”

$ git merge bd3c19763ad543f95d5174ab784b4166c577956e
Aktualizowanie e4a6c73831..bd3c19763a
Fast-forward
…

$ git push origin test
Enter passphrase for key '/home/marek/.ssh/id_rsa':
Wymienianie obiektów: 2775, gotowe.
Zliczanie obiektów: 100% (2775/2775), gotowe.
Kompresja delt z użyciem do 32 wątków
Kompresowanie obiektów: 100% (928/928), gotowe.
Zapisywanie obiektów: 100% (2613/2613), 1.10 MiB | 14.27 MiB/s, gotowe.
Total 2613 (delta 2082), reused 2181 (delta 1685), pack-reused 0 (from 0)
remote: Rozwiązywanie delt: 100% (2082/2082), wykonano z 155 lokalnymi obiektami.
To ssh://marekpasnikowski.pl:23/guix.git
   e4a6c73831..bd3c19763a  test -> test

Zgodnie z przewidywaniami, aktywacja gałęzi test zawodzi w trakcie rekonfiguracji systemu, a program guix jest przestawiony na gałąź test.

$ test-system
Updating channel 'guix' from Git repository at 'https://git.marekpasnikowski.pl/git/guix.git'...
guix pull: ostrzeżenie: pulled channel 'guix' from a mirror of https://git.guix.gnu.org/guix.git, which might be stale
Updating channel 'deployment' from Git repository at 'https://git.marekpasnikowski.pl/git/deployment.git'...
Updating channel 'guix-rust-past-crates' from Git repository at 'https://git.marekpasnikowski.pl/git/guix-rust-past-crates.git'...
guix pull: ostrzeżenie: pulled channel 'guix-rust-past-crates' from a mirror of https://codeberg.org/guix/guix-rust-past-crates.git, which might be stale
Updating channel 'nonguix' from Git repository at 'https://git.marekpasnikowski.pl/git/nonguix.git'...
guix pull: ostrzeżenie: pulled channel 'nonguix' from a mirror of https://gitlab.com/nonguix/nonguix, which might be stale
Updating channel 'sovereign' from Git repository at 'https://git.marekpasnikowski.pl/git/sovereign.git'...
Building from these channels:
  guix      https://git.marekpasnikowski.pl/git/guix.git        bd3c197
  deploymenthttps://git.marekpasnikowski.pl/git/deployment.git  7cdd8e2
  guix-rust-past-crateshttps://git.marekpasnikowski.pl/git/guix-rust-past-crates.git    e19b4de
  nonguix   https://git.marekpasnikowski.pl/git/nonguix.git     df4e6ed
  sovereign https://git.marekpasnikowski.pl/git/sovereign.git   b4068b3
 module-import-compiled  1.5MiB                                                                              3.7MiB/s 00:00 ▕██████████████████▏ 100.0%
 module-import-compiled  1.5MiB                                                                              5.7MiB/s 00:00 ▕██████████████████▏ 100.0%
building /gnu/store/f1q7isyx24lm3pzkh5h7li5xf99b12d2-git.scm.drv...
building /gnu/store/4w0c7yxg69dzvpi544zrglf2vl5fgnzj-hash.scm.drv...
building /gnu/store/k5x46841ampk8c5zn6j92vsph0zrbgs4-module-import.drv...
building /gnu/store/r9qx17fzkhqw15zjy7lyq1b90vjr8z6m-module-import.drv...
building /gnu/store/s3bwb8fpyfbr18x6x59ghczv0hrwg34w-compute-guix-derivation.drv...
Computing Guix derivation for 'x86_64-linux'... |
…

error: in phase 'build': uncaught exception:
%exception #<&invoke-error program: "cmake" arguments: ("--build" "." "-j" "1" "--" "-l" "32") exit-status: 2 term-signal: #f stop-signal: #f>
phase `build' failed after 15.0 seconds
command "cmake" "--build" "." "-j" "1" "--" "-l" "32" failed with status 2
build process 18 exited with status 256
builder for `/gnu/store/58y93f4hfbpgjb4zzkswn2n6hr3h2hwz-kpimtextedit-24.12.1.drv' failed with exit code 1
budowanie /gnu/store/58y93f4hfbpgjb4zzkswn2n6hr3h2hwz-kpimtextedit-24.12.1.drv nie powiodło się
View build log at '/var/log/guix/drvs/58/y93f4hfbpgjb4zzkswn2n6hr3h2hwz-kpimtextedit-24.12.1.drv.gz'.
substituting /gnu/store/h4v4qjxz860ycriw6mkhmkwp6zd89wd5-ktextwidgets-5.116.0...
cannot build derivation `/gnu/store/4qkz6dw4vjdd1wjxa8lzc1wyalidns1c-kaddressbook-24.12.1.drv': 1 dependencies couldn't be built
guix system: błąd: build of `/gnu/store/4qkz6dw4vjdd1wjxa8lzc1wyalidns1c-kaddressbook-24.12.1.drv' failed

$ guix describe
Generation 367  wrz 18 2025 10:21:29    (current)
  guix bd3c197
    repository URL: https://git.marekpasnikowski.pl/git/guix.git
    branch: test
    commit: bd3c19763ad543f95d5174ab784b4166c577956e
…

Ku mojemu zadowoleniu próba zwykłej aktualizacji kończy się oczekiwanym błędem.

$ update-system
Updating channel 'guix' from Git repository at 'https://git.marekpasnikowski.pl/git/guix.git'...
guix pull: błąd: aborting update of channel 'guix' to commit e4a6c73831dc996e7371e101308a416ae7b65436, which is not a descendant of bd3c19763ad543f95d5174ab784b4166c577956e
wskazówka: This could indicate that the channel has been tampered with and is trying to force a roll-back, preventing you from getting the latest updates.  If
you think this is not the case, explicitly allow non-forward updates.

W celu przeprowadzenia kolejnych eksperymentów przywracam działającą wersję w gałęzi test.

$ git reset --hard master
HEAD wskazuje teraz e4a6c73831 gnu: nebula: Update to 1.9.6.

$ git push -f
Enter passphrase for key '/home/marek/.ssh/id_rsa':
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To ssh://marekpasnikowski.pl:23/guix.git
 + bd3c19763a...e4a6c73831 test -> test (forced update)
branch 'test' set up to track 'origin/test'.

Implementacja zmian własnych

ŹRÓDŁO Na tym etapie osiągnięty jest już plan minimum, dzięki któremu mogę testować aktualizacje kanału guix bez zakłócania pracy gałęzi master. Udowodniona jest możliwość wykorzystania odrębnego kodu źródłowego guix. Pozostała tylko próba rekonfiguracji z własnymi zmianami w kanale guix. W trakcie procesu aktualizacji przed taką rekonfiguracją następuje uwierzytelnianie kanału.

Uwierzytelnianie kanału jest weryfikacją, czy wszystkie zmiany w repozytorium są podpisane przez programistów Guix.

Proces uwierzytelniania uniemożliwia wprowadzanie własnych zmian do repozytorium guix. Można ominąć ten proces używając opcji --disable-authentication.

Aby ta próba implementacji zmian własnych była skuteczna, potrzebuję również wprowadzić dowolną zmianę w repozytorium. Mam przygotowaną zmianę polegającą na dodaniu biblioteki Fontconfig do listy zależności programu Kate, aby sprawdzić czy zmieni to wyświetlanie czcionek.


Należy dodać --disable-authentication do aliasu test-system i wprowadzić zmianę do repozytorium źródłowego guix.

Aby rozszerzyć alias test-system należy wprowadzić odpowiednią zmianę w module (sovereign services admin) i dokonać rekonfiguracji systemu. Natomiast aby zmienić repozytorium guix należy edytować moduł (gnu packages kde-utils) i wypchnąć tę zmianę do mojego repozytorium źródłowego.

Rekonfiguracja w celu dodania opcji --disable-authentication przebiega bez zarzutu.

$ alias
alias collect-garbage='guix home delete-generations 7d; sudo guix system delete-generations 7d; sudo guix gc -d 7d '
alias downgrade-system='guix pull --fallback --allow-downgrades ; sudo guix system reconfigure -e "(@ (deployment systems rakan) operating-system*)" --fallback --allow-downgrades ; guix home delete-generations 7d; sudo guix system delete-generations 7d; sudo guix gc -d 7d '
alias edit='kate -s sesja -b'
alias grep='grep --color=auto'
alias ip='ip -color=auto'
alias ll='ls -l'
alias ls='ls -p --color=auto'
alias pull-guix='guix pull --fallback '
alias reconfigure-system='sudo guix system reconfigure -e "(@ (deployment systems rakan) operating-system*)" --fallback '
alias test-system='guix pull --fallback --allow-downgrades --disable-authentication --branch=test ; sudo guix system reconfigure -e "(@ (deployment systems rakan) operating-system*)" --fallback  -L ~/Szablony/sovereign -L ~/Szablony/deployment -v 3 '
alias update-system='guix pull --fallback ; sudo guix system reconfigure -e "(@ (deployment systems rakan) operating-system*)" --fallback ; guix home delete-generations 7d; sudo guix system delete-generations 7d; sudo guix gc -d 7d '

Samo wprowadzenie zmiany do mojej kopii kanału guix jest pomyślne.

$ git status
Na gałęzi test
Twoja gałąź jest na bieżąco z „origin/test”.

Zmiany nie przygotowane do złożenia:
  (użyj „git add <plik>...”, żeby zmienić, co zostanie złożone)
  (użyj „git restore <plik>...”, aby odrzucić zmiany w katalogu roboczym)
        zmieniono:       gnu/packages/kde-utils.scm

brak zmian dodanych do zapisu (użyj „git add” i/lub „git commit -a”)

$ git diff
diff --git a/gnu/packages/kde-utils.scm b/gnu/packages/kde-utils.scm
index 9d9f25e3e6..6e594f7a0a 100644
--- a/gnu/packages/kde-utils.scm
+++ b/gnu/packages/kde-utils.scm
@@ -402,6 +402,7 @@ (define-public kate
      (list extra-cmake-modules kdoctools))
     (inputs
      (list breeze-icons ;; default icon set
+           fontconfig
            plasma-activities
            kconfig
            kcrash

$ git commit -am 'test fontconfig change in kate'
[test 78dd3dfc72] test fontconfig change in kate
 1 file changed, 1 insertion(+)

$ git push origin test
Enter passphrase for key '/home/marek/.ssh/id_rsa':
Wymienianie obiektów: 9, gotowe.
Zliczanie obiektów: 100% (9/9), gotowe.
Kompresja delt z użyciem do 32 wątków
Kompresowanie obiektów: 100% (5/5), gotowe.
Zapisywanie obiektów: 100% (5/5), 1.10 KiB | 1.10 MiB/s, gotowe.
Total 5 (delta 4), reused 0 (delta 0), pack-reused 0 (from 0)
To ssh://marekpasnikowski.pl:23/guix.git
   e4a6c73831..78dd3dfc72  test -> test

Polecenie test-system również działa poprawnie!

$ test-system
Updating channel 'guix' from Git repository at 'https://git.marekpasnikowski.pl/git/guix.git'...
guix pull: ostrzeżenie: channel authentication disabled
Updating channel 'deployment' from Git repository at 'https://git.marekpasnikowski.pl/git/deployment.git'...
guix pull: ostrzeżenie: channel authentication disabled
Updating channel 'guix-rust-past-crates' from Git repository at 'https://git.marekpasnikowski.pl/git/guix-rust-past-crates.git'...
guix pull: ostrzeżenie: channel authentication disabled
Updating channel 'nonguix' from Git repository at 'https://git.marekpasnikowski.pl/git/nonguix.git'...
guix pull: ostrzeżenie: channel authentication disabled
Updating channel 'sovereign' from Git repository at 'https://git.marekpasnikowski.pl/git/sovereign.git'...
guix pull: ostrzeżenie: channel authentication disabled
Building from these channels:
  guix      https://git.marekpasnikowski.pl/git/guix.git        78dd3df
  deploymenthttps://git.marekpasnikowski.pl/git/deployment.git  7cdd8e2
  guix-rust-past-crateshttps://git.marekpasnikowski.pl/git/guix-rust-past-crates.git    e19b4de
  nonguix   https://git.marekpasnikowski.pl/git/nonguix.git     df4e6ed
  sovereign https://git.marekpasnikowski.pl/git/sovereign.git   b4068b3
substitute: looking for substitutes on 'https://substitutes.nonguix.org'... 100.0%
substitute: looking for substitutes on 'https://nonguix-proxy.ditigal.xyz/'... 100.0%
substitute: looking for substitutes on 'https://bordeaux.guix.gnu.org'... 100.0%
substitute: looking for substitutes on 'https://ci.guix.gnu.org'... 100.0%
building /gnu/store/50p1fk5a4ikfzblxcjg0alfi2z9qp4kd-compute-guix-derivation.drv...
Computing Guix derivation for 'x86_64-linux'... |
…

successfully built /gnu/store/8ikxhdzk5is3azmyl80vnpg2p8m10i2s-kate-25.04.0.drv
…

Moja zmiana w programie kate nie doprowadziła do oczekiwanego efektu, ale sam proces jest prawidłowy.

Testowanie zmian lokalnie

ŹRÓDŁO W trakcie prowadzenia powyższych eksperymentów uświadomiłem sobie również, że można spróbować wykorzystać opcję --url do testowania zmian lokalnie, bez wcześniejszego wypychania ich do repozytorium źródłowego.

Opcja --url polecenia guix pull pobiera kod źródłowy kanału guix z wyznaczonego w tej opcji adresu.

Pamiętam z wczesnych eksperymentów z Guix, że istnieje możliwość adresowania kanałów w strukturze systemu plików.


Tak jak przy wszystkich poprzednich zmianach, należy zacząć od kolejnego rozszerzenia aliasu test-system o opcję --url, i wydać te rozszerzone polecenie.

Nie wiem, jak zakodować ścieżkę dostępu do katalogu guix, więc potrzebuję ustalić to eksperymentalnie.

Pierwsze na myśl przychodzi zastosowanie klasycznego adresowania ~/Szablony/guix, ale to nie działa.

$ pull-guix --url=~/Szablony/guix
Updating channel 'guix' from Git repository at '~/Szablony/guix'...
guix pull: błąd: Błąd Git: unsupported URL protocol

$ pull-guix --url=file:/~/Szablony/guix
Updating channel 'guix' from Git repository at 'file:/~/Szablony/guix'...
guix pull: błąd: Błąd Git: failed to resolve address for file: Ta nazwa lub usługa jest nieznana

$ pull-guix --url=file://~/Szablony/guix
Updating channel 'guix' from Git repository at 'file://~/Szablony/guix'...
guix pull: błąd: Błąd Git: failed to resolve path 'file://~/Szablony/guix': Nie ma takiego pliku ani katalogu

Ostatnia próba jest interesująca. Rozwinięcie tyldy prowadzi do pierwszego sukcesu.

$ pull-guix --url=file:///home/marek/Szablony/guix
Updating channel 'guix' from Git repository at 'file:///home/marek/Szablony/guix'...

Zastanawiając się dlaczego reszta aliasu test-system wykorzystuje znak tyldy uświadomiłem sobie, że prawdziwym problemem nie jest ukrywanie nazwy użytkownika, lecz uogólnienie definicji aliasu na potrzeby dystrybucji. Wykorzystanie zmiennej środowiskowej w miejscu tyldy rozwiązuje ten problem.

$ pull-guix --url=file://$HOME/Szablony/guix
Updating channel 'guix' from Git repository at 'file:///home/marek/Szablony/guix'...

Rekonfiguracja z działającą definicją aliasu prowadzi bezpośrednio do celu. Proces ten przez niepokojąco długi czas nie daje informacji zwrotnej o postępie. Ufam jednak i nie przerywam go. Po wielu minutach pojawia się upragniony pasek postępu.

$ test-system
Updating channel 'guix' from Git repository at 'file:///home/marek/Szablony/guix'...
guix pull: ostrzeżenie: rolling back channel 'guix' from 78dd3dfc729340a66b4552f00909b82fa5e5f957 to e4a6c73831dc996e7371e101308a416ae7b65436
guix pull: ostrzeżenie: channel authentication disabled
Updating channel 'deployment' from Git repository at 'https://git.marekpasnikowski.pl/git/deployment.git'...
guix pull: ostrzeżenie: channel authentication disabled
Updating channel 'guix-rust-past-crates' from Git repository at 'https://git.marekpasnikowski.pl/git/guix-rust-past-crates.git'...
guix pull: ostrzeżenie: channel authentication disabled
Updating channel 'nonguix' from Git repository at 'https://git.marekpasnikowski.pl/git/nonguix.git'...
guix pull: ostrzeżenie: channel authentication disabled
Updating channel 'sovereign' from Git repository at 'https://git.marekpasnikowski.pl/git/sovereign.git'...
guix pull: ostrzeżenie: channel authentication disabled
Building from these channels:
  guix      file:///home/marek/Szablony/guix    e4a6c73
  deploymenthttps://git.marekpasnikowski.pl/git/deployment.git  7cdd8e2
  guix-rust-past-crateshttps://git.marekpasnikowski.pl/git/guix-rust-past-crates.git    e19b4de
  nonguix   https://git.marekpasnikowski.pl/git/nonguix.git     df4e6ed
  sovereign https://git.marekpasnikowski.pl/git/sovereign.git   b4068b3
substitute: looking for substitutes on 'https://substitutes.nonguix.org'... 100.0%
substitute: looking for substitutes on 'https://nonguix-proxy.ditigal.xyz/'... 100.0%
substitute: looking for substitutes on 'https://bordeaux.guix.gnu.org'... 100.0%
substitute: looking for substitutes on 'https://ci.guix.gnu.org'... 100.0%
building /gnu/store/zydg52hrszs0h468w43v3maarhyc028m-compute-guix-derivation.drv...
Computing Guix derivation for 'x86_64-linux'... |
…

Okazuje się również, guix system reconfigure również przetwarza od nowa, przez bardzo długi czas, lokalne repozytorium guix. Na szczęście jest to jednorazowa inwestycja. Każde kolejne wywołanie test-system jest szybkie.