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
31 changes: 31 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1706,3 +1706,34 @@ if(GECODE_INSTALL)
endif()

set_property(GLOBAL PROPERTY USE_FOLDERS ON)

# Report resolved options after dependency checks and target creation.
include(FeatureSummary)
foreach(gecode_option IN ITEMS
GECODE_BUILD_SHARED GECODE_BUILD_STATIC
GECODE_ENABLE_THREAD GECODE_ENABLE_CPPROFILER GECODE_ENABLE_CBS
GECODE_ENABLE_EXAMPLES GECODE_INSTALL
GECODE_ENABLE_SEARCH GECODE_ENABLE_INT_VARS GECODE_ENABLE_SET_VARS
GECODE_ENABLE_FLOAT_VARS GECODE_ENABLE_MINIMODEL GECODE_ENABLE_DRIVER
GECODE_ENABLE_FLATZINC GECODE_ENABLE_ALLOCATOR GECODE_ENABLE_AUDIT
GECODE_ENABLE_FAULT_INJECTION GECODE_REGENERATE_VARIMP
GECODE_DOC_SEARCH GECODE_DOC_TAGFILE)
get_property(gecode_option_description CACHE ${gecode_option} PROPERTY HELPSTRING)
add_feature_info(${gecode_option} ${gecode_option} "${gecode_option_description}")
endforeach()
add_feature_info(GECODE_ENABLE_QT GECODE_HAS_QT_RUNTIME
"Qt support (requested: ${GECODE_ENABLE_QT})")
add_feature_info(GECODE_ENABLE_GIST GECODE_BUILD_GIST_TARGET
"Gist (requested: ${GECODE_ENABLE_GIST})")
add_feature_info(GECODE_ENABLE_MPFR GECODE_HAS_MPFR
"MPFR support (requested: ${GECODE_ENABLE_MPFR})")
add_feature_info(GECODE_ENABLE_GCC_VISIBILITY GECODE_GCC_HAS_CLASS_VISIBILITY
"GCC visibility attributes (requested: ${GECODE_ENABLE_GCC_VISIBILITY})")
add_feature_info(GECODE_ENABLE_OSX_UNFAIR_MUTEX GECODE_USE_OSX_UNFAIR_MUTEX
"macOS unfair mutexes (requested: ${GECODE_ENABLE_OSX_UNFAIR_MUTEX})")
add_feature_info(GECODE_DOC_DOT GECODE_DOXYGEN_DOT
"Graphviz dot graphs (requested: ${GECODE_DOC_DOT})")
add_feature_info(BUILD_TESTING "BUILD_TESTING;GECODE_CAN_BUILD_TESTS"
"Test targets (requested: ${BUILD_TESTING})")
feature_summary(WHAT ENABLED_FEATURES DISABLED_FEATURES
DESCRIPTION "Gecode ${GECODE_PROJECT_VERSION} configuration:")
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ from it.
Version metadata shared by autoconf and CMake lives in `gecode-version.m4`.
`build/` is reserved for generated build outputs.

Configuration ends with a summary of enabled and disabled features after
dependency checks. Qt, Gist, MPFR, compiler visibility, macOS mutexes, Graphviz
graphs, and test targets show their requested settings alongside the resolved
state.

| Autoconf switch | CMake option / mechanism | Status | Notes |
|---|---|---|---|
| `--enable-shared` | `GECODE_BUILD_SHARED` | Supported directly | Default `ON` |
Expand Down
72 changes: 45 additions & 27 deletions test/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#endif

#include <iostream>
#include <iomanip>

#include <cstdlib>
#include <cstring>
Expand Down Expand Up @@ -275,21 +276,32 @@ namespace Test {
}
}

/// Report test cases; iterations of a test count as one case.
void print_test_summary(size_t selected, size_t passed, size_t failed) {
const size_t ran = passed + failed;
std::cout << "\nTest summary: " << selected << " selected, "
<< ran << " ran, " << passed << " passed, "
<< failed << " failed, " << selected - ran << " not run."
<< std::endl;
}

