Tato stránka popisuje, jak budou vypadat testy na cvičeních a časem bude obsahovat i popis (velké) domácí úlohy. Malé domácí úlohy jsou zmíněné u příslušných cvičení.

Podívejte se, prosím, na stránku průvodce předmětem, kde najdete podrobnosti o tom, jak funguje hodnocení jako takové.

Testy na cvičení

Toto je rozpis testů na cvičení. Test proběhne na začátku cvičení (doba trvání testu je 45 minut).

Týden (datum) Téma
08 (7. dubna - 11. dubna) T1: Verzovací systém Git
12 (5. květa - 7. května + 15. května) T2: Skriptování v shellu
14 (19. května - 23. května) T3: Sestavovací nástroj make

Očekává se, že se dostavíte na cvičení, na které jste zapsáni.

Protože 8. května je státní svátek, písemka T2 bude pro čtvrteční cvičení odložena o týden. Víme, že to není nejlepší řešení, ale rozvrh pro tenhle semestr v podstatě nemá žádný celý týden (tj. kdy probíhá výuka ve všech dnech) v druhé polovině semestru.

Test se bude psát na školních počítačích. Ujistěte se, že se tam můžete přihlásit a že máte vše pohodlně nastavené.

Vaše řešení bude odevzdáno prostřednictvím GitLabu nebo jiného Gitového repozitáře: ujistěte se, že umíte provést klonování prostřednictvím příkazové řádky.

Můžete používat naše webové stránky, off-line manuálové stránky a můžete nahlížet do svých poznámek a řešení příkladů, které jsou součástí našich materiálů.

Nesmíte používat žádná jiná zařízení (mobilní telefony, vlastní notebooky atd.), nahlížet do jiných on-line zdrojů (stroje budou mít stejně omezený přístup k internetu) ani sdělovat své řešení ostatním studentům (a naopak).

Jinými slovy, testy na cvičení vyžadují, abyste dokázali řešit úkoly samostatně pouze s pomocí technické dokumentace.

Jakýkoli pokus o obejití výše uvedených pravidel (např. pokus o vyhledávání na StackOverflow na mobilním telefonu) znamená okamžité neúspěšné ukončení předmětu.

Pokud zadání nerozumíte, můžete samozřejmě požádat učitele o dovysvětlení. Pokud je zřejmé, že se ubíráte správným směrem a potřebujete jen trochu postrčit, můžeme vám i lehce poradit.

Prosím, podívejte se též na obecné zásady v průvodci předmětem.

Poznámky k úloze na Git CLI

Informace pro zapsané na speciální úterní cvičení 24bNSWI177x15.

Pokud váš SIS/GitLab-ový login začíná na [a-j], přijďte, prosím, v 8.50; pokud váš login začíná na [k-z], prosím, přijďte v 9.40.

Aktualizace: zadání písemky dostanete pravděpodobně vytištěné. Prosím, ozvěte se nám včas (alespoň týden dopředu), pokud by vám to nějak komplikovalo situaci (např. pokud potřebujete větší písmo). Děkujeme!

Očekáváme, že zvládnete následující úlohy pomocí Gitu na příkazové řádce (některé budete muset provádět na vzdáleném stroji linux.ms.mff.cuni.cz).

  • Nastavit si prostředí Gitu (autor a e-mail)
  • Naklonovat repozitář (z gitolite3@linux.ms.mff.cuni.cz nebo z GitLabu nebo obecně přes HTTPS)
  • Vytvořit commit
  • Vytvořit větev
  • Přepínat mezi větvemi
  • Zmergovat větev (a vyřešit případné konflikty)
  • Nahrát změny (větve) na server

Ujistěte se, že můžete klonovat z gitolite3@linux.ms.mff.cuni.cz když jste na školních počítačích. Bude dostupná jen autentikace veřejným klíčem (tj. nahrajte vaše klíče do keys/key.[0-9].pub souborů ve vašem repozitáři, jak je popsáno na cvičení 05, ještě před zkouškou).

Abyste ověřili, že vám to funguje, projděte si následující kroky, prosím.

Spusťte ssh -o ForwardAgent=no LOGIN@u-pl1.ms.mff.cuni.cz.

  • Tohle se bude ptát na vaše SISové heslo a přihlásí vás na u-pl1.ms.
  • u-pl1.ms je v podstatě stejné jako libovolný počítač v učebně (tj. stejné soubory v ~).

