diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 03a5caf..5f1cdd2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,25 +28,25 @@ jobs: check_clang_format: name: "Check C++ style" - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v3 - name: Install clang run: | wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh - sudo ./llvm.sh 17 - sudo apt-get install clang-format-17 + sudo ./llvm.sh 18 + sudo apt-get install clang-format-18 - name: "Clang-format libtermbench" - run: find ./libtermbench -name "*.cpp" -o -name "*.h" | xargs clang-format-17 --Werror --dry-run + run: find ./libtermbench -name "*.cpp" -o -name "*.h" | xargs clang-format-18 --Werror --dry-run - name: "Clang-format tb" - run: find ./tb -name "*.cpp" -o -name "*.h" | xargs clang-format-17 --Werror --dry-run + run: find ./tb -name "*.cpp" -o -name "*.h" | xargs clang-format-18 --Werror --dry-run - name: "Check includes" run: ./scripts/check-includes.sh ubuntu_linux: - name: "Ubuntu Linux 22.04" - runs-on: ubuntu-22.04 + name: "Ubuntu Linux 24.04" + runs-on: ubuntu-24.04 env: CMAKE_PRESET: "linux-gcc-release" steps: @@ -54,7 +54,7 @@ jobs: - name: ccache uses: hendrikmuhs/ccache-action@v1 with: - key: "ccache-ubuntu_2204" + key: "ccache-ubuntu_2404" max-size: 256M - name: set environment variables id: set_vars @@ -67,18 +67,18 @@ jobs: sudo apt -q update sudo apt install -qy ninja-build sudo ./scripts/install-deps.sh - - name: "Install GCC 13" - run: sudo apt install g++-13 + - name: "Install GCC" + run: sudo apt install g++ - name: "cmake" - run: cmake --preset "$CMAKE_PRESET" -D CMAKE_CXX_COMPILER="g++-13" + run: cmake --preset "$CMAKE_PRESET" -D CMAKE_CXX_COMPILER="g++" - name: "build" run: cmake --build --preset "$CMAKE_PRESET" --preset -- -j3 - name: "install dependencies for running benchmarks" run: ./scripts/xvfb-deps.sh - name: "Install contour" run: | - wget https://github.com/contour-terminal/contour/releases/download/v$CONTOUR_VERSION/contour-$CONTOUR_VERSION-ubuntu22.04-amd64.deb - sudo dpkg -i contour-$CONTOUR_VERSION-ubuntu22.04-amd64.deb + wget https://github.com/contour-terminal/contour/releases/download/v$CONTOUR_VERSION/contour-$CONTOUR_VERSION-ubuntu24.04-amd64.deb + sudo dpkg -i contour-$CONTOUR_VERSION-ubuntu24.04-amd64.deb - name: "create and patch contour.yml config file" run: | set -ex diff --git a/README.md b/README.md index eeecce1..71c288a 100644 --- a/README.md +++ b/README.md @@ -13,15 +13,30 @@ benefit from this library, if not even integrating it. Adding a C-API binding is considered as soon there is also interest from other projects that cannot use the C++ API. + +## Run tests +To run tests you need to spawn `tb` executable from terminal, for example: +` contour $(pwd)/build/tb/tb --fixed-size --column-by-column --size 2 --output contour_results` +for more info run `tb --hlep` +In folder scripts you can find some convinent scripts for testing different terminals and way to create results afterwards, +you can run + +``` sh +./scripts/Xvfb-bench-run.sh $(pwd)/build/tb/tb +julia scripts/plot_results.jl +``` + +This will run benchmark in background and plot results with julia afterwards + ## Test coverage - [x] long text lines - [x] short text lines - [x] text lines with foreground color - [x] text lines with foreground & background color -- [ ] cursor movement (`CUB`, `CUD`, `CUF`, `CUP`, `CUU`) +- [x] cursor movement (`CUB`, `CUD`, `CUF`, `CUP`, `CUU`) - [ ] rectangular operations (`DECCRA`, `DECFRA`, `DECERA`) -- [ ] insert lines/columns (`IL`, `DECIC`) +- [x] insert lines/columns (`IL`, `DECIC`) - [ ] delete lines (`DL`) - [ ] erase lines/columns (`EL`, `ED`) - [ ] complex unicode LTR diff --git a/libtermbench/termbench.cpp b/libtermbench/termbench.cpp index 9f30fdc..e8011e7 100644 --- a/libtermbench/termbench.cpp +++ b/libtermbench/termbench.cpp @@ -106,8 +106,8 @@ void Benchmark::runAll() void Benchmark::summarizeToJson(std::ostream& os) { - std::string buffer = glz::write_json(results_); - os << buffer; + auto buffer = glz::write_json(results_); + os << buffer.value(); } void Benchmark::summarize(std::ostream& os) @@ -416,14 +416,14 @@ std::unique_ptr binary() std::unique_ptr ascii_line(size_t line_length) { - auto name = std::to_string(line_length) + " chars per line"; + auto name = std::to_string(line_length) + "_chars_per_line"; auto text = std::string(line_length, 'a') + std::string { "\n" }; return std::make_unique(name, text); } std::unique_ptr sgr_line(size_t line_length) { - auto name = std::to_string(line_length) + " chars with sgr per line"; + auto name = std::to_string(line_length) + "_chars_with_sgr_per_line"; std::string text {}; text += "\033[38;2;20;200;200m"; text += std::string(line_length, 'a'); @@ -434,7 +434,7 @@ std::unique_ptr sgr_line(size_t line_length) std::unique_ptr sgrbg_line(size_t line_length) { - auto name = std::to_string(line_length) + " chars with sgr and bg per line"; + auto name = std::to_string(line_length) + "_chars_with_sgr_and_bg_per_line"; std::string text {}; text += "\033[38;2;20;200;200m\033[48;2;100;100;100m"; text += std::string(line_length, 'a'); @@ -445,7 +445,7 @@ std::unique_ptr sgrbg_line(size_t line_length) std::unique_ptr unicode_simple(size_t line_length) { - auto name = std::to_string(line_length) + " unicode simple"; + auto name = std::to_string(line_length) + "_unicode_simple"; std::string text {}; for (size_t i = 0; i < line_length; ++i) text += "\u0061"; @@ -455,7 +455,7 @@ std::unique_ptr unicode_simple(size_t line_length) std::unique_ptr unicode_two_codepoints(size_t line_length) { - auto name = std::to_string(line_length) + " unicode diacritic"; + auto name = std::to_string(line_length) + "_unicode_diacritic"; std::string text {}; for (size_t i = 0; i < line_length; ++i) text += "\u0061\u0308"; @@ -465,7 +465,7 @@ std::unique_ptr unicode_two_codepoints(size_t line_length) std::unique_ptr unicode_three_codepoints(size_t line_length) { - auto name = std::to_string(line_length) + " unicode double diacritic"; + auto name = std::to_string(line_length) + "_unicode_double_diacritic"; std::string text {}; for (size_t i = 0; i < static_cast(line_length / 2); ++i) text += "\u0061\u035D\u0062"; @@ -473,29 +473,49 @@ std::unique_ptr unicode_three_codepoints(size_t line_length) return std::make_unique(name, text); } -std::unique_ptr unicode_fire_as_text(size_t line_length) +std::unique_ptr unicode_fire(size_t line_length) { - auto name = std::to_string(line_length) + " unicode fire as text"; + auto name = std::to_string(line_length) + "_unicode_fire"; std::string text {}; for (size_t i = 0; i < static_cast(line_length / 2); ++i) - text += std::string { "\U0001F525\U0000FE0E" }; + text += std::string { "\U0001F525" }; text += std::string { "\n" }; return std::make_unique(name, text); } -std::unique_ptr unicode_fire(size_t line_length) +/* Creates rectangular block: + * u --- f + * | | + * b --- d + * with each side being line_length long. + * */ +std::unique_ptr vt_movement(size_t line_length) { - auto name = std::to_string(line_length) + " unicode fire"; + auto name = std::to_string(line_length) + "_vt_movement"; std::string text {}; - for (size_t i = 0; i < static_cast(line_length / 2); ++i) - text += std::string { "\U0001F525" }; + text += std::format("\033[{}Au\033[1D", line_length); // up + text += std::format("\033[{}Cf\033[1D", line_length); // forward + text += std::format("\033[{}Bd\033[1D", line_length); // down + text += std::format("\033[{}Db\033[1D", line_length); // backward + text += std::string { "\n" }; + return std::make_unique(name, text); +} + +/* Inserts lines and columns + */ +std::unique_ptr vt_insert(size_t line_length) +{ + auto name = std::to_string(line_length) + "_vt_insert"; + std::string text {}; + text += std::format("\033[{}L", line_length); // insert lines IL + text += std::format("\033[{}{}", line_length, "'}"); // insert columns DECIC text += std::string { "\n" }; return std::make_unique(name, text); } std::unique_ptr unicode_flag(size_t line_length) { - auto name = std::to_string(line_length) + " unicode flag"; + auto name = std::to_string(line_length) + "_unicode_flag"; std::string text {}; std::string flag {}; flag += "\U0001F3F4"; diff --git a/libtermbench/termbench.h b/libtermbench/termbench.h index 1af9fdd..c172491 100644 --- a/libtermbench/termbench.h +++ b/libtermbench/termbench.h @@ -164,10 +164,11 @@ std::unique_ptr ascii_line(size_t); std::unique_ptr sgr_line(size_t); std::unique_ptr sgrbg_line(size_t); std::unique_ptr unicode_simple(size_t); +std::unique_ptr vt_movement(size_t); +std::unique_ptr vt_insert(size_t); std::unique_ptr unicode_two_codepoints(size_t); std::unique_ptr unicode_three_codepoints(size_t); std::unique_ptr unicode_flag(size_t); -std::unique_ptr unicode_fire_as_text(size_t); // U+FEOE std::unique_ptr unicode_fire(size_t); std::unique_ptr crafted(std::string name, std::string description, std::string text); } // namespace termbench::tests diff --git a/scripts/Xvfb-bench-run.sh b/scripts/Xvfb-bench-run.sh index 2d03c4a..9649681 100755 --- a/scripts/Xvfb-bench-run.sh +++ b/scripts/Xvfb-bench-run.sh @@ -49,9 +49,12 @@ function program_exit() { function bench_terminal() { printf "\033[1m==> Running terminal: $1\033[m\n" local terminal_name=$(basename $1) - time "${@}" -e "${TB_BIN}" --fixed-size --column-by-column --size 2 --output "${OUTPUT_DIR}/${terminal_name}_results" + time "${@}" -e "${TB_BIN}" --fixed-size --column-by-column --size 1 --output "${OUTPUT_DIR}/${terminal_name}_results" local exit_code=$? printf "\033[1m==> Terminal exit code: $exit_code\033[m\n" + if [[ $exit_code -ne 0 ]]; then + program_exit $exit_code + fi } set -x diff --git a/scripts/plot_results.jl b/scripts/plot_results.jl index 6088719..a6d98d0 100644 --- a/scripts/plot_results.jl +++ b/scripts/plot_results.jl @@ -1,6 +1,7 @@ using Pkg Pkg.add("CairoMakie") Pkg.add("JSON") +Pkg.instantiate() using CairoMakie using JSON @@ -20,23 +21,25 @@ end function get_values(data, data_type) if data_type == :ascii - name = "chars per line" + name = "chars_per_line" elseif data_type == :sgr - name = "chars with sgr per line" + name = "chars_with_sgr_per_line" elseif data_type == :sgr_bg - name = "chars with sgr and bg per line" + name = "chars_with_sgr_and_bg_per_line" elseif data_type == :unicode - name = "unicode simple" + name = "unicode_simple" elseif data_type == :diacritic - name = "unicode diacritic" + name = "unicode_diacritic" elseif data_type == :diacritic_double - name = "unicode double diacritic" + name = "unicode_double_diacritic" elseif data_type == :fire - name = "unicode fire" - elseif data_type == :fire_text - name = "unicode fire as text" + name = "unicode_fire" + elseif data_type == :vt_movement + name = "vt_movement" + elseif data_type == :vt_insert + name = "vt_insert" elseif data_type == :flag - name = "unicode flag" + name = "unicode_flag" end lines = Vector{Float64}() @@ -67,14 +70,14 @@ function generate_for_terminal(file_name, prefix="results_") data = get_data(file_name) - markers = [:circle :rect :cross :star4 :start5 :star6 :diamond] + markers = [:circle :rect :cross :star4 :star5 :star6 :diamond] get_values_l = (type) -> get_values(data,type) speed = [ get_values_l(t) for t in types] marker_size = 8 for (ind,dat) in enumerate(speed) - scatter!(ax,dat, label= terminal_name * "_" * string(types[ind]), marker = markers[ind], markersize = marker_size) + scatter!(ax, dat,label= terminal_name * "_" * string(types[ind]), marker = markers[ind], markersize = marker_size) end axislegend(position = :rt) @@ -108,13 +111,21 @@ generate_for_terminal("alacritty_results") generate_for_terminal("xterm_results") generate_for_terminal("kitty_results") generate_for_terminal("wezterm_results") -types = [:unicode :fire :flag :diacritic :diacritic_double :fire_text] +types = [:unicode :fire :flag :diacritic :diacritic_double] generate_for_terminal_l = (n) -> generate_for_terminal(n, "results_unicode_") generate_for_terminal_l("contour_results") generate_for_terminal_l("alacritty_results") generate_for_terminal_l("xterm_results") generate_for_terminal_l("kitty_results") generate_for_terminal_l("wezterm_results") +types = [:vt_movement :vt_insert] +generate_for_terminal_l = (n) -> generate_for_terminal(n, "results_vt_") +generate_for_terminal_l("contour_results") +generate_for_terminal_l("alacritty_results") +generate_for_terminal_l("xterm_results") +generate_for_terminal_l("kitty_results") +generate_for_terminal_l("wezterm_results") + -types = [:ascii :sgr :sgr_bg :unicode :fire :fire_text :flag :diacritic :diacritic_double] +types = [:ascii :sgr :sgr_bg :unicode :fire :flag :diacritic :diacritic_double :vt_movement :vt_insert] [ save("comparison_"*string(type)*".png", generate_comparison(type)) for type in types ] diff --git a/tb/main.cpp b/tb/main.cpp index 46c7f75..8fa2cca 100644 --- a/tb/main.cpp +++ b/tb/main.cpp @@ -122,7 +122,7 @@ struct TestsToRun struct BenchSettings { TerminalSize requestedTerminalSize {}; - size_t testSizeMB = 32; + size_t testSizeMB = 1; bool nullSink = false; bool stdoutFastPath = false; std::vector craftedTests {}; @@ -252,11 +252,12 @@ bool addTestsToBenchmark(termbench::Benchmark& tb, BenchSettings const& settings add_test(termbench::tests::unicode_simple); add_test(termbench::tests::unicode_two_codepoints); add_test(termbench::tests::unicode_three_codepoints); - add_test(termbench::tests::unicode_fire_as_text); add_test(termbench::tests::unicode_fire); add_test(termbench::tests::unicode_flag); add_test(termbench::tests::sgr_line); add_test(termbench::tests::sgrbg_line); + add_test(termbench::tests::vt_movement); + add_test(termbench::tests::vt_insert); } return true; }