Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:

- name: Build Docs
run: |
make build-docs
make build-docs NUM_JOBS=$(nproc)

- name: Setup GitHub Pages
uses: actions/configure-pages@v5
Expand Down
22 changes: 13 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ CMAKE_CONFIGURE_EXTRA_ARGS ?=
CMAKE_BUILD_EXTRA_ARGS ?=
# gcc or clang
COMPILER ?= gcc
NUM_JOBS ?= $(shell echo $$(( $$(nproc) / 2 )))

ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))

Expand All @@ -28,6 +29,7 @@ DOCS_PRESET := unixlike-docs-only

SRC_ENV := if [ -f "$(ROOT_DIR)/.env" ]; then export $$(cat "$(ROOT_DIR)/.env" | xargs); echo "Set enviornment variables:"; sed -E 's/=.*//' "$(ROOT_DIR)/.env"; echo; fi


default: help

##### --- snipped from gh:compiler-explorer/compiler-explorer/blob/main/Makefile
Expand Down Expand Up @@ -64,34 +66,34 @@ build: build-debug ## alias for build-debug

.PHONY: build-debug
build-debug: configure-debug ## build in debug mode
@$(SRC_ENV) && cmake --build --preset $(DEBUG_PRESET) $(CMAKE_BUILD_EXTRA_ARGS)
@$(SRC_ENV) && cmake --build --preset $(DEBUG_PRESET) $(CMAKE_BUILD_EXTRA_ARGS) -j $(NUM_JOBS)

.PHONY: build-release
build-release: configure-release ## build in release mode (with debug info)
@$(SRC_ENV) && cmake --build --preset $(RELEASE_PRESET) $(CMAKE_BUILD_EXTRA_ARGS)
@$(SRC_ENV) && cmake --build --preset $(RELEASE_PRESET) $(CMAKE_BUILD_EXTRA_ARGS) -j $(NUM_JOBS)

.PHONY: build-docs
build-docs: configure-docs ## build in release mode (with debug info)
@$(SRC_ENV) && cmake --build --preset $(DOCS_PRESET) $(CMAKE_BUILD_EXTRA_ARGS)
@$(SRC_ENV) && cmake --build --preset $(DOCS_PRESET) $(CMAKE_BUILD_EXTRA_ARGS) -j $(NUM_JOBS)

.PHONY: build-tests-debug
build-tests-debug: configure-debug
@$(SRC_ENV) && cmake --build --preset $(DEBUG_PRESET) --target asmgrader_tests $(CMAKE_BUILD_EXTRA_ARGS)
@$(SRC_ENV) && cmake --build --preset $(DEBUG_PRESET) --target asmgrader_tests $(CMAKE_BUILD_EXTRA_ARGS) -j $(NUM_JOBS)

.PHONY: build-tests-release
build-tests-release: configure-release
@$(SRC_ENV) && cmake --build --preset $(RELEASE_PRESET) --target asmgrader_tests $(CMAKE_BUILD_EXTRA_ARGS)
@$(SRC_ENV) && cmake --build --preset $(RELEASE_PRESET) --target asmgrader_tests $(CMAKE_BUILD_EXTRA_ARGS) -j $(NUM_JOBS)

.PHONY: test
test: test-debug ## alias for test-debug

.PHONY: test-debug
test-debug: build-tests-debug ## run tests in debug mode
@$(SRC_ENV) && ctest --preset $(DEBUG_PRESET) --progress --output-on-failure --no-tests=error $(CTEST_EXTRA_ARGS)
@$(SRC_ENV) && ctest --preset $(DEBUG_PRESET) --progress --output-on-failure --no-tests=error $(CTEST_EXTRA_ARGS) -j $(NUM_JOBS)