Spusťte ssh gitolite3@linux.ms.mff.cuni.cz.

  • Tohle se zkusí přihlásit po SSH s použitím vašich klíčů na u-pl1 k repozitářům Gitolite.

  • Měli byste vidět na výstupu něco podobného. Důležitá je ta část zprávy, kde vás Gitolite pozdravil vaším SISovým loginem (ačkoliv jste se přihlašovali jako uživatel gitolite3); seznam repozitářů se může lišit.

    PTY allocation request failed on channel 0
    hello LOGIN, this is gitolite3@linux running gitolite3 3.6.13-5.fc41 on git 2.48.1
    
    R   lab05-LOGIN
    R   lab06-group-sum-ng
    
  • Pokud vidíte následující, vaše klíče nejsou v pořádku nastaveny.

    gitolite3@linux.ms.mff.cuni.cz: Permission denied (publickey,password).
    

Klidně si URL gitolite3@linux.ms.mff.cuni.cz uložte někde na místní disk do vašeho $HOME, abyste ho nemuseli ručně opisovat během písemky.

Dokonce si můžete nastavit alias ve vašem ~/.ssh/config nějak takto, což vám umožní klonovat pomocí git clone exam:lab05-LOGIN.

Host exam
    Hostname linux.ms.mff.cuni.cz
    User gitolite3

Písemka se zaměřuje na práci s Gitem. Cílem nebude napsat celý skript ale budete pracovat s repozitářem, ve kterém bude následující skript pro tisk jednoduchý sloupcových grafů v terminálu. Budete v něm ale dělat drobné změny (třeba opravy překlepů), na správné místo v kódu vás ale vždy navedeme.

import argparse
import sys

def parse_config():
    args = argparse.ArgumentParser(description='Console bar plot')
    args.add_argument('--columns', default=60, type=int, metavar='N')
    return args.parse_args()

def load_input(inp):
    values = []
    for line_raw in inp:
        line = line_raw.strip()
        if line.startswith('#') or not line:
            continue
        try:
            val = float(line)
        except ValueError:
            print(f"WARNING: ignoring invalid line '{line}'.", file=sys.stderr)
            continue
        values.append(val)
    return values

def print_barplot(values, scale, symbol):
    for val in values:
        print(symbol * round(val / scale))

def main():
    config = parse_config()
    values = load_input(sys.stdin)
    if not values:
        sys.exit(0)
    coef = max(values) / config.columns
    print_barplot(values, coef, '#')

if __name__ == '__main__':
    main()

Poznámky k úloze na Shellové skriptování

Informace pro zapsané na speciální úterní cvičení 24bNSWI177x15.

Pokud váš SIS/GitLab-ový login začíná na [a-j], přijďte, prosím, v 8.45; pokud váš login začíná na [k-z], prosím, přijďte v 9.40.