/// Run all the tests with the supplied options.
int run_tests(const std::vector<Base*>& tests, const Options& options) {
Gecode::Support::RandomGenerator seed_sequence(options.seed);
int result = EXIT_SUCCESS;
size_t passed = 0;
size_t failed = 0;
for (auto test : tests) {
unsigned int test_seed = seed_sequence.next();
if (!run_test(test, test_seed, options, std::cout)) {
if (opt.stop) {
return EXIT_FAILURE;
} else {
result = EXIT_FAILURE;
}
if (run_test(test, test_seed, options, std::cout)) {
++passed;
} else {
++failed;
if (options.stop)
break;
}
}
return result;
print_test_summary(tests.size(), passed, failed);
return failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

class TestExecutor;
Expand All @@ -306,8 +318,9 @@ namespace Test {
Gecode::Support::Mutex output_mutex;
/// The next starting index among the tests.
std::atomic<size_t> next_tests;
/// The result
std::atomic<int> result;
/// Completed test cases
std::atomic<size_t> passed;
std::atomic<size_t> failed;
/// The number of test runners that are to be set up.
std::atomic<int> running_threads;
/// Flag indicating some thread is waiting on the execution to be done.
Expand All @@ -332,13 +345,14 @@ namespace Test {
public:
TestExecutionControl(const std::vector<Base*>& tests0, const Options& options0, int thread_count)
: tests(tests0), options(options0), output_mutex(),
next_tests(0), result(EXIT_SUCCESS), running_threads(thread_count),
next_tests(0), passed(0), failed(0), running_threads(thread_count),
execution_done_wait_started(false), execution_done_event() {}

/// Get the current result (either \a EXIT_SUCCESS or \a EXIT_FAILURE). Requires all threads to be done first.
int get_result() {
/// Report the results after all threads have finished and return the exit status.
int report_result() {
assert(running_threads.load() == 0);
return result.load();
print_test_summary(tests.size(), passed.load(), failed.load());
return failed.load() == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

/** Wait for test-runners to be completed.
Expand All @@ -354,9 +368,12 @@ namespace Test {
execution_done_event.wait();
}
private:
/// Set flag that failure has occurred.
void set_failure() {
result.store(EXIT_FAILURE);
/// Record a completed test case.
void record_result(bool success) {
if (success)
++passed;
else
++failed;
}

/// Indicate that a thread is done executing.
Expand All @@ -378,7 +395,7 @@ namespace Test {
/// True iff the runners should continue running tests
bool continue_testing() {
// Note: implementation should be cheap to call form multiple threads often
return !options.stop || result.load() == EXIT_SUCCESS;
return !options.stop || failed.load() == 0;
}

/// Write a string to standard output, synchronized across all test runners
Expand Down Expand Up @@ -424,9 +441,7 @@ namespace Test {
auto test = tec.tests[i];
unsigned int test_seed = seed_sequence.next();
std::ostringstream test_output;
if (!run_test(test, test_seed, tec.options, test_output)) {
tec.set_failure();
}
tec.record_result(run_test(test, test_seed, tec.options, test_output));
tec.write_output(test_output.str());
}
if (!tec.continue_testing()) {
Expand All @@ -451,7 +466,7 @@ namespace Test {
}
tec.await_test_runners_completed();

return tec.get_result();
return tec.report_result();
}
}

Expand Down Expand Up @@ -489,11 +504,14 @@ main(int argc, char* argv[]) {
}
}

if (opt.threads > 1) {
return run_tests_parallel(tests, opt);
} else {
return run_tests(tests, opt);
}
Gecode::Support::Timer timer;
timer.start();
const int result = opt.threads > 1 ?
run_tests_parallel(tests, opt) : run_tests(tests, opt);
std::ostringstream elapsed;
elapsed << std::fixed << std::setprecision(3) << timer.stop() / 1000.0;
std::cout << "Elapsed time: " << elapsed.str() << " s." << std::endl;
return result;
}

std::ostream&
Expand Down
Loading