.PHONY: test-release
test-release: build-tests-release ## run tests in release mode
@$(SRC_ENV) && ctest --preset $(RELEASE_PRESET) --progress --output-on-failure --no-tests=error $(CTEST_EXTRA_ARGS)
@$(SRC_ENV) && ctest --preset $(RELEASE_PRESET) --progress --output-on-failure --no-tests=error $(CTEST_EXTRA_ARGS) -j $(NUM_JOBS)


.PHONY: clean
Expand All @@ -107,8 +109,10 @@ deep-clean: ## remove all build files and configuration

.PHONY: list-opts
list-opts: ## list available CMake options
@if ! cmake -S . -B build/ -LAH -N 2>/dev/null \
| grep ASMGRADER_ -B 1 \
@if ! cmake -S . -B $(shell find build/ -maxdepth 1 -mindepth 1 | head -n1) -LAH -N 2>/dev/null \
| grep ASMGRADER_ --before-context 1 --group-separator='' \
| sed '/\/\// { s/^//; s/$$//; }' \
| sed '/^\w/ { s/^//; s/:/:/; }' \
; then \
printf '\033[31mError: CMake command failed. Is the project configured?\033[0m\n'; \
exit 1; \
Expand Down
2 changes: 2 additions & 0 deletions include/asmgrader/asmgrader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,7 @@
#include <variant> // IWYU pragma: export
#include <vector> // IWYU pragma: export

using namespace std::literals;