Následující seznam zachycuje témata (konstrukty, příkazy, …) které byste měli znát ke zkoušce. Seznam není vyčerpávající (například neuvádíme všechny příkazy z našeho mini manuálu ale pokrývá všechny hlavní části.

  • Vytvoření krátké pipeline se základními nástroji jako cut, uniq, paste, bc nebo sort.
  • Používat přesměrování vstupu/výstupu.
  • Iterace skrz řádky souboru pomocí while read ...; do ...; done < input.txt.
  • Použití konstrukce if, for a while.
  • Použití test nebo [ pro ovládání smyček a podmínek v shellu.
  • Zachycení standardního výstupu skrze $( cmd ).
  • Vkládat externí skripty pomocí source or . (tečka).
  • Použít proměnné a funkce v shellu, abyste lépe zachytili tok dat.
  • Chápat zpracování argumentů pomocí getopts.
  • Využití základních regulárních výrazů pro vyhledávání (grep) nebo triviální nahrazování (pomocí sed)

Své řešení budete opět odesílat přes repozitáře na gitolite3@linux.ms.mff.cuni.cz (opět ze školních strojů). Ujistěte se tedy, že si pamatujete základy Gitu (nebudete potřebovat větve, ale bez znalosti alespoň clone, commit a push řešení neodevzdáte).

Opět budete mít přístup k webu D3S s materiály ke cvičením a ke stroji linux.ms.mff.cuni.cz ale nebudete mít přístup ke GitLabu: prosím, naklonujte si vaše repozitáře včas (pokud je budete potřebovat).

Rady k nastavení Git jsou zmíněny výše.

Pokud to nebude výslovně povoleno, nemůžete během implementace přejít do jiného jazyka (například Python, AWK nebo PERL). Jinými slovy, není dovoleno odevzdat řešení jako python3 -c 'import sys; for line in sys.stdin ....

Formát zkoušky se bude řídit tímto vzorem. Obdržíte téměř kompletní řešení určitého úkolu. Vaším úkolem bude implementovat chybějící funkce k dokončení úkolu.

Zadání bude rozděleno do různých funkcí shellu, které budete implementovat. Poskytneme vám několik základních (automatizovaných) testů, které budou kontrolovat správnost jednotlivých funkcí (tj. i když se doporučuje přečíst si celý skript, abyste pochopili jeho účel, bude možné některé funkce implementovat izolovaně).

AKTUALIZACE: pokud si naklonujete gitolite3@linux.ms.mff.cuni.cz:t02-example tak získáte přístup ke kompletnímu příkladu ke zkoušce. Během písemky budeme pracovat s tímto kódem: pro každé cvičení bude ale zadání (a tedy v malé míře i kód) obsahovat drobné rozdíly.

Například, datový soubor může být rozdělen do více souborů (třeba podle ID cvičení), můžeme chtít tisknout e-mail místo loginu nebo generovat HTML místo Markdownu (tj. třeba přidat rouru skrz Pandoc).

Prosím, využijte tuto příležitost se s kódem seznámit (základ bude vždy stejný) nebo se podívat, jak fungují testy. Může vám to ušetřit nějaký čas při písemce a dovolit vám se ihned zaměřit na to důležité místo luštění, kde jsou které soubory.

Zatímco kód v repozitáři t02-example bude použit v písemce, příklad níže může být použit pro další procvičování.

Příkladem úkolu je vytvoření shellového skriptu, který vytvoří histogram. Nejprve vytvoříme data (od nás pochopitelně budete mít vzorová data):

mkdir data
for i in $( seq 1 100 ); do echo $(( i % 6 + i % 2 )) > data/$i.txt; done

Skript pak bude spuštěn takto:

./histogram.sh data/*.txt

A vytiskne následující:

    0   ################
    2   ##################################
    4   ##################################
    6   ################

A vy obdržíte následující kód s pokyny pro implementaci funkcí summarize_input, repeat_char a rozšíření make_histogram.

#!/bin/bash

set -ueo pipefail

# Spočítá počet výskytů vstupních řádků.
# Argumenty: žádné
# Vstup: HODNOTY
# Výstup: HODNOTA POČET na řádkách
#
# Můžeme bezpečně předpokládat, že řádky jsou identifikátory bez mezer.
#
# Příklad:
#  Vstup:
#    4
#    5
#    4
#  Výstup:
#    4 2
#    5 1
summarize_input() {
    # FIXME: shrnout vstup do správného formátu
    cat "$@"
}

# Zopakujte znak vícekrát.
# Argumenty: SYMBOL POČET
# Výstup: SYMBOL opakovaný POČET krát na stdout.
repeat_char() {
    # FIXME: tisknout podle vstupních argumentů
    echo "===="
}

# Vykreslí histogram.
# Vstup: řádky, každá řádka obsahuje pár HODNOTA POČET
# Výstup: Jednoduchý histogram, podívejte se na přesný formát u printf.
make_histogram() {
    local value
    local count

    # FIXME: iterovat přes všechny řádky (zachovejte formát tak, jak je!)
    read value count
    printf '%5s\t%s\n' "$value" "$( repeat_char '#' "$count" )"
}

main() {
    cat "$@" | summarize_input | make_histogram
}

main "$@"

Kvízy

Kvízy budou na cvičeních 02, 03, 04, 05, 06 a 07.

Malé domácí úkoly

Velký domácí úkol: nastavení projektu

Nastavte CI pro Pythoní projekt a připravte ho na další distribuci. To zahrnuje následující úkoly (detaily vizte níže).

  • Převeďte zdroják na řádný Pythoní balíček.
  • Vytvořte GitLabový CI job pro pytest (po přimergování implementace a oprav).
  • Vytvořte GitLabový CI job pro BATS testy (po několika opravách a dalším Git merge).

Očekáváme, že k odstartování své implementace použijete externí nástroje, ale před odevzdáním musíte rozumět celému skriptu a musíte označit všechny části, které jste osobně nenapsali (a pokud používáte nástroje, jako je ChatGPT, musíte odeslat celý protokol komunikace s tímto nástrojem).

Kontext

V této úloze budete pracovat na jednoduchém Pythoním projektu, který je schopen vykreslovat Jinja šablony (instalujte balíček Jinja2, ne Jinja).

Jako jednoduchý příklad (který také najdete ve složce examples ve vašem repozitáři s projektem) může posloužit následující transformace.

Mějme následující pole (seznam) v JSONu:

[
  {
     "name": "Introduction to Linux",
     "code": "NSWI177",
     "homepage": "https://d3s.mff.cuni.cz/teaching/nswi177/"
  },
  {
     "name": "Operating Systems",
     "code": "NSWI200",
     "homepage": "https://d3s.mff.cuni.cz/teaching/nswi200/"
  }
]

Mějme následující vstupní soubor:

Our courses
===========

Below is a list of (almost) all of our courses.

A budeme mít tuto šablonu. Všimněte si, že řídící struktury šablony používají {% (nebo {%- pokud chceme odstranit okolní prázdné znaky) a {{ pro nahrazování proměnných.

{{ content }}

{%- for course in data -%}
 * [{{ course.name }} ({{ course.code }})]({{ course.homepage }}) {{ NL }}
{%- endfor %}

Očekáváme, že náš šablonovač (konkrétní příkaz je v README) po spuštění vypíše následující.

Our courses
===========

Below is a list of (almost) all of our courses.

* [Introduction to Linux (NSWI177)](https://d3s.mff.cuni.cz/teaching/nswi177/)
* [Operating Systems (NSWI200)](https://d3s.mff.cuni.cz/teaching/nswi200/)

Zdrojový kód

Zdrojáky výše uvedené implementace jsou pro vás již připravené a brzy budete mít přístup k novému projektu v podstromu teaching/nswi177/2025 na GitLabu, kde budete pracovat.

Nekopírujte tento kód do vašeho obvyklého repozitáře a pracujete jen s repozitářem project-LOGIN (s výjimkou ai.log jak je zmíněno níže).

Repozitář též obsahuje několik testů. Jsou tam unit testy v Pythonu (používající pytest) a také testy na vyšší úrovni (budeme jim říkat integrační ač je to trochu přehnané) napsané v BATSu.

Spuštění je popsáno v README projektu.

Commitujte pouze soubory, které jsou potřeba. Určitě nemá smysl commitovat adresáře virtual environmentu, podadresáře __pycache__ nebo Pythoní .egg a .whl soubory.

Zadání

Váš hlavní úkol je nastavit tomuto projektu základní CI na GitLabu a připravit ho pro distribuci.

CI musí spustit Pythoní unit testy a skončit chybou při jakémkoliv problému. Přípravou na distribuci míníme to, že po vašich změnách půjde šablonovač nainstalovat pomocí pipu a mít ho dostupný příkazem nswi177-jinja-templater.

Vaším úkolem není projekt dostat na PyPI ale pouze nastavit repozitář na GitLabu.

Jinými slovy, následující příkazy nainstalují šablonovač do nového virtuálního prostředí a spuštění posledního příkazu vypíše krátkou nápovědu k našemu programu (předpokládáme, že jsme v prázdném adresáři, který nijak nesouvisí s klonem projektu).

python3 -m venv templater-venv
. ./templater-venv/bin/activate
pip install git+ssh://git@gitlab.mff.cuni.cz/teaching/nswi177/2025/project-LOGIN
nswi177-jinja-templater --help

A pro CI očekáváme, že váš projekt bude mít úlohu unittests, která spouští Pythoní testy.

Prosím, dbejte na to, aby se CI job skutečně jmenoval unittests a umístěte veškerou konfiguraci do jediného .gitlab-ci.yml souboru.

CI by mělo používat obraz python:3.13-alpine a měli byste instalovat verze z requirements.txt souboru. Očekáváme, že pytest (a možná další knihovny potřebné pro testy) nebudou v requirements.txt, ale raději uvnitř souboru requirements-dev.txt.

Určitě si všimnete, že testy neprocházejí, protože některé z Jinja filtrů nejsou naimplementovány.

Ale nestrachujte se. Vaše kolegyně Alice je už naimplementovala ve své větvi v repozitáři gitolite3@linux.ms.mff.cuni.cz:templater-alice.

Zaintegrujte (merge) její implementaci do vašeho repozitáře, abyste měli implementaci kompletní.

Mergování je povinnou částí úlohy a očekáváme, že provedete normální merge (možná jen fast-forward) a nikdy neprovedete tzv. rebase.

Pokud jste vše udělali správně, váš CI log bude vypadat zhruba takto (ze zřejmých důvodů jsou použité příkazy rozmazané).

Poté rozšíříte CI tak, aby též spouštělo BATS testy.

Očekáváme, že přidáte nový job nazvaný integrationtests, který nainstaluje daný balíček (takže bude fungovat příkaz nswi177-jinja-templater) a spustí všechny BATS testy z podadresáře tests (jak si asi vzpomínáte, tak pouhé pip install . by mělo zafungovat úplně skvěle).

Pro unittests byste měli instalovat závislosti z requirements.txt pro co nejlepší reprodukovatelnost, zatímco pro integrationtests instalujeme celý balíček, čili typicky z volnějšími požadavky na přesné verze závislostí.

Budete muset nejdřív doinstalovat bats pomocí apk add (je v pořádku instalovat tento balíček při každém spuštění CI).

Všimněte si, že současná implementace v common.bash volá program pomocí env PYTHONPATH=src python3 -m nswi177.templater – zmeňte volání jen na nswi177-jinja-templater. Také budete muset nahradit volbu --kill-after za -k v příkazu timeout, protože dlouhá varianta není na Alpine podporována.

Množství BATS testů není příliš velké, takže byste také měli přimergovat práce od kolegů Boba a Charlieho do vašeho repozitáře. Jako obvykle, proveďte normální merge a nikoliv rebase při slučování jejich práce.

Bob má repozitář na gitolite3@linux.ms.mff.cuni.cz:templater-bob zatímco Charlie dal svojí kopii na náš web na https://d3s.mff.cuni.cz/f/teaching/nswi177/202425/templater-charlie.git.

V případě konfliktů se ujistěte, že jste je vyřešili rozumně – rozhodně nechcete žádný z testů mazat, pokud nejsou úplně stejné.

Abychom shrnuli podčásti k řešení, možná vám pomůže tento seznam.

  • Přimergujte implementaci od Alice.
  • Nastavte pyproject.toml, setup.cfg a requirements.txt (a requirements-dev.txt) pro projekt project-login na GitLabu.
  • Nastavit CI na GitLabu tak, aby spouštělo Pythoní testy v úloze (job) unittests.
  • Přimergujte testy od Boba a Charlieho.
  • Opravte spuštění příkazu v BATS testech.
  • Opravte volání timeout, aby bylo timeout -k 30 "${timeout}" "$@".
  • Přidejte CI job integrationtests, který spustí všechny BATS testy.

Odevzdání a hodnocení

Odevzdejte svá řešení do repozitáře project-LOGIN na GitLabu.

Budeme kontrolovat, že projekt jde nainstalovat pomocí pip install git+https://gitlab.../project-LOGIN/ a že vaše konfigurace CI je v pořádku (po všech mergech by se mělo vše zelenat). Zkontrolujeme, že Pythoní kód může být spuštěn pomocí python3 -m src.nswi177.templater po instalaci závislostí skrz pip install -r requirements.txt (nebo pomocí python -m nswi177.templater pokud je přímo samotný balík také nainstalovaný) a že Pytesty mohou být spuštěny po instalaci z requirements-dev.txt.

Při kopírování fragmentů ze stránek, jako je StackOverflow, očekáváme, že je okomentujete přímo v příslušných zdrojácích. Komunikaci se stránkami řízenými umělou inteligencí uložte do souboru exam/project/ai.log ve vašem obvyklém repozitáři (student-LOGIN), opět jako textový soubor s jasně označenými částmi s vašimi vstupy a s odpověďmi.

Termín odevzdání je 2025-06-01.

Pro tuto úlohu nejsou k dispozici automatické testy: konec konců, vy máte nastavit testování pro projekt.

Prosím, ujistěte se tedy (třeba pomocí seznamu výše), že jste na žádnou část nezapomněli. V zadání nejsou žádné skryté pasti nebo triková řešení, jen je potřeba splnit všechny části zadání.