feat: pattern support args and multiple variants; add zed extension for highlight
All checks were successful
build-dsl-smoke / Build judge (push) Successful in 13s
build-dsl-smoke / debug / clang / linux (push) Successful in 6s
build-dsl-smoke / debug / gcc / linux (push) Successful in 8s
build-dsl-smoke / release / clang / linux (push) Successful in 9s
build-dsl-smoke / release / gcc / linux (push) Successful in 7s
build-dsl-smoke / sanitized / clang / linux (push) Successful in 8s
build-dsl-smoke / sanitized / gcc / linux (push) Successful in 7s
build-dsl-smoke / debug / clang / windows (push) Successful in 16s
build-dsl-smoke / debug-valgrind / gcc / linux (push) Successful in 14s
build-dsl-smoke / debug / msvc / windows (push) Successful in 18s
build-dsl-smoke / release / clang / windows (push) Successful in 17s
build-dsl-smoke / release / msvc / windows (push) Successful in 17s
build-dsl-smoke / SUMMARY (push) Successful in 5s

This commit is contained in:
2026-04-11 14:37:43 +03:00
parent dacae83dc6
commit 7f9f6a0a6e
29 changed files with 11429 additions and 94 deletions

View File

@@ -1,11 +1,20 @@
// Автогенерация тестов из папки с файлами. Удобно когда тестов много и
// вручную выписывать каждый через test("...") { stdin = ... stdout = ... }
// будет слишком громоздко.
// Автогенерация тестов из файлов/папок. Покрывает четыре типовых сценария:
//
// Два режима:
// 1) file-glob — пары .in/.ans файлов
// 2) dir-mode — каждый тест лежит в своей подпапке с фиксированными
// именами input/output файлов
// 1. Stdio-режим с парой globs — классика: stdin из .in, stdout = .ans
// 2. Shared expected — N входов, один общий ожидаемый файл
// 3. File-mode по args — программа читает файл по аргументу
// 4. Dir-mode с input+output файлами — программа читает И пишет файлы
//
// Плейсхолдеры в `args` pattern'а:
// {input_path} — путь к input-файлу текущего теста (для glob — разный,
// для литерала — один и тот же во всех тестах)
// {output_path} — аналогично для output
// {name} — wildcard-часть имени (glob) или basename директории (dir)
// {dir} — dir-mode: полный путь к директории теста
//
// Правило режима: наличие `{input_path}` в args → input кладётся как InFile,
// а не в stdin. Наличие `{output_path}` → expected сравнивается как OutFile,
// а не stdout.
toolchains {
gcc { platforms = "linux" }
@@ -19,11 +28,10 @@ build "release" {
profile = release
}
// Режим 1: глобы на input и output файлы.
// Тестом становится каждая пара (tests/*.in, tests/*.ans) с совпадающим
// базовым именем. Имя теста — имя файла без расширения.
group("from-files") {
weight = 0.5
// 1) Классика: каждая пара (*.in, *.ans) → один тест.
// Stdin ← .in, Stdout сравнивается с .ans.
group("stdio-pair") {
weight = 0.25
pattern {
input = "tests/*.in"
@@ -31,22 +39,42 @@ group("from-files") {
}
}
// Режим 2: каждый тест — подкаталог с фиксированным layout'ом.
// Ожидается структура:
// cases/
// 01-basic/
// input.txt
// expected.txt
// 02-edge/
// input.txt
// expected.txt
// Имя теста — имя подкаталога.
group("from-dirs") {
weight = 0.5
// 2) Один общий expected для всех входов.
// Удобно для задач где «для любого корректного входа ответ одинаковый»
// (edge-case fuzzing) или наоборот «все некорректные входы → error»
// (смотрим на один и тот же файл с сообщением об ошибке).
group("shared-output") {
weight = 0.25
pattern {
dirs = "cases/*"
input = "input.txt"
output = "expected.txt"
input = "edge/*.in"
output = "edge/expected.ans" // литерал без *
}
}
// 3) Программа читает файл по аргументу командной строки, а не из stdin.
// Expander создаёт InFiles[01.in]=..., запускает `./solution 01.in`,
// сравнивает stdout программы с содержимым соответствующего .ans.
group("file-input") {
weight = 0.25
pattern {
input = "file-tests/*.in"
output = "file-tests/*.ans"
args = "{input_path}"
}
}
// 4) Программа и читает, и пишет через файлы — никакого stdin/stdout.
// Expander кладёт input в InFiles, expected в OutFiles, запускает
// `./solution in.txt out.txt` и сравнивает созданный out.txt с expected.
group("file-io") {
weight = 0.25
pattern {
dirs = "cases/*" // каждая подпапка — отдельный тест
input = "in.txt"
output = "out.txt"
args = "{input_path}" "{output_path}"
}
}

View File

@@ -0,0 +1,41 @@
// Наследование общей конфигурации через `include`. Подключает соседний
// common.jdg (тулчейны + build_defaults + глобальные настройки), а затем
// задаёт только специфичные для этой задачи build-варианты и тесты.
//
// Пути в include относительны самому этому файлу (не CWD, не корню репо).
// Абсолютные пути тоже работают. Циклические включения детектятся парсером.
//
// Локальные директивы поверх include могут переопределять:
// - скаляры в build_defaults (через последующий build_defaults-блок)
// - timeout / memory_limit / binary / sources / normalize_crlf / trim_trailing_ws
// Но не могут переопределять:
// - toolchains с тем же именем (ошибка «duplicate toolchain»)
// - build с тем же именем
// - group с тем же именем
include "common.jdg"
build "release" {
profile = release
}
build "debug" {
profile = debug
warnings = pedantic
}
build "sanitized" {
profile = sanitized
sanitize = "address" "undefined"
platforms = "linux"
compilers = "gcc" "clang"
}
group("basic") {
weight = 1.0
test("smoke") {
stdin = "1\n42\n"
stdout = "42\n"
}
}

View File

@@ -0,0 +1,22 @@
// Общая инфраструктура для всех задач курса: тулчейны и базовые настройки
// билда. Подключается через `include "common.jdg"` из конкретных .jdg
// файлов задач. Локальные build-блоки наследуют эти дефолты через
// встроенный merge в build_defaults.
toolchains {
gcc { platforms = "linux" }
clang { platforms = "linux" "windows" }
msvc { platforms = "windows" }
}
build_defaults {
language = "c"
standard = "c11"
sources = "solution.c"
output = "solution"
warnings = strict
}
timeout 5s
normalize_crlf = true
trim_trailing_ws = true