// should always include last if possible, as the short macro names may conflict with other libraries.
#include <asmgrader/api/test_macros.hpp> // IWYU pragma: export
2 changes: 1 addition & 1 deletion src/app/professor_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ int ProfessorApp::run_impl() {
std::shared_ptr output_serializer =
std::make_shared<PlainTextSerializer>(output_sink, OPTS.colorize_option, OPTS.verbosity);

MultiStudentRunner runner{*assignment, output_serializer};
MultiStudentRunner runner{*assignment, output_serializer, OPTS.tests_filter};

output_serializer->on_run_metadata(RunMetadata{});

Expand Down
2 changes: 1 addition & 1 deletion src/app/student_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ int StudentApp::run_impl() {
StdoutSink output_sink;
std::shared_ptr output_serializer =
std::make_shared<PlainTextSerializer>(output_sink, OPTS.colorize_option, OPTS.verbosity);
AssignmentTestRunner runner{*assignment, output_serializer};
AssignmentTestRunner runner{*assignment, output_serializer, OPTS.tests_filter};

output_serializer->on_run_metadata(RunMetadata{});
AssignmentResult res = runner.run_all(OPTS.file_name);
Expand Down
10 changes: 7 additions & 3 deletions src/multi_student_runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,23 @@
#include <fmt/compile.h>

#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

namespace asmgrader {

MultiStudentRunner::MultiStudentRunner(Assignment& assignment, const std::shared_ptr<Serializer>& serializer)
MultiStudentRunner::MultiStudentRunner(Assignment& assignment, const std::shared_ptr<Serializer>& serializer,
const std::optional<std::string>& tests_filter)
: assignment_{&assignment}
, serializer_{serializer} {}
, serializer_{serializer}
, filter_{tests_filter} {}

MultiStudentResult MultiStudentRunner::run_all_students(const std::vector<StudentInfo>& students) const {
MultiStudentResult result;

AssignmentTestRunner assignment_runner{*assignment_, serializer_};
AssignmentTestRunner assignment_runner{*assignment_, serializer_, filter_};

for (const StudentInfo& info : students) {
serializer_->on_student_begin(info);
Expand Down
6 changes: 5 additions & 1 deletion src/multi_student_runner.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,24 @@
#include "output/serializer.hpp"

#include <memory>
#include <optional>
#include <string>
#include <vector>

namespace asmgrader {

class MultiStudentRunner
{
public:
MultiStudentRunner(Assignment& assignment, const std::shared_ptr<Serializer>& serializer);
MultiStudentRunner(Assignment& assignment, const std::shared_ptr<Serializer>& serializer,
const std::optional<std::string>& tests_filter);

MultiStudentResult run_all_students(const std::vector<StudentInfo>& students) const;

private:
Assignment* assignment_;
std::shared_ptr<Serializer> serializer_;
std::optional<std::string> filter_;
};

} // namespace asmgrader
17 changes: 14 additions & 3 deletions src/test_runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "program/program.hpp"
#include "version.hpp"

#include <range/v3/view/filter.hpp>
#include <range/v3/view/map.hpp>

#include <filesystem>
Expand All @@ -23,9 +24,11 @@

namespace asmgrader {

AssignmentTestRunner::AssignmentTestRunner(Assignment& assignment, const std::shared_ptr<Serializer>& serializer)
AssignmentTestRunner::AssignmentTestRunner(Assignment& assignment, const std::shared_ptr<Serializer>& serializer,
const std::optional<std::string>& tests_filter)
: assignment_{&assignment}
, serializer_{serializer} {}
, serializer_{serializer}
, filter_{tests_filter} {}

AssignmentResult AssignmentTestRunner::run_all(std::optional<std::filesystem::path> alternative_path) const {
// Assignment name -> TestResults
Expand All @@ -36,7 +39,15 @@ AssignmentResult AssignmentTestRunner::run_all(std::optional<std::filesystem::pa
assignment_->set_exec_path(std::move(*alternative_path));
}

for (TestBase& test : assignment_->get_tests()) {
auto maybe_tests_filter = ranges::views::filter([this](const TestBase& test) -> bool {
if (!filter_.has_value()) {
return true;
}

return test.get_name().find(*filter_) != std::string::npos;
});

for (TestBase& test : assignment_->get_tests() | maybe_tests_filter) {
// Skip tests that are marked as professor-only if we're not in professor mode
if (test.get_is_prof_only() && APP_MODE != AppMode::Professor) {
continue;
Expand Down
5 changes: 4 additions & 1 deletion src/test_runner.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@
#include <filesystem>
#include <memory>
#include <optional>
#include <string>

namespace asmgrader {

/// Manages test execution and result aggregation for a specific assignment
class AssignmentTestRunner
{
public:
AssignmentTestRunner(Assignment& assignment, const std::shared_ptr<Serializer>& serializer);
AssignmentTestRunner(Assignment& assignment, const std::shared_ptr<Serializer>& serializer,
const std::optional<std::string>& tests_filter);

AssignmentResult run_all(std::optional<std::filesystem::path> alternative_path) const;

Expand All @@ -23,6 +25,7 @@ class AssignmentTestRunner

Assignment* assignment_;
std::shared_ptr<Serializer> serializer_;
std::optional<std::string> filter_;
};

} // namespace asmgrader
8 changes: 8 additions & 0 deletions src/user/cl_args.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,14 @@ void CommandLineArgs::setup_parser() {
.help("Whether/when to stop early, to not flood the console with failing test messages.");


arg_parser_.add_argument("--filter")
.metavar("STR")
.nargs(1)
.action([&] (const std::string& opt) {
opts_buffer_.tests_filter = opt;
})
.help("Filter for test cases to be run. Matching occurs if STR occurs anywhere within the test case name.");

arg_parser_.add_argument("-c", "--color")
.choices("never", "auto", "always")
.default_value(std::string{"auto"})
Expand Down
5 changes: 5 additions & 0 deletions src/user/program_options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ struct ProgramOptions
VerbosityLevel verbosity = DEFAULT_VERBOSITY_LEVEL;
std::string assignment_name;

/// Filter for test cases to be ran
/// Only very basic matching for now: simply checks whether the specified string exists anywhere
/// within the test case name.
std::optional<std::string> tests_filter;

/// Never = stop only on fatal errors
/// FirstError = stop completely on the first error encountered
/// EachTestError = stop each test early upon error, but still attempt to run subsequent tests
Expand Down
Loading